我试图获取 Windows 上特定窗口的标题栏的高度。您可以使用记事本复制它。我使用的是 C++,我在网上找到的代码都没有产生正确的结果。使用例如
Screenpresso
我测量了窗口栏高度的 31
像素。
我尝试过的功能如下:
TitleBarHeight.h
:
#pragma once
#include <windows.h>
inline int get_title_bar_thickness_1(const HWND window_handle)
{
RECT window_rectangle, client_rectangle;
GetWindowRect(window_handle, &window_rectangle);
GetClientRect(window_handle, &client_rectangle);
return window_rectangle.bottom - window_rectangle.top -
(client_rectangle.bottom - client_rectangle.top);
}
inline int get_title_bar_thickness_2(const HWND window_handle)
{
RECT window_rectangle, client_rectangle;
GetWindowRect(window_handle, &window_rectangle);
GetClientRect(window_handle, &client_rectangle);
return (window_rectangle.right - window_rectangle.left - client_rectangle.right) / 2;
}
结果:
auto window_handle = FindWindow("Notepad", nullptr);
auto a = get_title_bar_thickness_1(window_handle); // 59
auto b = get_title_bar_thickness_2(window_handle); // 8
auto c = GetSystemMetrics(SM_CXSIZEFRAME); // 4
auto d = GetSystemMetrics(SM_CYCAPTION); // 23
使用
GetSystemMetrics()
获取系统指标不起作用,因为窗口显然可以有不同的标题栏高度,并且窗口句柄没有参数。
怎样才能真正得到
31
的结果?
假设您没有菜单栏,您可以将点从客户端坐标系映射到屏幕一。
RECT wrect;
GetWindowRect( hwnd, &wrect );
RECT crect;
GetClientRect( hwnd, &crect );
POINT lefttop = { crect.left, crect.top }; // Practically both are 0
ClientToScreen( hwnd, &lefttop );
POINT rightbottom = { crect.right, crect.bottom };
ClientToScreen( hwnd, &rightbottom );
int left_border = lefttop.x - wrect.left; // Windows 10: includes transparent part
int right_border = wrect.right - rightbottom.x; // As above
int bottom_border = wrect.bottom - rightbottom.y; // As above
int top_border_with_title_bar = lefttop.y - wrect.top; // There is no transparent part
有 8、8、8 和 31 像素(96DPI 又名 100% 缩放设置)
您还应该考虑 DPI 感知模式。尤其是
GetSystemMetrics
很棘手,因为它会记住应用程序启动时系统 DPI 的状态。
WM_GETTITLEBARINFOEX
,您将获得标题栏的边框。
TITLEBARINFOEX * ptinfo = (TITLEBARINFOEX *)malloc(sizeof(TITLEBARINFOEX));
ptinfo->cbSize = sizeof(TITLEBARINFOEX);
SendMessage(hWnd, WM_GETTITLEBARINFOEX,0, (LPARAM)ptinfo);
int height = ptinfo->rcTitleBar.bottom- ptinfo->rcTitleBar.top;
int width = ptinfo->rcTitleBar.right - ptinfo->rcTitleBar.left;
free(ptinfo);
首先,确保您的应用程序具有高 DPI 感知能力,这样系统就不会欺骗您。
选项:
信任 GetSystemMetrics。 几乎任何实际上具有不同标题大小的顶级窗口都在进行自定义非客户区管理,这将使其(几乎)不可能。 明显的例外是工具窗口 (WS_EX_TOOLWINDOW),如果还设置了 WS_CAPTION 样式,它可能具有 SM_CYSMCAPTION 高度。
获取目标窗口矩形和目标窗口的样式。 使用AdjustWindowRectEx 确定切换了WS_CAPTION 样式后的大小差异。 我不确定这是否有效,因为是否可以有没有某种边框的标题之间可能存在一些交互。
获取目标窗口矩形并发送WM_HITTEST消息以获取窗口下移的坐标。 计算其中有多少人获得 HT_CAPTION 作为回报。如果您使用二分搜索而不是线性搜索来执行此操作,则会获得奖励积分。 假设窗口有一个矩形标题区域,这可能是最难也是最可靠的方法。
如果我理解正确,看起来你想要获取窗口的边框大小(我们应该能够从宽度中收集它,因为没有标题栏)并从垂直大小减去客户端中减去它窗户...
inline int get_title_bar_thickness(const HWND window_handle)
{
RECT window_rectangle, client_rectangle;
int height, width;
GetWindowRect(window_handle, &window_rectangle);
GetClientRect(window_handle, &client_rectangle);
height = (window_rectangle.bottom - window_rectangle.top) -
(client_rectangle.bottom - client_rectangle.top);
width = (window_rectangle.right - window_rectangle.left) -
(client_rectangle.right - client_rectangle.left);
return height - (width/2);
}