我曾经执行以下操作来创建一个 800*600 客户区的窗口:
dwStyle = WS_OVERLAPPED | WS_THICKFRAME | WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX;
int nPositionX = 20, nPositionY = 20;
hWindowHandle = CreateWindow( L"CGFramework", wszWndCaption,
dwStyle, nPositionX, nPositionY,
800 + GetSystemMetrics( SM_CXSIZEFRAME )*2,
600 + GetSystemMetrics( SM_CYSIZEFRAME )*2
+ GetSystemMetrics( SM_CYCAPTION ),
0, 0, hInstance, 0
);
然后当用GetClientRect查询客户端矩形时,我以前得到800*600,但现在我将我的Visual Studio 2008项目升级到VS2012,现在GetClientRect()函数返回792*592。这只会发生在催吐 Aero 主题而不是 Classic Windows 主题中。
最重要的是,正在创建的窗口的实际大小是 804*629,我认为这是没有原因的,因为可调整大小的框架(来自 WS_THICKFRAME)明显大于每边 2 个像素。
所以我的问题如下:
- 为什么 800 + GetSystemMetrics( SM_CXSIZEFRAME )*2 不产生窗口宽度?除了普通的窗口边框和客户区之外,我什么也没看到。
- 为什么 800 + GetSystemMetrics( SM_CXSIZEFRAME )*2 是 804?你有没有看到默认为 2 像素宽的 WS_THICKFRAME 边框?不管我们说什么主题,这个结果都是错误的,没有这样的 2px 边框。我得到的真正边框大约是 5 或 6 px 宽,这增加了这些值的无意义。
- 为什么这只发生在 VS2012 而不是其他编译器版本?
- 为什么在 windows 7 aero 和 windows 8 aero 中会发生不同的情况?两个操作系统的行为不应该相同吗?相同的可执行文件将与 W7 中的经典主题完美配合,在 W7 Aero 中会产生错误的大小,并且会在 W8 中完全破坏我的窗口内容——可能是因为我正在使用 WinAPI 函数来创建适当的 D3D 后台缓冲区。出于某种原因,如果应用程序使用旧版本的编译器(例如 VS 2008)编译,它将在 W7 Aero 和 W8 中正常工作。
我不介意是否可以通过其他方式获得合适的窗口大小;我只是想知道为什么过去 15 年左右有效的通用程序不再起作用了。如果您的答案只是“使用 AdjustWindowRect”,那么请不要回答,因为我在这里问的是不同的东西。我什至可能无法使用该功能,所以我想知道为什么我得到的损坏的数字一定是这样的。
我认为函数 GetSystemMetrics() 实际上是返回边界边界的大小,因为我认为它们是唯一可以测量 2 个像素的东西(实际上它们在边界的每一侧都是 1 个像素..它对我来说仍然没有任何意义)
PS:在项目配置中更改 DPI Awareness 没有任何区别。