如何从 C++ 中的单独程序打开记事本中的系统菜单?
Posted
技术标签:
【中文标题】如何从 C++ 中的单独程序打开记事本中的系统菜单?【英文标题】:How to open system menu in Notepad from separate program in C++? 【发布时间】:2020-05-27 19:01:15 【问题描述】:我正在尝试在记事本中弹出系统菜单,如下所示:
不一定是帮助菜单;任何菜单都可以。
此代码将窗口置于前台并记录0x204a4 0x2bd041f 0
,但不会打开菜单。
#include <iostream>
#include <windows.h>
int main()
HWND hWnd = FindWindow(NULL, "Untitled - Notepad");
SetForegroundWindow(hWnd);
HMENU hMenu = GetSystemMenu(hWnd, FALSE);
int flag = TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, 452, 335, NULL, hWnd, NULL);
std::cout << hWnd << " " << hMenu << " " << flag << std::endl; // 0x204a4 0x2bd041f 0
SendMessage(hWnd, WM_SYSCOMMAND, flag, 0);
g++ main.cpp
更新:
这是我更新的代码。它打开了错误的菜单:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR pCmdLine, int nCmdShow)
const wchar_t CLASS_NAME[] = L"My Window Class";
WNDCLASS wc = ;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"My Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
return 0;
ShowWindow(hwnd, nCmdShow);
//--------------------------------------------------------------
HWND hWndNotepad = FindWindow(NULL, L"Untitled - Notepad");
if (!hWndNotepad)
MessageBox(hwnd, L"Notepad window handle not found.", L"Error", MB_OK | MB_ICONERROR);
if (!SetForegroundWindow(hWndNotepad))
MessageBox(hwnd, L"Unable to bring Notepad window to front.", L"Error", MB_OK | MB_ICONERROR);
HMENU hMenu = GetSystemMenu(hWndNotepad, FALSE);
if (!hMenu)
MessageBox(hwnd, L"Notepad menu handle not found.", L"Error", MB_OK | MB_ICONERROR);
TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, 452, 335, hwnd, NULL);
//--------------------------------------------------------------
MSG msg = ;
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
return 0;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
switch (uMsg)
case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
break;
return 0;
return DefWindowProc(hwnd, uMsg, wParam, lParam);
【问题讨论】:
你能用 AutoHotkey 或类似的代替吗? 您的应用在调用TrackPopupMenu()
时需要使用自己的HWND
,当该窗口在另一个进程中时,您不能使用菜单的所属窗口。但是您可以将WM_SYSCOMMAND
发布到另一个进程中的窗口。此外,您应该改用TrackPopupMenuEx()
。此外,在调用TrackPopupMenu/Ex()
之前,您没有进行任何错误处理以确保FindWindow()
、SetForegroundWindow()
和GetSystemMenu()
实际上是成功的
@RemyLebeau 我根据您的建议更新了我的帖子。但这会打开错误的菜单,如您在屏幕截图中所见。
@GirkovArpa 那是因为GetSystemMenu()
没有返回您正在寻找的菜单。它返回与窗口左上角图标和任务栏按钮关联的菜单。您正在寻找 GetMenu()
返回的菜单。
【参考方案1】:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR pCmdLine, int nCmdShow)
const wchar_t CLASS_NAME[] = L"My Window Class";
WNDCLASS wc = ;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"My Window", WS_OVERLAPPEDWINDOW, 683 - 100, 360 - 150, 300, 200, NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
return 0;
ShowWindow(hwnd, nCmdShow);
//--------------------------------------------------------------
HWND hWndNotepad = FindWindow(NULL, L"Untitled - Notepad");
if (!hWndNotepad)
MessageBox(hwnd, L"Notepad window handle not found.", L"Error", MB_OK | MB_ICONERROR);
return 0;
HMENU hMenu = GetMenu(hWndNotepad);
if (!hMenu)
MessageBox(hwnd, L"Notepad menu handle not found.", L"Error", MB_OK | MB_ICONERROR);
return 0;
tagTPMPARAMS tpm_params;
tpm_params.cbSize = sizeof(tagTPMPARAMS);
GetWindowRect(hWndNotepad, &tpm_params.rcExclude);
TrackPopupMenuEx(GetSubMenu(hMenu, 0), NULL, tpm_params.rcExclude.left, tpm_params.rcExclude.top, hwnd, NULL);
//--------------------------------------------------------------
MSG msg = ;
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage(&msg);
DispatchMessage(&msg);
return 0;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
switch (uMsg)
case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
break;
return 0;
return DefWindowProc(hwnd, uMsg, wParam, lParam);
g++ main.cpp -mwindows
【讨论】:
以上是关于如何从 C++ 中的单独程序打开记事本中的系统菜单?的主要内容,如果未能解决你的问题,请参考以下文章
压缩文件后(它们从 Visual Studio 中的文件路径引用打开),如何让我的应用程序从单独的 Winform 打开? (C#)