无标题栏C++ Win32窗口无法触发Windows 11停靠面板求助
解决方案
问题根源在于Windows 11的停靠(Snap)功能依赖窗口具备WS_MAXIMIZEBOX样式——系统会认为没有该样式的窗口不支持最大化类操作,因此不会触发顶部停靠的弹窗。要在保留自定义标题栏且窗口不可调整大小的前提下解决问题,可按以下步骤操作:
步骤1:保留WS_MAXIMIZEBOX样式
修改窗口创建时的样式参数,保留WS_MAXIMIZEBOX,移除WS_SIZEBOX(如果不需要窗口可调整大小):
HWND hWnd = CreateWindowW( L"minimal_example_window", L"", WS_VISIBLE | WS_POPUP | WS_MAXIMIZEBOX, // 保留WS_MAXIMIZEBOX,移除WS_SIZEBOX CW_USEDEFAULT, CW_USEDEFAULT, 1200, 800, NULL,NULL, hInstance, NULL );
步骤2:隐藏最大化按钮
由于我们不需要显示最大化按钮,可通过DWM API隐藏它。需要引入dwmapi.h并链接dwmapi.lib:
#include <dwmapi.h> #pragma comment(lib, "dwmapi.lib") // 链接DWM库
在窗口创建完成后,调用DwmSetWindowAttribute设置隐藏最大化按钮:
// 启用DWM非客户区渲染 DWMNCRENDERINGPOLICY render_policy = DWMNCRP_ENABLED; DwmSetWindowAttribute(hWnd, DWMWA_NCRENDERING_POLICY, &render_policy, sizeof(render_policy)); // 隐藏最大化按钮 DWORD button_mask = DWMNCA_HIDEMAXBUTTON; DwmSetWindowAttribute(hWnd, DWMWA_NCAP_BUTTONS, &button_mask, sizeof(button_mask));
步骤3:保持原有拖动逻辑
你的WM_NCHITTEST处理逻辑无需修改,依然可以让整个客户区作为标题栏拖动:
LRESULT CALLBACK window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_NCHITTEST) { LRESULT hit = DefWindowProc(hWnd, uMsg, wParam, lParam); if (hit == HTCLIENT) hit = HTCAPTION; return hit; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
完整修改后的代码
#include <windows.h> #include <dwmapi.h> #pragma comment(lib, "dwmapi.lib") LRESULT CALLBACK window_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_NCHITTEST) { LRESULT hit = DefWindowProc(hWnd, uMsg, wParam, lParam); if (hit == HTCLIENT) hit = HTCAPTION; return hit; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { WNDCLASSW window_class = { NULL, window_proc, NULL,NULL, hInstance, NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"minimal_example_window" }; RegisterClassW(&window_class); HWND hWnd = CreateWindowW( L"minimal_example_window", L"", WS_VISIBLE | WS_POPUP | WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 1200, 800, NULL,NULL, hInstance, NULL ); // 配置DWM属性隐藏最大化按钮 DWMNCRENDERINGPOLICY render_policy = DWMNCRP_ENABLED; DwmSetWindowAttribute(hWnd, DWMWA_NCRENDERING_POLICY, &render_policy, sizeof(render_policy)); DWORD button_mask = DWMNCA_HIDEMAXBUTTON; DwmSetWindowAttribute(hWnd, DWMWA_NCAP_BUTTONS, &button_mask, sizeof(button_mask)); MSG msg; while (GetMessageW(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessageW(&msg); } return 0; }
这样修改后,窗口既可以通过客户区任意拖动,又能触发Windows 11的顶部停靠弹窗,同时不会显示最大化按钮,也无法调整窗口大小。
内容的提问来源于stack exchange,提问作者Barnabás
相关产品推荐
相关产品推荐

