diff options
author | 2023-05-04 02:41:16 +1000 | |
---|---|---|
committer | 2023-05-04 02:41:16 +1000 | |
commit | a504bde3a7462b54fafd5cfc2f52e58d0f3218e1 (patch) | |
tree | 8b3108d572b1a0873a6cdbb4e8af1f17179545c3 /3rdparty/lzma/CPP/Windows/Control/Dialog.cpp | |
parent | befb9bf4a8cfdb2b693a32e32535b5eac522c5d8 (diff) |
3rdparty/lzma: Updated to LZMA SDK version 22.01
Diffstat (limited to '3rdparty/lzma/CPP/Windows/Control/Dialog.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/Windows/Control/Dialog.cpp | 238 |
1 files changed, 201 insertions, 37 deletions
diff --git a/3rdparty/lzma/CPP/Windows/Control/Dialog.cpp b/3rdparty/lzma/CPP/Windows/Control/Dialog.cpp index 9df3ef5ef24..9ddd23427d8 100644 --- a/3rdparty/lzma/CPP/Windows/Control/Dialog.cpp +++ b/3rdparty/lzma/CPP/Windows/Control/Dialog.cpp @@ -2,6 +2,8 @@ #include "StdAfx.h" +// #include "../../Windows/DLL.h" + #ifndef _UNICODE #include "../../Common/StringConvert.h" #endif @@ -26,6 +28,14 @@ static INT_PTR APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wP return FALSE; if (message == WM_INITDIALOG) dialog->Attach(dialogHWND); + + /* MSDN: The dialog box procedure should return + TRUE - if it processed the message + FALSE - if it did not process the message + If the dialog box procedure returns FALSE, + the dialog manager performs the default dialog operation in response to the message. + */ + try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); } catch(...) { return TRUE; } } @@ -39,6 +49,7 @@ bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam); case WM_TIMER: return OnTimer(wParam, lParam); case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam)); + case WM_DESTROY: return OnDestroy(); case WM_HELP: OnHelp(); return true; /* OnHelp( @@ -72,29 +83,62 @@ bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */) { case IDOK: OnOK(); break; case IDCANCEL: OnCancel(); break; + case IDCLOSE: OnClose(); break; case IDHELP: OnHelp(); break; default: return false; } 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; @@ -149,47 +193,167 @@ 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) { - rect.left = workRect.left; - rect.right = workRect.right; - xSize2 = xSize; + Show(SW_SHOWMAXIMIZED); + return; } - if (ySize2 > ySize || (needMove && fullNormalize)) + 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.top = workRect.top; - rect.bottom = workRect.bottom; - ySize2 = ySize; + 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 (needMove) + + RECT rect; + if (!GetWindowRect(&rect)) + return; + + if (useWorkArea) { - if (fullNormalize) - Show(SW_SHOWMAXIMIZED); - else - Move(rect.left, rect.top, xSize2, ySize2, true); + // 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; } -} -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); + { + 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; + } + } } + + bool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow) { HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this); |