Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2022-01-22 21:43:09 +0300
committerKornel <kornel@geekhood.net>2022-01-22 21:43:09 +0300
commitc3529a41f527101f05e9e834a19205ee33a3b097 (patch)
tree2a76fa3119a75a39cf3ea7418877f53f1a64b7b4 /CPP/Windows/Control
parent52eeaf1ad614fcd03b48423009182e3e3d1ff694 (diff)
21.0721.07
Diffstat (limited to 'CPP/Windows/Control')
-rw-r--r--CPP/Windows/Control/Dialog.cpp228
-rw-r--r--CPP/Windows/Control/Dialog.h2
2 files changed, 192 insertions, 38 deletions
diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp
index 6a9d7d9b..9ddd2342 100644
--- a/CPP/Windows/Control/Dialog.cpp
+++ b/CPP/Windows/Control/Dialog.cpp
@@ -2,6 +2,8 @@
#include "StdAfx.h"
+// #include "../../Windows/DLL.h"
+
#ifndef _UNICODE
#include "../../Common/StringConvert.h"
#endif
@@ -88,23 +90,55 @@ bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */)
return true;
}
-static bool GetWorkAreaRect(RECT *rect)
+
+static bool GetWorkAreaRect(RECT *rect, HWND hwnd)
{
- // use another function for multi-monitor.
+ if (hwnd)
+ {
+ #ifndef UNDER_CE
+ /* MonitorFromWindow() is supported in Win2000+
+ MonitorFromWindow() : retrieves a handle to the display monitor that has the
+ largest area of intersection with the bounding rectangle of a specified window.
+ dwFlags: Determines the function's return value if the window does not intersect any display monitor.
+ MONITOR_DEFAULTTONEAREST : Returns display that is nearest to the window.
+ MONITOR_DEFAULTTONULL : Returns NULL.
+ MONITOR_DEFAULTTOPRIMARY : Returns the primary display monitor.
+ */
+ const HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
+ if (hmon)
+ {
+ MONITORINFO mi;
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ if (GetMonitorInfoA(hmon, &mi))
+ {
+ *rect = mi.rcWork;
+ return true;
+ }
+ }
+ #endif
+ }
+
+ /* Retrieves the size of the work area on the primary display monitor.
+ The work area is the portion of the screen not obscured
+ by the system taskbar or by application desktop toolbars.
+ Any DPI virtualization mode of the caller has no effect on this output. */
+
return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, 0, rect, 0));
}
-bool IsDialogSizeOK(int xSize, int ySize)
+
+bool IsDialogSizeOK(int xSize, int ySize, HWND hwnd)
{
// it returns for system font. Real font uses another values
- LONG v = GetDialogBaseUnits();
- int x = LOWORD(v);
- int y = HIWORD(v);
+ const LONG v = GetDialogBaseUnits();
+ const int x = LOWORD(v);
+ const int y = HIWORD(v);
RECT rect;
- GetWorkAreaRect(&rect);
- int wx = RECT_SIZE_X(rect);
- int wy = RECT_SIZE_Y(rect);
+ GetWorkAreaRect(&rect, hwnd);
+ const int wx = RECT_SIZE_X(rect);
+ const int wy = RECT_SIZE_Y(rect);
return
xSize / 4 * x <= wx &&
ySize / 8 * y <= wy;
@@ -159,46 +193,166 @@ bool CDialog::MoveItem(int id, int x, int y, int width, int height, bool repaint
return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint)));
}
+
+/*
+typedef BOOL (WINAPI * Func_DwmGetWindowAttribute)(
+ HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
+
+static bool GetWindowsRect_DWM(HWND hwnd, RECT *rect)
+{
+ // dll load and free is too slow : 300 calls in second.
+ NDLL::CLibrary dll;
+ if (!dll.Load(FTEXT("dwmapi.dll")))
+ return false;
+ Func_DwmGetWindowAttribute f = (Func_DwmGetWindowAttribute)dll.GetProc("DwmGetWindowAttribute" );
+ if (f)
+ {
+ #define MY__DWMWA_EXTENDED_FRAME_BOUNDS 9
+ // 30000 per second
+ RECT r;
+ if (f(hwnd, MY__DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK)
+ {
+ *rect = r;
+ return true;
+ }
+ }
+ return false;
+}
+*/
+
+
+static bool IsRect_Small_Inside_Big(const RECT &sm, const RECT &big)
+{
+ return sm.left >= big.left
+ && sm.right <= big.right
+ && sm.top >= big.top
+ && sm.bottom <= big.bottom;
+}
+
+
+static bool AreRectsOverlapped(const RECT &r1, const RECT &r2)
+{
+ return r1.left < r2.right
+ && r1.right > r2.left
+ && r1.top < r2.bottom
+ && r1.bottom > r2.top;
+}
+
+
+static bool AreRectsEqual(const RECT &r1, const RECT &r2)
+{
+ return r1.left == r2.left
+ && r1.right == r2.right
+ && r1.top == r2.top
+ && r1.bottom == r2.bottom;
+}
+
+
void CDialog::NormalizeSize(bool fullNormalize)
{
RECT workRect;
- GetWorkAreaRect(&workRect);
- int xSize = RECT_SIZE_X(workRect);
- int ySize = RECT_SIZE_Y(workRect);
+ if (!GetWorkAreaRect(&workRect, *this))
+ return;
RECT rect;
- GetWindowRect(&rect);
- int xSize2 = RECT_SIZE_X(rect);
- int ySize2 = RECT_SIZE_Y(rect);
- bool needMove = (xSize2 > xSize || ySize2 > ySize);
- if (xSize2 > xSize || (needMove && fullNormalize))
+ if (!GetWindowRect(&rect))
+ return;
+ int xs = RECT_SIZE_X(rect);
+ int ys = RECT_SIZE_Y(rect);
+
+ // we don't want to change size using workRect, if window is outside of WorkArea
+ if (!AreRectsOverlapped(rect, workRect))
+ return;
+
+ /* here rect and workRect are overlapped, but it can be false
+ overlapping of small shadow when window in another display. */
+
+ const int xsW = RECT_SIZE_X(workRect);
+ const int ysW = RECT_SIZE_Y(workRect);
+ if (xs <= xsW && ys <= ysW)
+ return; // size of window is OK
+ if (fullNormalize)
+ {
+ Show(SW_SHOWMAXIMIZED);
+ return;
+ }
+ int x = workRect.left;
+ int y = workRect.top;
+ if (xs < xsW) x += (xsW - xs) / 2; else xs = xsW;
+ if (ys < ysW) y += (ysW - ys) / 2; else ys = ysW;
+ Move(x, y, xs, ys, true);
+}
+
+
+void CDialog::NormalizePosition()
+{
+ RECT workRect;
+ if (!GetWorkAreaRect(&workRect, *this))
+ return;
+
+ RECT rect2 = workRect;
+ bool useWorkArea = true;
+ const HWND parentHWND = GetParent();
+
+ if (parentHWND)
{
- rect.left = workRect.left;
- rect.right = workRect.right;
- xSize2 = xSize;
+ RECT workRectParent;
+ if (!GetWorkAreaRect(&workRectParent, parentHWND))
+ return;
+
+ // if windows are in different monitors, we use only workArea of current window
+
+ if (AreRectsEqual(workRectParent, workRect))
+ {
+ // RECT rect3; if (GetWindowsRect_DWM(parentHWND, &rect3)) {}
+ CWindow wnd(parentHWND);
+ if (wnd.GetWindowRect(&rect2))
+ {
+ // it's same monitor. So we try to use parentHWND rect.
+ /* we don't want to change position, if parent window is not inside work area.
+ In Win10 : parent window rect is 8 pixels larger for each corner than window size for shadow.
+ In maximize mode : window is outside of workRect.
+ if parent window is inside workRect, we will use parent window instead of workRect */
+ if (IsRect_Small_Inside_Big(rect2, workRect))
+ useWorkArea = false;
+ }
+ }
}
- if (ySize2 > ySize || (needMove && fullNormalize))
+
+ RECT rect;
+ if (!GetWindowRect(&rect))
+ return;
+
+ if (useWorkArea)
{
- rect.top = workRect.top;
- rect.bottom = workRect.bottom;
- ySize2 = ySize;
+ // we don't want to move window, if it's already inside.
+ if (IsRect_Small_Inside_Big(rect, workRect))
+ return;
+ // we don't want to move window, if it's outside of workArea
+ if (!AreRectsOverlapped(rect, workRect))
+ return;
+ rect2 = workRect;
}
- if (needMove)
+
{
- if (fullNormalize)
- Show(SW_SHOWMAXIMIZED);
- else
- Move(rect.left, rect.top, xSize2, ySize2, true);
+ const int xs = RECT_SIZE_X(rect);
+ const int ys = RECT_SIZE_Y(rect);
+ const int xs2 = RECT_SIZE_X(rect2);
+ const int ys2 = RECT_SIZE_Y(rect2);
+ // we don't want to change position if parent is smaller.
+ if (xs <= xs2 && ys <= ys2)
+ {
+ const int x = rect2.left + (xs2 - xs) / 2;
+ const int y = rect2.top + (ys2 - ys) / 2;
+
+ if (x != rect.left || y != rect.top)
+ Move(x, y, xs, ys, true);
+ // SetWindowPos(*this, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
+ return;
+ }
}
}
-void CDialog::NormalizePosition()
-{
- RECT workRect, rect;
- GetWorkAreaRect(&workRect);
- GetWindowRect(&rect);
- if (rect.bottom > workRect.bottom && rect.top > workRect.top)
- Move(rect.left, workRect.top, RECT_SIZE_X(rect), RECT_SIZE_Y(rect), true);
-}
+
bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow)
{
diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h
index f804a9e7..8a39e996 100644
--- a/CPP/Windows/Control/Dialog.h
+++ b/CPP/Windows/Control/Dialog.h
@@ -183,7 +183,7 @@ public:
}
};
-bool IsDialogSizeOK(int xSize, int ySize);
+bool IsDialogSizeOK(int xSize, int ySize, HWND hwnd = NULL);
}}