带控件的DialogEx:resize?

目的是调整最适合配置的Systemmetrics屏幕高度和对象机器上的screendepth的DialogEx窗口:

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { return DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_MAIN), nullptr, DlgProc); } 

IDD_MAIN在768p中设置为默认值。 我们将其IDD_760P并使用其资源文件配置作为基础来处理。

 IDD_768P DIALOGEX 0, 0, 701, 191 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "MahProject" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN LTEXT "Add",IDC_STATIC,506,10,14,8 EDITTEXT IDC_TEXT,528,7,120,14,ES_AUTOHSCROLL EDITTEXT IDC_NUMBER,647,7,21,14,ES_NUMBER LTEXT "times.",IDC_STATIC,671,10,23,8 LISTBOX IDC_LIST,7,22,641,148,LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP //principal, main, or chief control on form PUSHBUTTON "&Add",IDC_ADD,650,30,46,14 PUSHBUTTON "&Up",IDC_UP,650,47,47,14 PUSHBUTTON "&Down",IDC_DOWN,650,63,47,14 PUSHBUTTON "&Sideways",IDC_CREATE,650,80,47,14 PUSHBUTTON "&UpsideDown",IDC_REMOVE,650,97,47,14 PUSHBUTTON "&Less",IDC_CLEAR,650,114,47,14 PUSHBUTTON "&More",IDC_LOGON,650,131,47,14 PUSHBUTTON "&NoMore",IDC_NOLOGON,650,148,47,14 LTEXT "Great",IDC_STATIC_ONE,530,180,70,8 CTEXT "-",IDC_SHOWCOUNT,600,180,25,8 LTEXT "Fantastic",IDC_STATIC_TWO,625,180,30,8 END 

根据这篇文章 ,这些控件可以使用CreateWindow单独重新校准,但这是很多代码。
是否有一种方法可以根据上面的IDD_1080PIDD_2160P, IDD_4320P及更高版本对表单进行子类化以使用额外的资源文件预设? 在代码中我们放置GetSystemMetrics(SM_CXSCREEN)GetSystemMetrics(SM_CYSCREEN)函数?

您可以在WM_INITDIALOG调整对话框的WM_INITDIALOG

GetSystemMetrics(SM_CXSCREEN) / GetSystemMetrics(SM_CYSCREEN)给出全屏宽度/高度。 这会尝试重叠工具栏。 你可能不希望这样。

SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcDesktop, NULL); 将获得桌面矩形,或者您可以显示最大化窗口

 BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { if (msg == WM_INITDIALOG) { ShowWindow(hwnd, SW_MAXIMIZE); return 0; } ... return FALSE; } 

您应该将对话框样式更改为以下内容:

STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MAXIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME

请注意,您必须移动/调整所有子控件的大小。 移动子控件时,不是你必须在屏幕坐标中的位置,然后转换为父窗口的客户端坐标。

 #include  #include "resource.h" #define rcwidth(rc) (rc.right - rc.left) #define rcheight(rc) (rc.bottom - rc.top) void move_resize(HWND child, int dx, int dy, int dw, int dh) { if (!child) return; if (!IsWindow(child)) return; if (!GetParent(child)) return; //find child window's coordinates relative to top-left of parent: RECT rc; GetWindowRect(child, &rc); //rc is now child control's rectangle in screen coordinates POINT pt = { 0 }; ScreenToClient(GetParent(child), &pt); OffsetRect(&rc, pt.x, pt.y); //rc is now child control's rectangle relative to parent window //prevent negative size if ((rcwidth(rc) + dw) < 0) dw = -rcwidth(rc); if ((rcheight(rc) + dh) < 0) dh = -rcheight(rc); MoveWindow(child, rc.left + dx, rc.top + dy, rcwidth(rc) + dw, rcheight(rc), TRUE); } BOOL CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static RECT save_rect; switch (msg) { case WM_INITDIALOG: GetClientRect(hwnd, &save_rect); ShowWindow(hwnd, SW_MAXIMIZE); break; case WM_SIZE: if (lParam) { int cx = LOWORD(lParam); int cy = HIWORD(lParam); int dx = cx - save_rect.right; int dy = cy - save_rect.bottom; //change x/y position of OK/Cancel button move_resize(GetDlgItem(hwnd, IDCANCEL), dx, dy, 0, 0); move_resize(GetDlgItem(hwnd, IDOK), dx, dy, 0, 0); //change width/height of listbox: move_resize(GetDlgItem(hwnd, IDC_LIST1), 0, 0, dx, dy); GetClientRect(hwnd, &save_rect); } break; case WM_COMMAND: if (LOWORD(wParam) == IDOK) EndDialog(hwnd, wParam); if (LOWORD(wParam) == IDCANCEL) EndDialog(hwnd, wParam); break; } return FALSE; } int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE, LPTSTR, int) { DialogBox(hinst, MAKEINTRESOURCE(IDD_DIALOG1), 0, DlgProc); return 0; } 

在“旧”时代,人们讨论了在资源文件中使用静态数据而不是当时“有限”的处理能力。 这些天似乎不是这样的问题,但是在这种情况下,处理巨大的DPI可能是一个问题。
我相信巴马克的答案是要走的路,但我认为这是一种权宜之计,但更便宜,更不精确的选择。
遗憾的是,我们不能将预处理器用于不同的预设,因此我们的想法是在入口点之后枚举LPCDLGTEMPLATE的lpTemplate值:

 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { Create_Temporary_hwnd_here ... lpTemplate = DoSystemParametersInfoStuff(hwnd); ... Destroy__Temporary_hwnd ... return DialogBoxW(hInstance, MAKEINTRESOURCEW(lpTemplate), nullptr, DlgProc); } 

DoSystemParametersInfostuff返回相应的字符串IDD_1080P,IDD_2160P等。如果资源文件中每个模板的模板结构和关联数据未更改,则应该没有问题。
Edit1:在我们使用Barmak的替代方法获取DlgProc窗口的句柄之前调用函数MonitorFromWindow时,检查主/辅显示可能有点尴尬。 好吧,似乎一旦离开它就不可能再回到wWinMain例程,所以下一个选择是从wWinMain创建另一个短暂的“更便宜”的程序来获得适当的模板。
编辑2:由于AOO,不同分辨率的表单模板都在可下载的电子表格中设置。