0

The aim is to resize the Window of the DialogEx that best fit the configured Systemmetrics screenheight and screendepth on the object machine:

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

IDD_MAIN is setup as the default in 768p. Let's call it IDD_760Pinstead and use its resource file config as the base to work on.

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

These controls can be separately recalibrated with CreateWindow according to this post but that's a lot of code.
Is there a way of subclassing the form to use extra resource file presets based on the above for IDD_1080P, IDD_2160P, IDD_4320P& beyond? Where in the code would we place the GetSystemMetrics(SM_CXSCREEN) and GetSystemMetrics(SM_CYSCREEN) functions?

Community
  • 1
  • 1
Laurie Stearn
  • 959
  • 1
  • 13
  • 34
  • You can use a library for dialogs resizing like this http://www.codeproject.com/Articles/141908/Resizing-Win-Dialogs-with-DialogBox-and-Dialog-R. There aere many around in C, C++, C# etc. – Frankie_C Feb 27 '16 at 13:50
  • Aw ok, it's a DIALOGEX with the chief control as a ListBox. Frankie's suggestion is very well documented and presented project, but a little bit top-heavy for this perhaps? – Laurie Stearn Feb 27 '16 at 14:27
  • 1
    It's still completely unclear, what you are looking for. The updated title doesn't help much: Noone knows, what a *Chief Window* is, nor what controls a Listbox presumably contains. The rest of your question just lists seemingly unrelated questions. – IInspectable Feb 27 '16 at 14:51
  • 1
    You want a resizable dialog with width and height set in pixels? or set in dialog units? In above example the dialog width is `701` in dialog units --- in `WM_INITDIALOG` you can resize the dialog and move/resize the controls – Barmak Shemirani Feb 27 '16 at 16:21
  • Yes, that's the direction where we wish to tread. What functions do you recommend for this? – Laurie Stearn Feb 27 '16 at 16:54

2 Answers2

1

You can resize the dialog in WM_INITDIALOG

GetSystemMetrics(SM_CXSCREEN)/GetSystemMetrics(SM_CYSCREEN) gives the full screen width/height. This would try to overlap the toolbar. You probably don't want that.

SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcDesktop, NULL); will get the rectangle for desktop, or you can just show maximized window

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

You should change the dialog style to the following:

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

Note, you will have to move/resize all the child controls. When moving child controls, not that you have to its position in screen coordinates, then convert to client coordinate's of parent window.

Example

#include <Windows.h>
#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;
}
Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • 1
    Both the `GetSystemMetrics` and the `SystemParametersInfo` calls retrieve information for the primary display only. Single-monitor setups are hardly the norm these days, and the code should really account for multi-monitor setups. – IInspectable Feb 27 '16 at 17:09
  • One has to take care with 3D dialogs viz SM_CXEDGE as well.Thanks- is [this](https://msdn.microsoft.com/en-us/library/bb158585.aspx?f=255&MSPPError=-2147217396) the kind of thing to resize the controls? – Laurie Stearn Feb 27 '16 at 17:18
  • See update for moving/resizing the controls. The link you have shown is correct. But the trick is to remember the original coordinates of the child control, then move or resize each control as dialog is resized. – Barmak Shemirani Feb 27 '16 at 17:45
  • Yeah thanks, I guess the original edit of the question was vague in the sense precision resizing was not required. Just didn't want the thing looking ridiculously small on an ultra hi-res display.This is going to turn into a fair bit of code. No way of using the "resource file presets" in the OP then? – Laurie Stearn Feb 27 '16 at 17:52
  • It looks like you don't need re-sizing at all. User can adjust resolution and DPI settings. You can also look up "DPI-Awareness" https://msdn.microsoft.com/en-us/library/windows/desktop/dd371771%28v=vs.85%29.aspx – Barmak Shemirani Feb 27 '16 at 19:48
0

In the "old" days there were avid discussions about the use of static data in resource files as opposed to the then "limited" processing power. Doesn't appear to be such an issue these days, however in this case the processing for huge DPIs might be an issue.
I believe Barmak's answer is the way to go, but added this as an expedient, but cheaper and less precise alternative.
Unfortunately we cannot use the preprocessor for the different presets, so the idea is to enumerate lpTemplate values for LPCDLGTEMPLATE just after the entry point:

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 returns the appropriate strings IDD_1080P, IDD_2160P etc. Provided the template structure and associated data for each template in the resource file is not changed there shouldn't be a problem.
Edit1: Checking for primary/secondary display might be a little awkward if calling the function MonitorFromWindow before we get a handle for our DlgProc window using the alternative method to Barmak's. Well it appears that it is not possible to ever return to the wWinMain routine once having left it, so the next option is to create another ephemeral "cheaper" hwnd from wWinMain to get the appropriate templates.
Edit 2: The form templates for the different resolutions are all set up in a spreadsheet downloadable here thanks to AOO.

Community
  • 1
  • 1
Laurie Stearn
  • 959
  • 1
  • 13
  • 34