沧桑不尽
无穷的沧桑,不尽的落叶
疯狂C时代
上节中说道的是菜单的一些基本操作,显然满足不了实际上的需要,因为在我们操作程序的时候,有的菜单项有时是可
用的,有时是不可用的,也有可能根据情况动态地添加、删除和修改菜单,本节将解决这些问题。此外,快捷菜单往往
能大大地提高工作的效率,所以还要说下快捷菜单的东西。
菜单项的添加、删除、和修改,也就是通过这个API而已,所以这节就是学习这个函数的使用了。
1.添加菜单项
BOOL AppendMenu(hMenu hMenu,UINT uFlags,UINT uIDNewltem,LPCTSTR lpNewltem);
2.插入菜单项
BOOL InsertMenu(HMENU hMenu,UINt uPosition,UINT uFlags,UINT uIDNewltem,LPCTSTR lpNewltem);
3.修改菜单项
BOOL ModifyMenu(HMENU hMnu,UINT uPosition,UINT uFlags,UINT uIDNewltem,LPCTSTR IpNewltem);
4.删除菜单项
BOOL DeleteMenu(HMENU hMenu,UINT uPosition,UINT uFlags);
BOOL RemoveMenu( HMENU hMenu, UINT uPosition, UINT uFlags
);
其实AppendMenu和InsertMenu函数都是添加菜单项函数,只不过ApendMenu是在菜单的最后添加菜单项,InsertMenu
则是在菜单项中间插入菜单项。DeleteMenu和RemoveMenu都可以删除菜单,两者的不同之处在于:当它们用于popup属
性的菜单项时,DeleteMenu不仅删除菜单项,而且将这个popup菜单项的所有子项目全部删除,而RemoveMenu函数进菜
单项中移去这个popup菜单项,整个popup菜单在内存中还是存在的。
这些函数的参数基本上都差不多,hMenu是要操作的菜单的句柄;uPositon是菜单项的位置。位置的表示方法有两种:用命
令ID定位或用位置索引。函数使用哪一种方法,是有后面的uFlags决定的。当uFlags为MF_BYCOMMAND时,uPosition应
为菜单项的命令ID;而uFlags为MF_BYPOSITON时,uPosition表示菜单项的位置索引,索引是从0开始的,第一个菜单项
的索引为0.
AppendMenu和InsertMenu函数中的uIDNewItem表示这个新菜单项的命令ID,lpNewmItem是新菜单项的文字字符串指
针。ModifyMenu函数则是修改这两个参数了。
 
为了编程上的方便,接下来就把快捷菜单的给说了,然后在同一个程序中实现菜单的高级操作和快捷菜单的操作。
前面也说了,快捷菜单也是弹出时菜单,只不过在鼠标单击右键时弹出,弹出的时候,是在鼠标单击的位置弹出。
这里要用到一个函数TrackPopupMenu函数。

TrackPopupMenu

  函数功能:该函数在指定位置显示快捷菜单,并跟踪菜单项的选择。快捷菜单可出现在屏幕上的任何位置。

  函数原型:BOOL TrackPopupMenu(HMENU hMenu,UINT uFlags,int x,int y,int nReserved,HWND hWnd,CONST RECT”prcRect);

  参数

  hMenu:被显示的快捷菜单的句柄。此句柄可为调用CreatePopupMenu创建的新快捷菜单的句柄,也可以为调用GetSubMenu取得的与一个已存在菜单项相联系的子菜单的句柄。

  uFlags:一种指定功能选项的位标志。用下列标志位之一来确定函数如何水平放置快捷菜单:

  TPM_CENTERALIGN:若设置此标志,函数将按参数x指定的坐标水平居中放置快捷菜单。

  TPM_LEFTALIGN:若设置此标志,函数使快捷菜单的左边界与由参数X指定的坐标对齐。

  TPM_RIGHTALIGN:若设置此标志,函数使快捷菜单的右边界与由参数X指定的坐标对齐。

  用下列标志位之一来确定函数如何垂直放置快捷菜单:

  TPM_BOTTOMALIGN:若设置此标志,函数使快捷菜单的下边界与由参数y指定的坐标对齐。

  TPM_TOPALIGN:若设置此标志,函数使快捷菜单的上边界与由参数y指定的坐标对齐。

  TPM_VCENTERALIGN;若设置此标志,函数将按参数y指定的坐标垂直居中放置快捷菜单

  用下列标志位之一来确定在菜单没有父窗口的情况下用户的选择:

  TPM_NONOTIFY:若设置此标志,当用户单击菜单项时函数不发送通知消息。

  TPM_RETURNCMD;若设置此标志;函数将用户所选菜单项的标识符返回到返回值里。

  (补充:当TrackPopupMenu的返回值大于0,就说明用户从弹出菜单中选择了一个菜单。以返回的ID号为参数wParam的值,程序给自己发送了一个WM_SYSCOMMAND消息)

  用下列标志位之一来确定在快捷菜单跟踪哪一个鼠标键:

  TPM_LEFTBUTTON:若设置此标志,用户只能用鼠标左键选择菜单项。

  TPM_RIGHTBUTTON:若设置此标志,用户能用鼠标左、右键选择菜单项。

  X:在屏幕坐标下,快捷菜单的水平位置。

  Y:在屏幕坐标下,快捷菜单的垂直位置。

  NReserved:保留值,必须为零。

  HWnd:拥有快捷菜单的窗口的句柄。此窗口接收来自菜单的所有消息。函数返回前,此窗口不接受来自菜单的WM_COMMAND消息。

  如果在参数uFlags里指定了TPM_NONOTIFY值,此函数不向hWnd标识的窗口发消息。 但必须给hWnd里传一个窗口句柄,可以是应用程序里的任一个窗口句柄。

  PrcRect:未用。

  返回值:如果在参数uFlags里指定了TPM_RETURNCMD值,则返回值是用户选择的菜单项的标识符。如果用户未作选择就取消了菜单或发生了错误,则退回值是零。如果没在参数uFlags里指定TPM_RETURNCMD值,若函数调用成功,返回非零值,若函数调用失败,返回零。若想获得更多的错误信息,清调用GetLastError

  函数:

  备注:Windows CE不支持参数uFlags取下列值:TPM_NONOTIFY;TPM_LEFTBUTTON;TPM_RIGHTBUTTON。

 
