如何在C++中获取Win10开始菜单的HWND?已尝试FindWindowEx未果
嗨,我之前也遇到过这个问题——Win10的开始菜单是基于UWP的组件,普通的FindWindowEx根本拿不到它的HWND,因为现代应用的窗口结构和传统Win32窗口不一样。下面我给你详细讲怎么用C++代码正确获取它的HWND和矩形区域。
为什么你的FindWindowEx调用失败?
Win10的开始菜单属于UWP应用框架,它的窗口并不是传统意义上的Win32顶层窗口,而且它的实际类名/标题可能和你预期的不一样,或者被系统隐藏了,所以直接用类名+标题查找会返回NULL。
正确的解决方案:枚举窗口+进程验证
我们需要枚举所有顶层窗口,结合UWP窗口的特性和进程名来精准定位开始菜单窗口。具体步骤是:
- 用
EnumWindows枚举所有顶层窗口 - 通过
DwmGetWindowAttribute判断窗口是否属于UWP应用 - 验证窗口所属进程是否是开始菜单的宿主进程
StartMenuExperienceHost.exe - 找到目标HWND后,用
GetWindowRect获取矩形区域
完整C++代码示例
#include <windows.h> #include <dwmapi.h> #include <iostream> #include <string> #pragma comment(lib, "dwmapi.lib") // EnumWindows的回调函数,用于筛选开始菜单窗口 BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { // 跳过不可见窗口 if (!IsWindowVisible(hwnd)) { return TRUE; } // 获取窗口类名 WCHAR className[256]; GetClassNameW(hwnd, className, sizeof(className) / sizeof(WCHAR)); std::wstring windowClass(className); // 判断是否是UWP核心窗口类 if (windowClass != L"Windows.UI.Core.CoreWindow") { return TRUE; } // 通过DWM属性判断是否是UWP窗口(被系统隐藏的现代应用窗口) BOOL isCloaked = FALSE; if (DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, &isCloaked, sizeof(isCloaked)) != S_OK || !isCloaked) { return TRUE; } // 获取窗口所属进程ID DWORD pid = 0; GetWindowThreadProcessId(hwnd, &pid); if (pid == 0) { return TRUE; } // 打开进程获取进程名 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); if (!hProcess) { return TRUE; } WCHAR processPath[MAX_PATH]; if (GetModuleFileNameExW(hProcess, NULL, processPath, MAX_PATH) == 0) { CloseHandle(hProcess); return TRUE; } std::wstring procPath(processPath); // 检查是否是开始菜单的宿主进程 if (procPath.find(L"StartMenuExperienceHost.exe") != std::wstring::npos) { // 找到目标HWND,保存到传入的参数中 *(HWND*)lParam = hwnd; CloseHandle(hProcess); return FALSE; // 停止枚举 } CloseHandle(hProcess); return TRUE; // 继续枚举 } int main() { HWND startMenuHwnd = NULL; // 启动窗口枚举 EnumWindows(EnumWindowsProc, (LPARAM)&startMenuHwnd); if (startMenuHwnd) { std::wcout << L"成功找到开始菜单HWND: " << startMenuHwnd << std::endl; // 获取窗口矩形区域 RECT windowRect; if (GetWindowRect(startMenuHwnd, &windowRect)) { std::wcout << L"开始菜单矩形区域信息:\n"; std::wcout << L"左边界: " << windowRect.left << L" 上边界: " << windowRect.top << std::endl; std::wcout << L"右边界: " << windowRect.right << L" 下边界: " << windowRect.bottom << std::endl; } else { std::cout << "获取矩形区域失败,错误码: " << GetLastError() << std::endl; } } else { std::cout << "未找到开始菜单窗口,请确保开始菜单处于打开状态!" << std::endl; } return 0; }
注意事项
- 编译时要确保项目是Unicode字符集(VS默认就是这个设置)
- 开始菜单只有在展开状态下才会存在对应的窗口,测试时要先打开开始菜单
- 需要链接
dwmapi.lib,代码里的#pragma comment(lib, "dwmapi.lib")已经帮你处理了这个依赖
内容的提问来源于stack exchange,提问作者tianxiaoyong
相关产品推荐
相关产品推荐

