mirror of
https://github.com/ip7z/7zip.git
synced 2026-04-21 06:03:40 +00:00
'21.07'
This commit is contained in:
parent
98e06a519b
commit
f19f813537
1244 changed files with 325856 additions and 2 deletions
414
CPP/Windows/Control/Dialog.cpp
Normal file
414
CPP/Windows/Control/Dialog.cpp
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
// Windows/Control/Dialog.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include "../../Windows/DLL.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
#include "../../Common/StringConvert.h"
|
||||
#endif
|
||||
|
||||
#include "Dialog.h"
|
||||
|
||||
extern HINSTANCE g_hInstance;
|
||||
#ifndef _UNICODE
|
||||
extern bool g_IsNT;
|
||||
#endif
|
||||
|
||||
namespace NWindows {
|
||||
namespace NControl {
|
||||
|
||||
static INT_PTR APIENTRY DialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
CWindow tempDialog(dialogHWND);
|
||||
if (message == WM_INITDIALOG)
|
||||
tempDialog.SetUserDataLongPtr(lParam);
|
||||
CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr());
|
||||
if (dialog == NULL)
|
||||
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; }
|
||||
}
|
||||
|
||||
bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG: return OnInit();
|
||||
case WM_COMMAND: return OnCommand(wParam, 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(
|
||||
#ifdef UNDER_CE
|
||||
(void *)
|
||||
#else
|
||||
(LPHELPINFO)
|
||||
#endif
|
||||
lParam);
|
||||
return true;
|
||||
*/
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CDialog::OnCommand(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam);
|
||||
}
|
||||
|
||||
bool CDialog::OnCommand(int code, int itemID, LPARAM lParam)
|
||||
{
|
||||
if (code == BN_CLICKED)
|
||||
return OnButtonClicked(itemID, (HWND)lParam);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CDialog::OnButtonClicked(int buttonID, HWND /* buttonHWND */)
|
||||
{
|
||||
switch (buttonID)
|
||||
{
|
||||
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, HWND hwnd)
|
||||
{
|
||||
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, HWND hwnd)
|
||||
{
|
||||
// it returns for system font. Real font uses another values
|
||||
const LONG v = GetDialogBaseUnits();
|
||||
const int x = LOWORD(v);
|
||||
const int y = HIWORD(v);
|
||||
|
||||
RECT 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;
|
||||
}
|
||||
|
||||
bool CDialog::GetMargins(int margin, int &x, int &y)
|
||||
{
|
||||
x = margin;
|
||||
y = margin;
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = margin;
|
||||
rect.bottom = margin;
|
||||
if (!MapRect(&rect))
|
||||
return false;
|
||||
x = rect.right - rect.left;
|
||||
y = rect.bottom - rect.top;
|
||||
return true;
|
||||
}
|
||||
|
||||
int CDialog::Units_To_Pixels_X(int units)
|
||||
{
|
||||
RECT rect;
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = units;
|
||||
rect.bottom = units;
|
||||
if (!MapRect(&rect))
|
||||
return units * 3 / 2;
|
||||
return rect.right - rect.left;
|
||||
}
|
||||
|
||||
bool CDialog::GetItemSizes(int id, int &x, int &y)
|
||||
{
|
||||
RECT rect;
|
||||
if (!::GetWindowRect(GetItem(id), &rect))
|
||||
return false;
|
||||
x = RECT_SIZE_X(rect);
|
||||
y = RECT_SIZE_Y(rect);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDialog::GetClientRectOfItem(int id, RECT &rect)
|
||||
{
|
||||
::GetWindowRect(GetItem(id), &rect);
|
||||
ScreenToClient(&rect);
|
||||
}
|
||||
|
||||
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;
|
||||
if (!GetWorkAreaRect(&workRect, *this))
|
||||
return;
|
||||
RECT rect;
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RECT rect;
|
||||
if (!GetWindowRect(&rect))
|
||||
return;
|
||||
|
||||
if (useWorkArea)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
if (aHWND == 0)
|
||||
return false;
|
||||
Attach(aHWND);
|
||||
return true;
|
||||
}
|
||||
|
||||
INT_PTR CModalDialog::Create(LPCTSTR templateName, HWND parentWindow)
|
||||
{
|
||||
return DialogBoxParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);
|
||||
}
|
||||
|
||||
#ifndef _UNICODE
|
||||
|
||||
bool CModelessDialog::Create(LPCWSTR templateName, HWND parentWindow)
|
||||
{
|
||||
HWND aHWND;
|
||||
if (g_IsNT)
|
||||
aHWND = CreateDialogParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);
|
||||
else
|
||||
{
|
||||
AString name;
|
||||
LPCSTR templateNameA;
|
||||
if (IS_INTRESOURCE(templateName))
|
||||
templateNameA = (LPCSTR)templateName;
|
||||
else
|
||||
{
|
||||
name = GetSystemString(templateName);
|
||||
templateNameA = name;
|
||||
}
|
||||
aHWND = CreateDialogParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);
|
||||
}
|
||||
if (aHWND == 0)
|
||||
return false;
|
||||
Attach(aHWND);
|
||||
return true;
|
||||
}
|
||||
|
||||
INT_PTR CModalDialog::Create(LPCWSTR templateName, HWND parentWindow)
|
||||
{
|
||||
if (g_IsNT)
|
||||
return DialogBoxParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);
|
||||
AString name;
|
||||
LPCSTR templateNameA;
|
||||
if (IS_INTRESOURCE(templateName))
|
||||
templateNameA = (LPCSTR)templateName;
|
||||
else
|
||||
{
|
||||
name = GetSystemString(templateName);
|
||||
templateNameA = name;
|
||||
}
|
||||
return DialogBoxParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);
|
||||
}
|
||||
#endif
|
||||
|
||||
}}
|
||||
Loading…
Add table
Add a link
Reference in a new issue