至于获取鼠标的位置,可以请出这个函数:

GetCursorPos

  函数功能:该函数检取光标的位置,以屏幕坐标表示。

  函数原型:BOOL GetCursorPos(LPPOlNT IpPoint);

  参数:

  IpPint:POINT结构指针,该结构接收光标的屏幕坐标。

  使用时要先定义一个数据结构: Public Type POINTAPI

  x As Long

  y As Long

  End Type

  GetCursorPos biao

  那么biao.x用来存放当前光标的x轴坐标,biao.y用来存放当前y轴的坐标。

  返回值:如果成功,返回值非零;如果失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。

 
使用TrackPopupMenu要注意的是,弹出的菜单句柄一般为popup类型的,而用LoadMenu函数装载的并不是popup类型的
,popup只能在第二层或者够多层中定义,这时就要用GetSubMenu函数来获取第二层菜单句柄,也就是popup型的菜单句柄
,GetSubMenu这个函数比较简单,大家看下就会明白的,不多说。
继上节中的代码,MyMenu.rc修改为如下代码:
代码
/**************MyMenu.rc Written By XHK 2009.3.3*************/
/*****MyMenu.c Modified by XHK 2009.3.4****/

#include
<resource.h>

#define ICO_MAIN 0X1000 //图标
#define IDM_MAIN 0X2000 //菜单
#define IDA_MAIN 0X2000 //快捷键

#define IDM_OPEN 0X4101 //“打开”菜单项
#define IDM_INACTIVE 0X4201 //“被禁用的菜单项”
#define IDM_GRAYED 0X4202 //“灰化的菜单项”
#define IDM_HELP 0X4301 //“帮助”菜单项

#define IDM_SHORTCUT 0X4400 //快捷菜单
#define IDM_APPEND 0X4401 //“添加新菜单项”
#define IDM_DELETE 0X4402 //“删除菜单项”

/********The ico file of the window***********/
ICO_MAIN ICON
"xhk.ico"
/*********************************************/
/**Next is the definition of the Menus**********/
IDM_MAIN menu discardable
{
popup
"文件(&F)"
{
menuitem
"打开(&O)\tCtrl+Alt+O",IDM_OPEN
}

popup
"查看(&V)"
{
menuitem
"被禁用的菜单项",IDM_INACTIVE,INACTIVE
menuitem separator
menuitem
"被灰化的菜单项",IDM_GRAYED,GRAYED
}

popup
"帮助(&H)",HELP
{
menuitem
"帮助主题(&H)\tF1",IDM_HELP
}
}

IDM_SHORTCUT menu discardable
{
popup
" "//不想起名字了,用空格了
{
menuitem
"添加新菜单项",IDM_APPEND
menuitem
"删除菜单项",IDM_DELETE
}
}

//下面定义快捷建

IDA_MAIN accelerators
{
VK_F1,IDM_HELP,VIRTKEY
//F1
"O",IDM_OPEN,VIRTKEY,CONTROL,ALT //Ctrl+Alt+O
}

程序代码文件修改如下:
代码
/*****MyMenu.c Written by XHK 2009.3.3****/
/*****MyMenu.c Modified by XHK 2009.3.4****/
#include
<windows.h>

#define ICO_MAIN 0X1000 //图标
#define IDM_MAIN 0X2000 //菜单
#define IDA_MAIN 0X2000 //快捷键

