转换对话单位时SetWindowPos()设置错误的大小?

时间:2017-05-22 21:47:36

标签: c windows winapi

我试图围绕从对话单位(DLU)转换为像素,但我没有这样做。

我附上了一个演示问题的示例程序,一个只有一个按钮的对话框。我先解释一下: 我的.rc文件将对话框定义为" IDD_DIALOG1 DIALOG 0,0,320,240"所以DLU的大小是320x240。

我在调用MapDialogRect()时输入了这个大小,然后收回rec.right为480而rec.bottom为390。

如果我截取窗口并删除边框,我会得到一个精确到480x390像素的客户区。好哇!然而,转换工作......

当我调用SetWindowPos()时,使用固定值480x390或返回的rec.right和rec.bottom,窗口变小,客户区域为474x362。

我错过了什么吗?难道客户区不应该保持480×390像素吗?

.c文件:

#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文件:

// 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
}

[编辑]尝试使用AdjustWindowRectEx():

[Edit2] 5月23日,更正了我的复制粘贴错误:

    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] - 5月29日

我原来的问题是关于SetWindowPos()及其行为,我收到了有效答案。

然而,经历了设计调整大小的窗口,复制每个大小和位置,用代码编写然后以编程方式转换它的繁琐过程,我意识到我是愚蠢的。

我所要做的就是在资源编辑器中为每个所需大小创建另一个对话框,当用户更改大小时,我只需使用EndDialog()销毁窗口,然后使用DialogBox()再次调用该过程,提供名称所选尺寸的适当对话窗口。

1 个答案:

答案 0 :(得分:2)

SetWindowPos设置窗口外边缘的大小,包括窗口的非客户区域部分,如标题栏和边框。如果您的应用程序不是DPI aware,则Windows可能会对您的窗口应用缩放。 DWM阴影也可能在感知大小中起作用,但它不应包含在您的计算中。

AdjustWindowRectEx可用于根据客户矩形的所需大小计算窗口矩形所需的大小。