请先查阅有BitMap的Menu取得Menu的相关知识,再查如何拦截ComboBoxMouseMove的SubClass之技巧一些商业软件中,当滑鼠指向某个MenuItem时,在表单的底部STATUSBAR中会显示有该Item功能的简要说明。而VB5中有关Menu的捕捉事件只有一个CLICK,那该如何做呢。其实当选择了Menu後,Mouse在MenuSubMenuMenuItem上移来移去时,会产生WM_MENUSELECT的Message给Menu所在的表单,而其wParam的LowWord有两个意义,如果Mouse指到的Item之下还有子Menu,该LowWordofwParam指的是该Item是第几个SubMenu,而lParam便是Menu的Handle;相反的,如果Mouse所指的Item底下没有PopupMenu了,那LowWordofwParam指的是MenuID,而lParam是hSubMenu。
档案编辑选项-->hMenu(功能表,Menu) ------- |复制|--------->hSubMenu(子功能表,SubMenu) |贴上| |减下------------->MenuID(功能表项目,MenuItem) || -------
所以了,这就得使用SubClass的技巧,取得WM_MENUSELECT的Message,进而得知到底是选到了哪一个MenuItem。当然了,我们可以使用GetMenuGetSubMenuGetMenuItemID等API来得知功能表上每一个项目的hMenuhSubMenuMenuID,如此一来,和WM_MENUSELECT讯息所取得的lParamwParam做做比较,就可得知到底选上了哪一个,而本例则是使用GetMenuString取得MenuItem的title,如果您的MenuItems没有相同的title,也不失一得知方式。
'以下在form,请自行加Menu於Form上 PrivateSubForm_Load() DimretAsLong hMenu=GetMenu(Me.hwnd)
'记录原本的WindowProcedure的位址 preWinProc=GetWindowLong(Me.hwnd,GWL_WNDPROC) '设定Combo1的windowProcedure到wndproc ret=SetWindowLong(Me.hwnd,GWL_WNDPROC,AddressOfwndproc) EndSub
PrivateSubForm_Unload(CancelAsInteger) DimretAsLong '取消Message的截取,而使之又只送往原来的WindowProcedure ret=SetWindowLong(Me.hwnd,GWL_WNDPROC,preWinProc) EndSub
'以下在.Bas '以下程式在module1.bas DeclareFunctionSetWindowLongLib"user32"Alias"SetWindowLongA"_ (ByValhwndAsLong,ByValnIndexAsLong,ByValdwNewLongAsLong)AsLong DeclareFunctionGetWindowLongLib"user32"Alias"GetWindowLongA"_ (ByValhwndAsLong,ByValnIndexAsLong)AsLong DeclareFunctionCallWindowProcLib"user32"Alias"CallWindowProcA"_ (ByVallpPrevWndFuncAsLong,ByValhwndAsLong,ByValMsgAsLong,_ ByValwParamAsLong,ByVallParamAsLong)AsLong DeclareFunctionGetMenuStringLib"user32"Alias"GetMenuStringA"(ByValhMenuAsLong,ByValwIDItemAsLong,ByVallpStringAsString,ByValnMaxCountAsLong,ByValwFlagAsLong)AsLong DeclareFunctionGetMenuLib"user32"(ByValhwndAsLong)AsLong DeclareFunctionGetSubMenuLib"user32"(ByValhMenuAsLong,ByValnPosAsLong)AsLong
PublicConstGWL_WNDPROC=(-4) PublicConstWM_MENUSELECT=&H11F PublicConstMF_BYCOMMAND=&H0& PublicConstMF_BYPOSITION=&H400&
PublichMenuAsLong PublicpreWinProcAsLong PrivateTypetLong llAsLong EndType PrivateTypeTwoWord LowWordAsInteger HiWordAsInteger EndType PublicFunctionwndproc(ByValhwndAsLong,ByValMsgAsLong,_ ByValwParamAsLong,ByVallParamAsLong)AsLong DimMenuItemStrAsString,SubMenuStrAsString DimhSubmenuAsLong,MenuIdAsLong,iAsLong DimtmplAstLong,tmptAsTwoWord '以下程式会截取WM_MENUSELECT处理完後,再将之送往原来的WindowProcedure IfMsg=WM_MENUSELECTThen SubMenuStr=String(255,0) MenuItemStr=String(255,0)
tmpl.ll=wParam LSettmpt=tmpl MenuId=tmpt.LowWord
hSubmenu=GetSubMenu(lParam,MenuId) IfhSubmenu=0Then'表示该item之下没有popupMenu了 CallGetMenuString(lParam,MenuId,MenuItemStr,256,MF_BYCOMMAND) MenuItemStr=Left(MenuItemStr,InStr(1,MenuItemStr,Chr(0))-1) Debug.Print"正在MenuItem" MenuItemStr Else CallGetMenuString(hMenu,hSubmenu,SubMenuStr,256,MF_BYCOMMAND) SubMenuStr=Left(SubMenuStr,InStr(1,SubMenuStr,Chr(0))-1) Debug.Print"正在PopUpMenu" SubMenuStr EndIf EndIf '将之送往原来的WindowProcedure wndproc=CallWindowProc(preWinProc,hwnd,Msg,wParam,lParam) EndFunction->
|