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

问题描述 投票:0回答:3

我想在打开窗口之前计算它的完整大小。我正在使用 AdjustWindowRectEx() 来实现此目的。对于客户端大小为 640x480 的窗口,我的代码如下所示:

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

这将返回以下值:

    left: -3
    top: -22
    right: 643
    bottom: 483

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

    wrect.right - wrect.left
    wrect.bottom - wrect.top

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

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

我使用的是 Windows 7。

编辑:

这是因为问题标题具有误导性而被否决吗?正如 MSDN 自动文档中所述,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;
}   
winapi
3个回答
7
投票

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));

0
投票
The maximum length of the DLL file name is 33 characters; the maximum length of the function name is 63 characters.

• 安装程序在调用DLL 文件时不能接受复合参数(即宽度超过4 字节的参数)。但是,参数可以是指向复合结构的指针。强文本


-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);

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

© www.soinside.com 2019 - 2024. All rights reserved.