1.右键菜单(Context Menu,上下文菜单)的使用
(1)创建菜单
右键菜单是一个弹出式菜单,使用CreatePopupMenu创建
(2)显示弹出式菜单
BOOL TrackPopupMenu( HMENU hMenu, //弹出菜单句柄
UINT uFlags, //显示方式
int x, //水平位置,屏幕坐标系
int y, //垂直位置,屏幕坐标系
int nRevserved, //保留,必须为0
HWND hWnd, //处理菜单消息的窗口句柄
CONST RECT *prcRect); //NULL,忽略
TrackPopupMenu是阻塞函数
//将客户区坐标系下的坐标转换为屏幕坐标系下的坐标
BOOL ClientToScreen( HWND hWnd, //窗口句柄
LPPOINT lpPoint); //[IN/OUT]
输入:客户区坐标系下的坐标
输出:屏幕坐标系下的坐标
(3)命令处理
WM_COMMAND消息与窗口菜单一致。如果TrackPopupMenu设置了TPM_RETURNCMD被点击的菜单ID是通过返回值获取。
(4)菜单项的状态
WM_INITMENUPOPUP消息,按照弹出式菜单处理。
2.菜单的处理位置
(1)鼠标右键抬起
WM_RBUTTONUP,鼠标右键抬起消息,是窗口坐标系坐标,使用时要转换成屏幕坐标系坐标。
ClientToScreen
ScreenToClient
(2)WM_CONTEXTMENU
wPARAM:右键点击的窗口句柄
lPARAM:LOWORD - x坐标,屏幕坐标系
HIWORD - y坐标,屏幕坐标系
WM_CONTEXTMENU消息是在WM_RBUTTONUP消息之后产生。
相关代码:

#include "stdafx.h" HINSTANCE g_hInstance = 0; //接收当前程序实例句柄 void OnCreate(HWND hWnd) { HMENU hSys = GetSystemMenu(hWnd, FALSE); //删除系统菜单 for (int i = 0; i < 6; i++) { DeleteMenu(hSys, 0, MF_BYPOSITION); } //增加系统菜单 AppendMenu(hSys, MF_SEPARATOR, 0, ""); AppendMenu(hSys, MF_STRING, 1001, "我的菜单项"); } void OnSysCommand(HWND hWnd, WPARAM wParam) { switch (LOWORD(wParam)) { case 1001: MessageBox(hWnd, "我的菜单项被点击", "Info", MB_OK); break; } } void OnRButtonUp(HWND hWnd, LPARAM lParam) { /* HMENU hPopup = CreatePopupMenu(); AppendMenu(hPopup, MF_STRING, 1002, "新建"); AppendMenu(hPopup, MF_SEPARATOR, 0, ""); AppendMenu(hPopup, MF_STRING, 1003, "退出"); POINT pt = { 0 }; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); ClientToScreen(hWnd, &pt); BOOL nRet = TrackPopupMenu(hPopup, TPM_CENTERALIGN | TPM_VCENTERALIGN|TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, NULL); switch (nRet) { case 1002: MessageBox(hWnd, "没发出WM_COMMAND消息,处理了新建被点击", "Info", MB_OK); break; case 1003: MessageBox(hWnd, "没发出WM_COMMAND消息,处理了退出被点击", "Info", MB_OK); break; } */ } void OnCommand(HWND hWnd, WPARAM wParam) { switch (LOWORD(wParam)) { case 1002: MessageBox(hWnd, "新建被点击", "Info", MB_OK); break; case 1003: MessageBox(hWnd, "退出被点击", "Info", MB_OK); break; } } void OnContextMenu(HWND hWnd, LPARAM lParam) { HMENU hPopup = CreatePopupMenu(); AppendMenu(hPopup, MF_STRING, 1002, "新建"); AppendMenu(hPopup, MF_SEPARATOR, 0, ""); AppendMenu(hPopup, MF_STRING, 1003, "退出"); POINT pt = { 0 }; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); //ClientToScreen(hWnd, &pt);//无需转换 BOOL nRet = TrackPopupMenu(hPopup, TPM_CENTERALIGN | TPM_VCENTERALIGN | TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, NULL); switch (nRet) { case 1002: MessageBox(hWnd, "没发出WM_COMMAND消息,处理了新建被点击", "Info", MB_OK); break; case 1003: MessageBox(hWnd, "没发出WM_COMMAND消息,处理了退出被点击", "Info", MB_OK); break; } } //窗口处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CONTEXTMENU: OnContextMenu(hWnd, lParam); break; case WM_COMMAND: OnCommand(hWnd, wParam); break; case WM_RBUTTONUP: OnRButtonUp(hWnd, lParam); break; case WM_SYSCOMMAND: OnSysCommand(hWnd, wParam); break; case WM_CREATE: OnCreate(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } //注册窗口类 BOOL Register(LPSTR lpClassName, WNDPROC wndProc) { WNDCLASSEX wce = { 0 }; wce.cbSize = sizeof(wce); wce.cbClsExtra = 200; wce.cbClsExtra = 200; wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wce.hCursor = NULL; wce.hIcon = NULL; wce.hIconSm = NULL; wce.hInstance = g_hInstance; wce.lpfnWndProc = wndProc; wce.lpszClassName = lpClassName; wce.lpszMenuName = NULL; wce.style = CS_HREDRAW | CS_VREDRAW; ATOM nAtom = RegisterClassEx(&wce); if (0 == nAtom) { return FALSE; } return TRUE; } //创建主窗口 HWND CreateMainWindow(LPSTR lpClassName, LPSTR lpWndName) { HWND hWnd = CreateWindowEx(0, lpClassName, lpWndName, WS_OVERLAPPEDWINDOW, 500, 200, 500, 300, NULL, NULL, g_hInstance, NULL); return hWnd; } //显示窗口 void Display(HWND hWnd) { ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); } //消息循环 void Message() { MSG nMsg = { 0 }; while (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { g_hInstance = hInstance; Register("Main", WndProc); HWND hWnd = CreateMainWindow("Main", "window"); Display(hWnd); Message(); return 0; }
运行结果: