使用WS_OVERLAPPED,AdjustWindowRectEx()和GetWindowRect()给出错误的大小

And*_*eas 10 winapi

我想在打开窗口之前计算窗口的完整大小.我正在使用AdjustWindowRectEx()来实现这一目标.对于客户端大小为640x480的窗口,我的代码看起来像这样:

    wrect.left = 0;
    wrect.top = 0;
    wrect.right = 640;
    wrect.bottom = 480;
    AdjustWindowRectEx(&wrect, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, FALSE, 0);
Run Code Online (Sandbox Code Playgroud)

这将返回以下值:

    left: -3
    top: -22
    right: 643
    bottom: 483
Run Code Online (Sandbox Code Playgroud)

但是,当使用CreateWindowEx()打开窗口并传递时

    wrect.right - wrect.left
    wrect.bottom - wrect.top
Run Code Online (Sandbox Code Playgroud)

作为窗口大小,窗口的大小物理大小实际上是656x515像素.仍然,GetWindowRect()返回646x505,即与AdjustWindowRectEx()返回的尺寸相同,但正如我所说,当我拍摄桌面的屏幕截图并使用绘图程序测量窗口的大小时,其物理尺寸实际为656x515像素.有人对此有解释吗?

客户端大小没问题,它是640x480,但看起来边框大小计算错误,因为边框使用的像素数多于AdjustWindowRectEx()和GetWindowRect()计算的像素数.

我在Windows 7上.

编辑:

这是因为问题的标题是误导性的吗?如MSDN autodocs中所述,AdjustWindowRectEx()不支持WS_OVERLAPPED.那么有没有其他方法来计算WS_OVERLAPPED窗口的尺寸?使用WS_OVERLAPPEDWINDOW不是解决方案,因为它设置了我不想要的WS_THICKFRAME和WS_MAXIMIZEBOX.

现在有一些测试代码显示了问题.您可以看到客户端大小正常,但窗口的物理大小大于GetWindowRect()返回的大小.

#include <stdio.h>

#include <windows.h>

#define CLASSNAME "Test"

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{  
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wcx;
    RECT wrect;
    HWND hWnd;
    char tmpstr[256];

    memset(&wcx, 0, sizeof(WNDCLASSEX));

    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.style = CS_HREDRAW|CS_VREDRAW;  
    wcx.lpfnWndProc = WindowProc;
    wcx.hInstance = hInstance;
    wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcx.hbrBackground = GetStockObject(BLACK_BRUSH);  // important! otherwise a borderless window resize will not be drawn correctly        
    wcx.lpszClassName = CLASSNAME;

    RegisterClassEx(&wcx);

    wrect.left = 0;
    wrect.top = 0;
    wrect.right = 640;
    wrect.bottom = 480;     
    AdjustWindowRectEx(&wrect, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, FALSE, 0); 

    hWnd = CreateWindowEx(0, CLASSNAME, "Test", WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, 0, 0, wrect.right - wrect.left, wrect.bottom - wrect.top, NULL, NULL, hInstance, NULL);
    ShowWindow(hWnd, SW_SHOWNORMAL);

    GetWindowRect(hWnd, &wrect);
    sprintf(tmpstr, "%d %d %d %d\n", wrect.left, wrect.top, wrect.right, wrect.bottom);

    AllocConsole();
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), tmpstr, strlen(tmpstr), NULL, NULL);

    GetClientRect(hWnd, &wrect);
    sprintf(tmpstr, "%d %d %d %d\n", wrect.left, wrect.top, wrect.right, wrect.bottom);
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), tmpstr, strlen(tmpstr), NULL, NULL);

    Sleep(10000);

    DestroyWindow(hWnd);        
    UnregisterClass(CLASSNAME, hInstance);          

    return 0;
}   
Run Code Online (Sandbox Code Playgroud)

γηρ*_*όμε 6

GetWindowRect api的大小不正确:

Due to compatability requirements, certain metrics are reported in such a way that they're not consistent with what is actually drawn on the screen when Aero Glass (more accurately, "Windows Vista Aero") is enabled. This sort of approach is needed in order to change the look of the system for the vast majority of apps for which this isn't an issue.However, there's been a recent change in the system which will be coming out in Vista RC1 that will return the correct rendered value from GetWindowRect() for executables that are linked with "winver = 6.0". This allows new and newly-linked applications to get the "correct" values from GetWindowRect().

Aero Glass下不可调整大小的窗口上的GetWindowRect

改用DwmGetWindowAttribute正确的尺寸:

DwmGetWindowAttribute(hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, &wrect, sizeof(wrect));
Run Code Online (Sandbox Code Playgroud)


xMR*_*MRi -1

如果AdjustWindowRect不起作用,只需尝试创建Window并在窗口创建后调整大小。

// Create the window with a nearly correct size
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = 640;
rect.bottom = 480;  
AdjustWindowRectEx(&rect, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX, FALSE, 0); 

// try
hWnd = CreateWindowEx(0, CLASSNAME, "Test", WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL);

// Get the size that is really required and adjust
RECT rectCreated;
GetWindowRect(hWnd, &rectCreated);
rect.right += rectCreated.right-rectcreated.left;
rect.bottom += rectCreated.bottom-rectcreated.top;

// Resize to let the window fir the inner client aea
SetWindowPos(hWnd,NULL,0,0,rect.right-rect.left,rect.bottom-rect.top,SWP_NOMOVE|SWP_NOZORDER);

// Show it.
ShowWindow(hWnd, SW_SHOWNORMAL);
Run Code Online (Sandbox Code Playgroud)

代码未经过测试。希望其中没有错误或语法错误。

  • 但 GetWindowRect() 也给出了错误的大小。请参阅上面我的示例代码。GetWindowRect() 返回与AdjustWindowRectEx() 相同的大小,但它们都是错误的。 (2认同)