右键菜单的创建

时间:2022-12-26 00:23:13

创建:CreatePopupMenu
增加:AppendMenu

显示:BOOL TrackPopupMenu
{
HMENU hMenu,//显示的彩带句柄
UINT uFlags,//显示的方式
int x,//菜单的x屏幕坐标
int y,//菜单的y屏幕坐标
int nReseveed,//保留,必须为0
HWND hWnd,//处理菜单命令的窗口句柄
CONST RECT *prcRect);//忽略

命令处理:WM_COMMAND

使用右键菜单的位置
WM_RBUTTONUP消息
在WM_RBUTTONUP中,添加菜单的创建与显示,右键消息坐标,转换成屏幕坐标使用。
ClientToScreen.
WM_CONTEXTMENU消息,用于显示右键菜单的消息

WPARAM //右键点击时对应的窗口句柄
LPARAM //右键抬起时鼠标的屏幕坐标位置
LOWORD(lParam)-x屏幕坐标
HIWORD(lParam)-y屏幕坐标

WM_RBUTTONUP和WM_CONTEXTMENU对比
坐标系不同,WM_RBUTTONUP客户区坐标
WM_CONTEXTMENU屏幕坐标
先有WM_RBUTTONUP消息,后有WM_CONTEXTMENU消息

#include "stdafx.h"
////2
HINSTANCE g_hInst=NULL;
///b
void OnRButtonUp(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
    //创建弹出式菜单
    HMENU hPopMenu=CreatePopupMenu();
    //增加菜单项
    AppendMenu(hPopMenu,MF_STRING,1001,"测试");
    AppendMenu(hPopMenu,MF_SEPARATOR,0,NULL);
    AppendMenu(hPopMenu,MF_STRING,1002,"退出");
    //获取菜单位置
    POINT point={0};
    point.x=LOWORD(lParam);
    point.y=HIWORD(lParam);
    int nX=LOWORD(lParam);
    int nY=HIWORD(lParam);
    ClientToScreen(hWnd,&point);
    //显示菜单
    TrackPopupMenu(hPopMenu,TPM_LEFTALIGN,point.x,point.y,0,hWnd,NULL);
}

void OnCommand(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
    int nCmdID=LOWORD(wParam);
    switch(nCmdID)
    {
    case 1001:
        MessageBox(NULL,"Hello Popmenu","PopMenu",MB_OK);
        break;
    case 1002:
        PostQuitMessage(0);
        break;
    }
}
void OnContextMenu(HWND hwnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
    //创建弹出式菜单
    HMENU hPopMenu=CreatePopupMenu();
    //增加菜单项
    AppendMenu(hPopMenu,MF_STRING,1001,"测试1");
    AppendMenu(hPopMenu,MF_SEPARATOR,0,NULL);
    AppendMenu(hPopMenu,MF_STRING,1002,"退出1");
}
////3
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd,//窗口句柄
                         UINT nMsg,//窗口消息Id
                         WPARAM wParam,//消息传来的两个参数
                         LPARAM lParam)
{   
    switch(nMsg)    //消息退出的命令
    {
    case WM_RBUTTONUP://a当鼠标右键抬起时消息
        OnRButtonUp(hWnd,nMsg,wParam,lParam);
        break;
    case WM_CONTEXTMENU:
        OnContextMenu(hWnd,nMsg,wParam,lParam);
        break;
    case WM_COMMAND:
        OnCommand(hWnd,nMsg,wParam,lParam);
            break;
    case WM_DESTROY:
        PostQuitMessage(0); //使窗口退出
        return 0;
    }
    //返回缺省的窗口处理函数
    return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
////4
//注册窗口-首先使用WNDCLASSEX定义窗口类的各项参数
BOOL RegisterWnd(LPSTR pszClassName)
{
    WNDCLASSEX wce      ={0};
    wce.cbSize          =sizeof(wce);
    wce.cbClsExtra      =0;//窗口类的附加参数
    wce.cbWndExtra      =0;//窗口的附加参数
    wce.hbrBackground   =HBRUSH(COLOR_WINDOW);//窗口的背景画刷
    wce.hCursor         =NULL;//窗口的光标
    wce.hIcon           =NULL;//窗口的图标
    wce.hIconSm         =NULL;//窗口的小图标
    wce.hInstance       =g_hInst;//应用程序的实例句柄
    wce.lpfnWndProc     =WndProc;//窗口处理函数指针
    wce.lpszClassName   =pszClassName;//窗口类的名称
    wce.lpszMenuName    =NULL;//菜单名称
    wce.style           =CS_HREDRAW|CS_VREDRAW;//窗口风格
//注册窗口用RegisterClassEx,返回用ATOM
    ATOM nAtom=RegisterClassEx(&wce);
    if(0==nAtom)
    {
        return FALSE;//窗口注册没有成功
    }
    return TRUE;
}

////5创建窗口
HWND CreateWnd(LPSTR pszClassName)
{
    HWND hWnd=CreateWindowEx(0,//窗口的扩展风格
        pszClassName,//窗口类的名称
        "MyWnd",//窗口的标题
        WS_OVERLAPPEDWINDOW,//窗口的堆叠风格
        CW_USEDEFAULT,//窗口的坐标和长宽
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,//窗口的父窗口
        NULL,//窗口的菜单
        g_hInst,//应用程序句柄
        NULL);//窗口创建时的附加参数
    return hWnd;
}

////6窗口的显示
void DisplayWnd(HWND hWnd)
{
    ShowWindow(hWnd,SW_SHOW);//显示窗口
    UpdateWindow(hWnd);//刷新窗口界面
}

////7窗口的消息循环
void Message()
{
    MSG msg={0};
    while (GetMessage(&msg,NULL,0,0))//获取消息
    {
        TranslateMessage(&msg);//翻译消息
        DispatchMessage(&msg);//调用窗口处理函数处理消息
    }
}
//// 1 新建时自动生成
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    // TODO: Place code here.
////将程序依次执行
    g_hInst=hInstance;
    RegisterWnd("MYWND");//注册窗口
    HWND hWnd=CreateWnd("MYWND");//创建窗口
    DisplayWnd(hWnd);//显示窗口
    Message( );//执行消息循环

    return 0;
}