12.菜单(二)

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;
}
View Code

   运行结果:

  

原文地址:https://www.cnblogs.com/csqtech/p/5616133.html