创建菜单:
HMENU CreateMenu(VOID);
添加菜单项:
BOOL AppendMenu( HMENU hMenu, // handle to menu
UINT uFlags, // menu-item options
UINT_PTR uIDNewItem, // identifier, menu, or submenu
LPCTSTR lpNewItem // menu-item content
);
uFlags:
MF_POPUP -有子菜单的菜单项目,uIDNewItem要设置为子菜单的句柄(转换为uint)
MF_SEPARATOR -分隔线
MF_STRING -一般菜单项,被点击后会发送消息 WM_COMMAND
MF_MENUBREAK -换一列
把菜单加到窗口:
BOOL SetMenu( HWND hWnd, // handle to window HMENU hMenu // handle to menu
);
//修改菜单的勾选状态
DWORD CheckMenuItem( HMENU hmenu, // handle to menu
UINT uIDCheckItem, // menu item to check or uncheck
UINT uCheck // menu item options
);
uCheck:
MF_BYCOMMAND -填写菜单id
MF_BYPOSITION -填写菜单索引
MF_CHECKED/MF_UNCHECKED //1/0 --是否选中
//触发菜单点击事件
case WM_COMMAND:
On_Command(hwnd,wparam);
break;
//点击事件处理
void On_Command(HWND hwnd,WPARAM wparam)
{
bool IsFromMenu=(HIWORD(wparam)==0?true:false);//点击菜单:0,加速键:1
unsigned int id=LOWORD(wparam);//被点的控件id
switch(id)
{
case 10011:
//MessageBox(NULL,"打开","info",MB_OK);
if(isChecked)
{
CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_UNCHECKED);isChecked=false;
}
else{ CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_CHECKED);isChecked=true;
//MessageBox(NULL,"1","info",MB_OK);
}
break;
}
}
//设置可用或不可用,与CheckMenuItem用法一样
BOOL EnableMenuItem(HMENU hMenu,// handle to menu
UINT uIDEnableItem, // menu item to update
UINT uEnable // options
);
WM_INITMENUPOPUP //弹出菜单在被点击还未弹出来之前触发的消息
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_INITMENUPOPUP
WPARAM wParam, // handle to menu (HMENU)
LPARAM lParam // item position and indicator
);
lParam:
LOWORD 被点击菜单的索引
HIWORD 将要显示的菜单是否为窗口菜单(弹出式菜单不属于窗口菜单)
系统菜单的操作,消息:WM_SYSCOMMAND,不太重要,一般不用。
HMENU GetSystemMenu( HWND hWnd, // handle to window
BOOL bRevert // 是否返回默认菜单
);
AppendMenu //前面用过
//删除菜单,根据位置删除时,删除前一个,后面一个会改变位置。
BOOL DeleteMenu( HMENU hMenu, // handle to menu
UINT uPosition, // menu item identifier or position
UINT uFlags // option(MF_BYPOSITION/MF_BYCOMMAND)
);
右键菜单:弹出式菜单,前面用过,这里主要在右键时显示菜单。
BOOL TrackPopupMenu(
HMENU hMenu, // handle to shortcut menu
UINT uFlags, // options
int x, // horizontal position
int y, // vertical position
int nReserved, // reserved, must be zero
HWND hWnd, // handle to owner window
CONST RECT *prcRect // ignored
);
uFlags:
TPM_RETURNCMD -点击菜单项,不发出WM_COMMAND消息,但有返回值(被点击菜单的ID)
//右键消息处理函数,也可以在WM_CONTEXTMENU消息中处理(专门处理)
//WM_CONTEXTMENU 在 WM_RBUTTONUP之后触发的
//WM_CONTEXTMENU 中的坐标不需要转换
void OnRButtonUp(HWND hwnd,LPARAM lparam)
{
HMENU menucontext=CreatePopupMenu();
AppendMenu(menucontext,MF_STRING,103,"查看");
AppendMenu(menucontext,MF_STRING,104,"放大");
AppendMenu(menucontext,MF_STRING,105,"缩小");
POINT pt={0};
pt.y=HIWORD(lparam);
pt.x=LOWORD(lparam);
ClientToScreen(hwnd,&pt);//将客户区坐标转换为相对于屏幕的坐标
int cmdid= TrackPopupMenu(menucontext,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0,
hwnd,NULL);//在鼠标位置显示菜单
char txt[30]={0};
sprintf(txt,"被点的菜单ID:%d\n",cmdid);
MessageBox(hwnd,txt,"info",MB_OK);
}
ScreenToClient();//坐标转换函数
代码示例:
同样创建win32 application
主要cpp代码修改为:
// win32app.cpp : Defines the entry point for the application. // #include "stdafx.h" #include <stdio.h> HINSTANCE g_hinstance=0;//全局句柄 HMENU menu1=0,menu2=0; HANDLE g_houtput=0; void OnCreate(HWND hwnd,LPARAM lparam) { HMENU menu=CreateMenu(); menu1=CreatePopupMenu(); AppendMenu(menu1,MF_STRING|MF_CHECKED,10011,"打开"); AppendMenu(menu1,MF_STRING,10012,"保存"); AppendMenu(menu1,MF_SEPARATOR,0,NULL); AppendMenu(menu1,MF_STRING|MF_MENUBREAK,10013,"退出"); menu2=CreatePopupMenu(); AppendMenu(menu2,MF_STRING,10021,"复制"); AppendMenu(menu2,MF_STRING|MF_GRAYED,10022,"粘贴"); AppendMenu(menu,MF_POPUP,(UINT)menu1,"文件"); AppendMenu(menu,MF_SEPARATOR,0,NULL); AppendMenu(menu,MF_POPUP,(UINT)menu2,"编辑"); SetMenu(hwnd,menu); HMENU menusys=GetSystemMenu(hwnd,FALSE); for(int i=0;i<6;i++) { // DeleteMenu(menusys,0,MF_BYPOSITION);//删除系统菜单项 } AppendMenu(menusys,MF_STRING,101,"我的菜单"); } LRESULT CALLBACK OnInitMunuPopUp( HWND hwnd, // handle to window UINT uMsg, // WM_INITMENUPOPUP WPARAM wParam, // handle to menu (HMENU) LPARAM lParam // item position and indicator ) { unsigned int index=LOWORD(lParam); int IsWindowMenu=HIWORD(lParam); char txt[200]={0}; sprintf(txt,"OnInitMenuPopUp:menu:%d,Index:%d,IsWindow:%d\n",wParam,index,IsWindowMenu); WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); return 0; } bool isChecked=true; void On_Command(HWND hwnd,WPARAM wparam) { bool IsFromMenu=(HIWORD(wparam)==0?true:false); unsigned int id=LOWORD(wparam); switch(id) { case 10011: //MessageBox(NULL,"打开","info",MB_OK); if(isChecked) { CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_UNCHECKED);isChecked=false; } else{ CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_CHECKED);isChecked=true; //MessageBox(NULL,"1","info",MB_OK); } break; } } void OnSysCommand(HWND hwnd,WPARAM wparam) { bool IsFromMenu=(HIWORD(wparam)==0?true:false); unsigned int id=LOWORD(wparam); switch(id) { case 101: MessageBox(hwnd,"我的菜单","info",MB_OK); break; default: //MessageBox(hwnd,"我的菜单1","info",MB_OK); break; } } void OnRButtonUp(HWND hwnd,LPARAM lparam) { // HMENU menucontext=CreatePopupMenu(); // AppendMenu(menucontext,MF_STRING,103,"查看"); // AppendMenu(menucontext,MF_STRING,104,"放大"); // AppendMenu(menucontext,MF_STRING,105,"缩小"); // POINT pt={0}; // pt.y=HIWORD(lparam); // pt.x=LOWORD(lparam); // ClientToScreen(hwnd,&pt);//将客户区坐标转换为相对于屏幕的坐标 // int cmdid= TrackPopupMenu(menucontext,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0, // hwnd,NULL);//在鼠标位置显示菜单 // char txt[30]={0}; // sprintf(txt,"被点的菜单ID:%d\n",cmdid); // MessageBox(hwnd,txt,"info",MB_OK); } void OnContextMenu(HWND hwnd,LPARAM lparam) { HMENU menucontext=CreatePopupMenu(); AppendMenu(menucontext,MF_STRING,103,"查看"); AppendMenu(menucontext,MF_STRING,104,"放大"); AppendMenu(menucontext,MF_STRING,105,"缩小"); POINT pt={0}; pt.y=HIWORD(lparam); pt.x=LOWORD(lparam); //ClientToScreen(hwnd,&pt);//将客户区坐标转换为相对于屏幕的坐标 int cmdid= TrackPopupMenu(menucontext,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0, hwnd,NULL);//在鼠标位置显示菜单 if(cmdid!=0){ char txt[30]={0}; sprintf(txt,"被点的菜单ID:%d\n",cmdid); MessageBox(hwnd,txt,"info",MB_OK); } } //回调函数 LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam) { switch(msg) { case WM_SYSCOMMAND: if(wparam==SC_CLOSE){ int ret=MessageBox(NULL,"是否退出","info",MB_YESNO); if(ret==IDYES){ //下面代码会自动关闭和销毁 //PostQuitMessage(0); } else return 0;//不执行下面代码 } OnSysCommand(hwnd,wparam); break; //在创建窗口之后还未显示的时候 case WM_CREATE: OnCreate(hwnd,lparam); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_COMMAND: On_Command(hwnd,wparam); break; case WM_INITMENUPOPUP: OnInitMunuPopUp(hwnd,msg,wparam,lparam); break; case WM_RBUTTONUP: OnRButtonUp(hwnd,lparam); break; case WM_CONTEXTMENU: OnContextMenu(hwnd,lparam); break; } return DefWindowProc(hwnd,msg,wparam,lparam); } //注册窗口类 BOOL Register(LPSTR lpClassName,WNDPROC wndproc) { WNDCLASSEX wce={0}; wce.cbSize=sizeof(wce); wce.cbClsExtra=200; wce.cbWndExtra=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 atom= RegisterClassEx(&wce); if(atom==0){ MessageBox(NULL,"注册失败","info",MB_OK); return FALSE; } return TRUE; } //创建窗口 HWND CreateMain(LPSTR lpClassName,LPSTR lpWndName) { HWND hwnd=CreateWindowEx(0,lpClassName,lpWndName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,g_hinstance,"hello create"); return hwnd; } //创建子窗口 HWND CreateChild(HWND phwnd,LPSTR lpClassName,LPSTR lpWndName) { if(Register(lpClassName,DefWindowProc)==0) { MessageBox(phwnd,"创建子窗口失败","info",MB_OK); return NULL; } //子窗口风格,都要 WS_CHILD|WS_VISIBLE HWND hwnd=CreateWindowEx(0,lpClassName,lpWndName,WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, 200,200,phwnd,NULL,g_hinstance,NULL); return hwnd; } //显示窗口 void Display(HWND hwnd) { ShowWindow(hwnd,SW_SHOW); UpdateWindow(hwnd); } //处理消息 void MSGdeal() { MSG msg={0}; while(GetMessage(&msg,NULL,0,0)){ TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//派发给 WinProc 处理消息 } } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { AllocConsole();//调试程序方法 g_houtput=GetStdHandle(STD_OUTPUT_HANDLE); g_hinstance=hInstance; // TODO: Place code here. if(Register("main",WinProc)==0) { MessageBox(NULL,"注册失败","提示",MB_OK); return 0; } HWND hwnd= CreateMain("main","pro1"); Display(hwnd); MSGdeal(); return 0; }