UE4使用C++创建系统托盘右键菜单功能异常问题求助
问题修复与原理说明
右键无弹出菜单的修复
你遇到的问题有4个核心原因,对应修复方案如下:
- 未处理右键事件:当前代码只监听了
WM_LBUTTONDBLCLK(左键双击)事件,右键点击对应的WM_RBUTTONUP事件完全没有处理 - 自定义WndProc未挂载到UE4窗口:UE4的原生窗口有默认的窗口处理函数,你自行编写的WndProc如果没有绑定到对应窗口句柄,系统永远不会调用它,所有托盘事件都会被UE4默认逻辑吞掉
- 弹出菜单前未设置前台窗口:Win32要求调用
TrackPopupMenu前必须将所属窗口设为前台窗口,否则菜单会出现无法弹出、点击空白处无法关闭的异常 - NOTIFYICONDATA未初始化大小:Win32要求所有结构体必须先初始化cbSize成员,否则跨系统版本调用时会出现不可预期的错误
修复后的完整代码参考:
#define NOTIFICATION_TRAY_ICON_MSG (WM_USER + 0x100) // 存储原UE4窗口过程的指针,必须保留,否则UE4原生窗口逻辑会失效 WNDPROC OriginalWndProc = nullptr; const int IDM_EXIT = 100; LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case NOTIFICATION_TRAY_ICON_MSG: { switch (lParam) { // 处理右键抬起事件 case WM_RBUTTONUP: // 保留你原来的左键双击逻辑 case WM_LBUTTONDBLCLK: { POINT pt; GetCursorPos(&pt); HMENU hmenu = CreatePopupMenu(); InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit"); // 必须先设置前台窗口 SetForegroundWindow(hWnd); TrackPopupMenu(hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, pt.x, pt.y, 0, hWnd, NULL); // 销毁菜单避免内存泄漏 DestroyMenu(hmenu); return 0; } } break; } // 处理菜单点击事件 case WM_COMMAND: { if (LOWORD(wParam) == IDM_EXIT) { // 这里写退出逻辑,比如调用UKismetSystemLibrary::QuitGame return 0; } break; } } // 所有未处理的消息必须交给原UE4窗口过程处理,否则会导致输入失效等问题 return CallWindowProc(OriginalWndProc, hWnd, message, wParam, lParam); } void AddTrayIcon(HWND hWnd, UINT uID, UINT uCallbackMsg, UINT uIcon) { NOTIFYICONDATA nid = {0}; // 必须初始化结构体大小 nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = hWnd; nid.uID = uID; nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nid.uCallbackMessage = uCallbackMsg; FString ThePath = FPaths::ConvertRelativePathToFull(FPaths::RootDir()) ; FString GameName = FApp::GetName(); ThePath.Append(GameName); ThePath.Append(".exe"); GEngine->AddOnScreenDebugMessage(-1, 12.f, FColor::White, ThePath); WORD id = 0; nid.hIcon = ExtractAssociatedIcon(nullptr, ThePath.GetCharArray().GetData(),&id); wcscpy_s(nid.szTip, L"Tool Tip"); Shell_NotifyIcon(NIM_ADD, &nid); // 挂载自定义窗口过程,保存原有窗口过程 OriginalWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)CustomWndProc); }
WndProc触发机制说明
WndProc是Win32平台的窗口过程函数,属于Windows消息驱动模型的核心:
- 每个Windows窗口创建时都会绑定一个窗口过程函数指针,系统会通过这个函数通知窗口所有发生的事件
- 你在
NOTIFYICONDATA中设置了uCallbackMessage为自定义的NOTIFICATION_TRAY_ICON_MSG后,每当用户操作托盘图标时,系统就会给你绑定的hWnd发送这条自定义消息,消息的lParam存储具体的操作类型(左键点击、右键点击、双击等) - 你之前编写的WndProc没有绑定到UE4的窗口上,因此系统只会调用UE4自带的窗口过程,你的逻辑永远不会被触发,这是右键无响应的核心原因之一
内容的提问来源于stack exchange,提问作者sandy
相关产品推荐
相关产品推荐