#define IDM_OPEN 0X4101 //“打开”菜单项
#define IDM_INACTIVE 0X4201 //“被禁用的菜单项”
#define IDM_GRAYED 0X4202 //“灰化的菜单项”
#define IDM_HELP 0X4301 //“帮助”菜单项


#define IDM_SHORTCUT 0X4400
#define IDM_APPEND 0X4401
#define IDM_DELETE 0X4402

HMENU hMenu;
//定义全局变量,方面函数调用
HMENU hMenuShort;//同上

//定义弹出快捷菜单函数
int PopupShortcutMenu(hWnd)
{
POINT point;
GetCursorPos(
&point);//获取鼠标的位置
//弹出菜单
TrackPopupMenu(GetSubMenu(hMenuShort,0),TPM_CENTERALIGN,point.x,point.y,0,(HWND)hWnd,NULL);
return 1;
}

//回调函数
LRESULT WINAPI WinProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
{
//HMENU hMenu;
//HINSTANCE hInstance;
switch(Msg)
{
case WM_COMMAND:
switch(0x0000ffff&wParam)
{
case IDM_OPEN:
MessageBox(hWnd,
"你单击了\"打开\"菜单项","提示",MB_OK);
break;
case IDM_HELP:
MessageBox(hWnd,
"你单击了\"帮助主题\"菜单项","提示",MB_OK);
break;
case IDM_APPEND:
//添加新菜单项
AppendMenu(GetSubMenu(hMenuShort,0),MF_CHECKED,0X4403,"新添加的菜单项");
break;
case IDM_DELETE:
//删除菜单项
DeleteMenu(GetSubMenu(hMenuShort,0),0x4403,MF_BYCOMMAND);
break;
}
break;
case WM_RBUTTONUP:
PopupShortcutMenu(hWnd);
break;
case WM_DESTROY://响应鼠标单击关闭按钮事件
PostQuitMessage(0);
return 0;//退出函数
}
return DefWindowProc(hWnd,Msg,wParam,lParam);
}

//主函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
char *cName = "myWindow";
char *cCaption = "带目录的窗口 - Made By XHK";
WNDCLASSEX wc;
HWND hWnd;

HACCEL hAccel;
//快捷键表句柄
MSG Msg;

wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
wc.cbSize
= sizeof(WNDCLASSEX);
wc.hbrBackground
= (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor
= NULL;
wc.hIcon
= LoadIcon(hInstance,MAKEINTRESOURCE(ICO_MAIN));//载入图标
wc.hIconSm = NULL;
wc.hInstance
= hInstance;
wc.lpfnWndProc
= WinProc;
wc.lpszClassName
=(LPSTR)cName;
wc.lpszMenuName
= NULL;
wc.style
= CS_HREDRAW | CS_VREDRAW;

RegisterClassEx(
&wc);
hMenuShort
= LoadMenu(hInstance,MAKEINTRESOURCE(IDM_SHORTCUT));
hMenu
= LoadMenu(hInstance,MAKEINTRESOURCE(IDM_MAIN));
hWnd
= CreateWindowEx(WS_EX_CLIENTEDGE,cName,cCaption,WS_OVERLAPPEDWINDOW,
400,300,300,200,NULL,hMenu,hInstance,NULL);
if(hWnd == NULL)
{
//容错处理
MessageBox(NULL,"There's an Error","Error Title",MB_ICONEXCLAMATION|MB_OK);
return 0;
}
ShowWindow(hWnd,nShowCmd);
//显示窗口
UpdateWindow(hWnd);

//获取快捷键句柄
hAccel=LoadAccelerators(hInstance,MAKEINTRESOURCE(IDA_MAIN));

while(GetMessage(&Msg,NULL,0,0))
{
//先判断是不是快捷键消息
if(!TranslateAccelerator(hWnd,hAccel,&Msg))
{
TranslateMessage(
&Msg);//翻译消息
DispatchMessage(&Msg);//分派消息
}
}
return Msg.message;
}

 

贴个图
疯狂C 时代
不好意思,照的时候,它头一偏,结果一部没照到,不过要看的部分都有,大家就将就下了,如果你不将就看的话,那就自
己写一个出来了,哈。其实我是很希望你们能够自己写,不要直接Ctrl+C、Ctrl+V就可以了,就是抄,也希望你能够亲自讲
那些羞涩的字符敲进去。因为编程时才能发现错误,解决了错误,你就进步了,如果我上面的代码没有错的话,你直接复制
粘贴就了事了,即使你说你没一行代码都看过了,都理解了,但我可以肯定的说你没有进步(针对没有写过这类程序的人说
的,知道的飞过)。谦虚使人进步,你想成为高手吗,那就虚心地去写代码去吧。
posted on 2010-03-05 19:47  沧桑不尽  阅读(818)  评论(0编辑  收藏  举报