C4lculated
C4lculated

Reputation: 33

SetWindowPos() sets the wrong size when converting Dialog Units?

I'm trying to wrap my head around converting from Dialog Units(DLU) to pixels but I'm failing to do so.

I've attached a sample program that demonstrates the problem, a dialog box with only one button. I'll explain first: My .rc file defines the dialog box as "IDD_DIALOG1 DIALOG 0, 0, 320, 240" so the size in DLU is 320x240.

I input this size in my call to MapDialogRect() and receive back that rec.right is 480 and rec.bottom is 390.

If I screenshot the window and remove the borders I get a client area of exactly 480x390 pixels. Huzzah! the conversion works, however...

When I call SetWindowPos(), either with fixed values of 480x390 or the returned rec.right and rec.bottom the window gets smaller, with a client area of 474x362.

Am I missing something? Shouldn't the client area stay exactly 480 by 390 pixels?

.c file:

#include <windows.h>
#include "resource.h" 

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch(Message)
    {
        case WM_INITDIALOG:
        break;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case ID_RSZ:
                {
                    RECT rec;
                    rec.left = 0;
                    rec.top = 0;
                    rec.right = 320;
                    rec.bottom = 240;
                    MapDialogRect(hwnd, &rec);
                    SetWindowPos(hwnd, NULL, 0, 0, rec.right, rec.bottom, SWP_NOMOVE);
                    //SetWindowPos(hwnd, NULL, 0, 0, 480, 390, SWP_NOMOVE);
                }
                break;
            }
        break;
        case WM_CLOSE:
            EndDialog(hwnd, 0);
        break;
        default:
            return FALSE;
    }
    return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
}

.rc file:

// Generated by ResEdit 1.6.6
// Copyright (C) 2006-2015
// http://www.resedit.net

#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"




//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG1 DIALOG 0, 0, 320, 240
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "Ms Shell Dlg"
{
    PUSHBUTTON      "Resize!", ID_RSZ, 144, 102, 35, 21, 0, WS_EX_LEFT
}

[Edit] trying to use AdjustWindowRectEx():

[Edit2]May 23rd, corrected my copy-paste error:

    case ID_RSZ:
        {
            RECT rec;
            rec.left = 0;
            rec.top = 0;
            rec.right = 320;
            rec.bottom = 240;
            MapDialogRect(hwnd, &rec);
            AdjustWindowRectEx(&rec, DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU, FALSE, 0);
            if(rec.left < 0) rec.right += (rec.left*-1);
            if(rec.top < 0) rec.bottom += (rec.top*-1);
            SetWindowPos(hwnd, NULL, 0, 0, rec.right, rec.bottom, SWP_NOMOVE);
        }
        break;

[Edit3] - May 29th

My original question was about SetWindowPos() and it's behavior, and I received a valid answer.

However, going through the laborious process of designing the resized windows, copying each size and position, writing it in code and then converting it programmatically , I realized that I'm being dumb.

All I had to do is create another dialog for each desired size in my resource editor, and when the user changes size I simply destroy the window with EndDialog() and call the process again with DialogBox() providing the name of the appropriate dialog window for the selected size.

Upvotes: 1

Views: 1745

Answers (1)

Anders
Anders

Reputation: 101569

SetWindowPos sets the size of the outer edge of the window including the non-client area parts of the window like the titlebar and borders. If your application is not DPI aware then Windows might apply scaling to your window. The DWM shadow might also play a part in the perceived size but it should not be included in your calculations.

AdjustWindowRectEx can be used to calculate the required size of the window rectangle, based on the desired size of the client rectangle.

Upvotes: 2

Related Questions