创建菜单:
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 ",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
",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
",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
",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;
}