《windows核心编程》(十三)-----------2013.8.16
一、概念
菜单的使用
创建菜单
HMENU CreateMenu(VOID); //创建成功返回菜单句柄
增加菜单项
BOOL AppendMenu(
HMENUhMenu, //菜单句柄
UINTuFlags, //菜单项风格
UINT_PTRuIDNewItem, //菜单项ID
LPCTSTRlpNewItem //菜单项的名称
);
设置到窗口
BOOL SetMenu(
HWNDhWnd, //窗口句柄
HMENUhMenu //菜单句柄
);
示例:
在窗口创建时创建窗口。
void OnMenu(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
HMENU hMainMenu = CreateMenu();//创建主菜单
AppendMenu(hMainMenu,MF_STRING,1001,"文件");//添加文件菜单
AppendMenu(hMainMenu,MF_STRING,1002,"编辑");//添加编辑菜单
AppendMenu(hMainMenu,MF_STRING,1003,"帮助");//添加帮助菜单
SetMenu(hWnd,hMainMenu);//将主菜单加入到窗口中
}
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd,UINT nMsg,
WPARAM wParam,LPARAM lParam)
{
switch(nMsg)
{
case WM_COMMAND:
break;
case WM_CREATE:
OnMenu(hWnd,nMsg,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
菜单的创建
HMENUCreatePopupMenu(VOID);//创建成功返回菜单句柄
加入顶层菜单
BOOLAppendMenu(
HMENUhMenu, //菜单句柄
UINTuFlags, //菜单项增加选项,MF_POPUP
UINT_PTRuIDNewItem, //弹出式菜单的句柄
LPCTSTRlpNewItem //菜单项的名称
);
示例:
void OnMenu(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
HMENU hMainMenu = CreateMenu();//创建主菜单
HMENU hFileMenu = CreatePopupMenu();//创建下拉菜单
AppendMenu(hFileMenu,MF_STRING,1001,"新建");//在下拉菜单中加入新建菜单
AppendMenu(hFileMenu,MF_STRING,1002,"打开");//在下拉菜单中加入打开菜单
AppendMenu(hFileMenu,MF_STRING,1003,"退出");//在下拉菜单中加入退出菜单
AppendMenu(hMainMenu,MF_STRING | MF_POPUP,(UINT)hFileMenu,"文件");//将下拉菜单加入到主菜单中
HMENU hEditMenu = CreatePopupMenu();//创建下拉菜单
AppendMenu(hEditMenu,MF_STRING,1004,"剪切");//在下拉菜单中加入剪切菜单
AppendMenu(hEditMenu,MF_STRING,1005,"复制");//在下拉菜单中加入复制菜单
AppendMenu(hEditMenu,MF_STRING,1006,"粘贴");//在下拉菜单中加入粘贴菜单
AppendMenu(hMainMenu,MF_STRING | MF_POPUP,(UINT)hEditMenu,"编辑");//将下拉菜单加入到主菜单中
HMENU hHelpMenu = CreatePopupMenu();//创建下拉菜单
AppendMenu(hHelpMenu,MF_STRING,1007,"帮助");//在下拉菜单中加入帮助菜单
AppendMenu(hHelpMenu,MF_STRING,1008,"关于");//在下拉菜单中加入关于菜单
AppendMenu(hMainMenu,MF_STRING | MF_POPUP,(UINT)hHelpMenu,"帮助");//将下拉菜单加入到主菜单中
SetMenu(hWnd,hMainMenu);//将主菜单加入到窗口中
}
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd,UINT nMsg,
WPARAM wParam,LPARAM lParam)
{
switch(nMsg)
{
case WM_COMMAND:
break;
case WM_CREATE:
OnMenu(hWnd,nMsg,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
WM_COMMAND 消息
WPARAM:
HIWORD-对于菜单为0
LOWORD -菜单项的ID
LPARAM - 对于菜单为NULL
命令处理过程
获取WPARAM菜单ID,根据ID处理。
在增加菜单项可以设置菜单项的状态。
可以使用菜单API 修改状态
CheckMenuItem
EnableMenuItem
函数使用时,需要通过设置MF_BYPOSITION或者MF_BYCOMMAND,确定使用菜单索引或者菜单ID。
WM_INITMENUPOPUP
在菜单被激活但是未显示,窗口会收到这个消息
WPARAM-菜单句柄(即将显示的菜单句柄
LPARAM- LOWORD是菜单项索引(被点击的顶层菜单索引
HIWORD是窗口菜单标识
示例:
void OnCommand(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
int nID = LOWORD(wParam);
switch(nID)
{
case 1001:
MessageBox(NULL,"新建","Infor",MB_OK);
break;
case 1002:
MessageBox(NULL,"打开","Infor",MB_OK);
break;
case 1003:
MessageBox(NULL,"退出","Infor",MB_OK);
break;
case 1004:
MessageBox(NULL,"剪切","Infor",MB_OK);
break;
case 1005:
MessageBox(NULL,"复制","Infor",MB_OK);
break;
case 1006:
MessageBox(NULL,"粘贴","Infor",MB_OK);
break;
case 1007:
MessageBox(NULL,"帮助","Infor",MB_OK);
break;
case 1008:
MessageBox(NULL,"关于","Infor",MB_OK);
break;
}
}
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd,UINT nMsg,
WPARAM wParam,LPARAM lParam)
{
switch(nMsg)
{
case WM_COMMAND:
OnCommand(hWnd,nMsg,wParam,lParam);
break;
case WM_CREATE:
OnMenu(hWnd,nMsg,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
1 系统菜单的获取
HMENUGetSystemMenu(
HWNDhWnd,//窗口句柄
BOOLbRevert //重置选项
);返回获取到的系统菜单句柄
bRevert:TRUE -删除旧菜单,恢复到默认的系统菜单
FALSE -返回当前的系统菜单句柄。
2 系统菜单的修改
AppendMenu
DeleteMenu
3 系统菜单命令响应
通过WM_SYSCOMMAND响应菜单命令。
WPARAM的LOWORD是命令ID
右键菜单 ContextMenu的使用
右键菜单是一个弹出式菜单,使用CreatePopupMenu创建。
BOOLTrackPopupMenu(
HMENU hMenu, //菜单句柄
UINT uFlags, //显示方式
int x,//水平位置,屏幕坐标系
int y,//垂直位置,屏幕坐标系
intnReserved, //保留,必须0
HWND hWnd, //处理菜单消息的窗口句柄
CONST RECT *prcRect //NULL,忽略
);TrackPopupMenu是阻塞函数
WM_COMMAND,与窗口菜单一致
如果Track设置了TPM_RETURNCMD选项,那么点击的菜单项ID通过函数的返回值获取。
WM_INITMENUPOPUP,按照弹出菜单处理
1鼠标右键抬起
WM_RBUTTONUP鼠标右键消息窗口坐标系坐标,要使用需要转换成屏幕坐标系
ClientToScreen
ScreenToClient
2 WM_CONTEXTMENU
WParam - 右键点击的窗口句柄
LPARAM - LOWORD X坐标,屏幕坐标系
HIWORDY坐标,屏幕坐标系
WM_CONTEXTMENU消息是在WM_RBUTTONUP消息之后产生。
void OnContextMenu(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
POINT pt = {0};
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
HMENU hMenu = CreatePopupMenu();
AppendMenu(hMenu,MF_STRING,10001,"复制");
AppendMenu(hMenu,MF_STRING,10002,"粘贴");
TrackPopupMenu(hMenu,TPM_LEFTALIGN,pt.x,pt.y,NULL,hWnd,NULL);
DestroyMenu(hMenu);
}
//窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd,UINT nMsg,
WPARAM wParam,LPARAM lParam)
{
switch(nMsg)
{
case WM_CONTEXTMENU:
OnContextMenu(hWnd,nMsg,wParam,lParam);
break;
case WM_COMMAND:
OnCommand(hWnd,nMsg,wParam,lParam);
break;
case WM_CREATE:
OnMenu(hWnd,nMsg,wParam,lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
资源的使用
资源脚本文件:*.rc文件
编译器:RC.EXE
1添加菜单资源
2加载菜单资源
2.1 在注册时设置菜单资源
2.2 加载菜单资源,设置到窗口
HMENU LoadMenu(
HINSTANCE hInstance, // handle to module
LPCTSTR lpMenuName // menu name or resource identifier
);
CreateWindow/Ex
SetMenuMAKEINTRESOURCE - 将数字形式的资源ID转换为字符串形式的资源ID
1添加资源
注意图标的大小,一个图标文件中,可以有多个不同大小的图标。
2加载
HICON LoadIcon(
HINSTANCE hInstance, // handle to applicationinstance
LPCTSTR lpIconName // name string or resource identifier
); 成功返回HICON句柄
3设置
3.1 注册窗口类
3.2 WM_SETICON消息
4绘制
DrawIcon
1添加光标的资源
光标的大小默认是32X32像素,每个光标有HotSpot,是当前鼠标的热点
2使用资源
HCURSORLoadCursor(
HINSTANCE hInstance, // handle to application instance
LPCTSTR lpCursorName // name or resource identifier
); hInstance - 可以为NULL,获取系统默认的Cursor
2.1在注册窗口时,设置光标
2.2使用SetCursor设置光标
HCURSORSetCursor(
HCURSORhCursor // handle to cursor
);
3 WM_SETCURSOR 消息参数
WPARAM - 当前使用的光标句柄
LPARAM - LOWORD 当前区域的代码(Hit-Test code )
HIWORD - 当前鼠标消息ID
1添加字符串资源
添加字符串表,在表中增加字符串
2字符串资源的使用
intLoadString(
HINSTANCE hInstance, // handle to resource module
UINT uID, //字符串ID
LPTSTR lpBuffer, //存放字符串BUFF
intnBufferMax // 字符串BUFF长度
); 成功返回字符串长度,失败0