K kaithink Unregistered / Unconfirmed GUEST, unregistred user! 2003-09-24 #21 晕 ,看了半天你的代码都没想出怎么搞<br>楼上,我以为你说不行呢<br><br>怎么试法,钩子我不会啊,我就想要句柄,你帮我写出来吧<br><br>42753005我的QQ号<br>kaithink@msn.com我的MSN<br><br>大家都加我啊,谈论问题直接些,结果我会贴在这里结贴,分数绝不含糊!
晕 ,看了半天你的代码都没想出怎么搞<br>楼上,我以为你说不行呢<br><br>怎么试法,钩子我不会啊,我就想要句柄,你帮我写出来吧<br><br>42753005我的QQ号<br>kaithink@msn.com我的MSN<br><br>大家都加我啊,谈论问题直接些,结果我会贴在这里结贴,分数绝不含糊!
B bluebridge Unregistered / Unconfirmed GUEST, unregistred user! 2003-09-24 #24 在VCL中是不可能做到的,因为原始的Windows中的edit就有这个菜单。
D DeityFox Unregistered / Unconfirmed GUEST, unregistred user! 2003-09-24 #26 { 单元名称: MenuSubClass.pas<br> 功能简介: 通过Hook拦截菜单句柄,包括Tedit的右键菜单<br> 作者: Deityfox<br> QQ : 58193693<br> MSN: Deityfox@hotmail.com<br>}<br>unit MenuSubClass;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms;<br><br>const<br>WM_SPECIAL=$01E2; //SPECIAL menu<br>MENU_CLASS = '#32768';<br>EDIT_CLASS='TEdit';<br><br>type<br> TCallbackThunk = packed record<br> POPEDX: Byte;<br> MOVEAX: Byte;<br> SelfPtr: Pointer;<br> PUSHEAX: Byte;<br> PUSHEDX: Byte;<br> JMP: Byte;<br> JmpOffset: Integer;<br> end;<br><br><br> TMenuHookCallback =<br> procedure(code: Integer; wparam: WPARAM; lparam: LPARAM) of object;<br><br> TOSType=( Win32s,WinNT3,Win95,Win98,WinME,WinNT4,Win2000,WinXP,Win2003);<br> TMenuSubClass = class(TComponent)<br> private<br> { Private declarations }<br> log:tstringlist;<br> FHook : HHOOK;<br> FThunk,FThunk1 : TCallbackThunk;<br> bSysMenu : Boolean;<br> NewProc : Pointer;<br> OldProc : Longint;<br> HookProc : Pointer;<br><br><br> function MenuCallBack(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT;stdcall;<br><br> protected<br> { Protected declarations }<br><br> public<br> { Public declarations }<br> constructor Create(AOwner: TComponent); override;<br> destructor Destroy; override;<br><br><br> published<br> { Published declarations }<br> end;<br><br>procedure Register;<br><br>implementation<br><br>procedure Register;<br>begin<br> RegisterComponents('foxVCL', [TMenuSubClass]);<br>end;<br><br><br><br>{ TMenuSubClass }<br><br><br>//hook CallBack Procedure<br>function TMenuSubClass.MenuCallBack(code: Integer; wparam: WPARAM;<br> lparam: LPARAM): LRESULT;<br>var<br> cwps: TCWPStruct;<br> lRet: Longint;<br> szClass: array[0..8] of char;<br> MenuHwnd:Hwnd;<br>begin<br>if (Code = HC_ACTION) then<br>begin<br> CopyMemory(@cwps, Pointer(lParam), SizeOf(CWPSTRUCT));<br> case cwps.message of<br> WM_CONTEXTMENU:<br> begin<br> //判断是否Tedit<br> GetClassName(cwps.wParam, szClass, Length(szClass)-1);<br> if (lstrcmpi(szClass,EDIT_CLASS) = 0) then<br> begin<br> //Tedit 的句柄<br> log.add('TEdit Handle: '+inttostr(cwps.wParam));<br> end;<br> end;<br> WM_INITMENUPOPUP:<br> begin<br> log.add('WM_INITMENUPOPUP ');<br> //判断是否系统菜单<br> if (getSystemmenu(cwps.hwnd,false)=cwps.wParam) or (hiword(cwps.lParam)<>0) then<br> bSysMenu:=true<br> else<br> bSysMenu:=false;<br> end;<br> //特殊的菜单??如果没有这个消息好像在9x有些菜单钩不住<br> WM_SPECIAL: //$01E2 SPECIAL Menu???<br> begin<br> log.add('WM_SPECIAL '+inttostr(CWPs.hwnd));<br> GetClassName(cwps.hwnd, szClass, Length(szClass)-1);<br> // Window name for menu is #32768<br> if (lstrcmpi(szClass, MENU_CLASS) = 0) and (not bSysMenu) then<br> begin<br> log.add('WM_SPECIAL '+inttostr(CWPs.hwnd));<br> //cwps.hwnd就是菜单的句柄 <br> ////<br> //可以对菜单进行子类化 <br> end;<br> end;<br> end;<br><br> WM_CREATE:<br> begin<br><br> GetClassName(cwps.hwnd, szClass, Length(szClass)-1);<br> // Window name for menu is #32768<br> if (lstrcmpi(szClass, MENU_CLASS) = 0) and (not bSysMenu) then<br> begin<br> log.add('WM_CREATE '+inttostr(CWPs.hwnd));<br> //cwps.hwnd就是菜单的句柄 <br> ////<br> //可以对菜单进行子类化<br> end;<br> end;<br> end;<br> WM_UNINITMENUPOPUP:bSysMenu:=false;<br> end;<br> Result:=0;<br>end;<br>// Call the next hook in the chain<br>Result := CallNextHookEx(WH_CALLWNDPROC, Code, wParam, lParam);<br><br>end;<br><br><br><br>constructor TMenuSubClass.Create(AOwner: TComponent);<br>begin<br> inherited Create(AOwner);<br> log:=tstringlist.Create;<br> if not (csDesigning in ComponentState) then<br> begin<br> FThunk.POPEDX:= $5A;<br> FThunk.MOVEAX:= $B8;<br> FThunk.SelfPtr:= Self;<br> FThunk.PUSHEAX:= $50;<br> FThunk.PUSHEDX:= $52;<br> FThunk.JMP:= $E9;<br> FThunk.JmpOffset:= Integer(@TMenuSubClass.MenuCallBack)-Integer(@FThunk.JMP)-5;<br> FHook:= SetWindowsHookEx(WH_CALLWNDPROC, TFNHookProc(@FThunk), 0, MainThreadID);<br> end;<br>end;<br><br>destructor TMenuSubClass.Destroy;<br>begin<br> log.SaveToFile('e:/log.txt');<br> log.Free;<br> if not (csDesigning in ComponentState) then<br> UnhookWindowsHookEx(FHook);<br> inherited Destroy;<br>end;<br>end.<br>
{ 单元名称: MenuSubClass.pas<br> 功能简介: 通过Hook拦截菜单句柄,包括Tedit的右键菜单<br> 作者: Deityfox<br> QQ : 58193693<br> MSN: Deityfox@hotmail.com<br>}<br>unit MenuSubClass;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms;<br><br>const<br>WM_SPECIAL=$01E2; //SPECIAL menu<br>MENU_CLASS = '#32768';<br>EDIT_CLASS='TEdit';<br><br>type<br> TCallbackThunk = packed record<br> POPEDX: Byte;<br> MOVEAX: Byte;<br> SelfPtr: Pointer;<br> PUSHEAX: Byte;<br> PUSHEDX: Byte;<br> JMP: Byte;<br> JmpOffset: Integer;<br> end;<br><br><br> TMenuHookCallback =<br> procedure(code: Integer; wparam: WPARAM; lparam: LPARAM) of object;<br><br> TOSType=( Win32s,WinNT3,Win95,Win98,WinME,WinNT4,Win2000,WinXP,Win2003);<br> TMenuSubClass = class(TComponent)<br> private<br> { Private declarations }<br> log:tstringlist;<br> FHook : HHOOK;<br> FThunk,FThunk1 : TCallbackThunk;<br> bSysMenu : Boolean;<br> NewProc : Pointer;<br> OldProc : Longint;<br> HookProc : Pointer;<br><br><br> function MenuCallBack(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT;stdcall;<br><br> protected<br> { Protected declarations }<br><br> public<br> { Public declarations }<br> constructor Create(AOwner: TComponent); override;<br> destructor Destroy; override;<br><br><br> published<br> { Published declarations }<br> end;<br><br>procedure Register;<br><br>implementation<br><br>procedure Register;<br>begin<br> RegisterComponents('foxVCL', [TMenuSubClass]);<br>end;<br><br><br><br>{ TMenuSubClass }<br><br><br>//hook CallBack Procedure<br>function TMenuSubClass.MenuCallBack(code: Integer; wparam: WPARAM;<br> lparam: LPARAM): LRESULT;<br>var<br> cwps: TCWPStruct;<br> lRet: Longint;<br> szClass: array[0..8] of char;<br> MenuHwnd:Hwnd;<br>begin<br>if (Code = HC_ACTION) then<br>begin<br> CopyMemory(@cwps, Pointer(lParam), SizeOf(CWPSTRUCT));<br> case cwps.message of<br> WM_CONTEXTMENU:<br> begin<br> //判断是否Tedit<br> GetClassName(cwps.wParam, szClass, Length(szClass)-1);<br> if (lstrcmpi(szClass,EDIT_CLASS) = 0) then<br> begin<br> //Tedit 的句柄<br> log.add('TEdit Handle: '+inttostr(cwps.wParam));<br> end;<br> end;<br> WM_INITMENUPOPUP:<br> begin<br> log.add('WM_INITMENUPOPUP ');<br> //判断是否系统菜单<br> if (getSystemmenu(cwps.hwnd,false)=cwps.wParam) or (hiword(cwps.lParam)<>0) then<br> bSysMenu:=true<br> else<br> bSysMenu:=false;<br> end;<br> //特殊的菜单??如果没有这个消息好像在9x有些菜单钩不住<br> WM_SPECIAL: //$01E2 SPECIAL Menu???<br> begin<br> log.add('WM_SPECIAL '+inttostr(CWPs.hwnd));<br> GetClassName(cwps.hwnd, szClass, Length(szClass)-1);<br> // Window name for menu is #32768<br> if (lstrcmpi(szClass, MENU_CLASS) = 0) and (not bSysMenu) then<br> begin<br> log.add('WM_SPECIAL '+inttostr(CWPs.hwnd));<br> //cwps.hwnd就是菜单的句柄 <br> ////<br> //可以对菜单进行子类化 <br> end;<br> end;<br> end;<br><br> WM_CREATE:<br> begin<br><br> GetClassName(cwps.hwnd, szClass, Length(szClass)-1);<br> // Window name for menu is #32768<br> if (lstrcmpi(szClass, MENU_CLASS) = 0) and (not bSysMenu) then<br> begin<br> log.add('WM_CREATE '+inttostr(CWPs.hwnd));<br> //cwps.hwnd就是菜单的句柄 <br> ////<br> //可以对菜单进行子类化<br> end;<br> end;<br> end;<br> WM_UNINITMENUPOPUP:bSysMenu:=false;<br> end;<br> Result:=0;<br>end;<br>// Call the next hook in the chain<br>Result := CallNextHookEx(WH_CALLWNDPROC, Code, wParam, lParam);<br><br>end;<br><br><br><br>constructor TMenuSubClass.Create(AOwner: TComponent);<br>begin<br> inherited Create(AOwner);<br> log:=tstringlist.Create;<br> if not (csDesigning in ComponentState) then<br> begin<br> FThunk.POPEDX:= $5A;<br> FThunk.MOVEAX:= $B8;<br> FThunk.SelfPtr:= Self;<br> FThunk.PUSHEAX:= $50;<br> FThunk.PUSHEDX:= $52;<br> FThunk.JMP:= $E9;<br> FThunk.JmpOffset:= Integer(@TMenuSubClass.MenuCallBack)-Integer(@FThunk.JMP)-5;<br> FHook:= SetWindowsHookEx(WH_CALLWNDPROC, TFNHookProc(@FThunk), 0, MainThreadID);<br> end;<br>end;<br><br>destructor TMenuSubClass.Destroy;<br>begin<br> log.SaveToFile('e:/log.txt');<br> log.Free;<br> if not (csDesigning in ComponentState) then<br> UnhookWindowsHookEx(FHook);<br> inherited Destroy;<br>end;<br>end.<br>
K kaithink Unregistered / Unconfirmed GUEST, unregistred user! 2003-09-24 #28 谁再帮我加一个加菜单项<br>我试了几次不得其法,加不进,否则无法知道那个句柄到底是不是右键菜单的句柄。
D DouZheng Unregistered / Unconfirmed GUEST, unregistred user! 2003-09-24 #29 问题要有人来回答,<br>那就得经常顶~<br>就向做广告一样,收视率最重要呀~<br>我顶,我顶, 我帮你顶~<br>自已也要顶呀~<br>而且,会号召别人帮你顶,那才行~
3 328xy Unregistered / Unconfirmed GUEST, unregistred user! 2003-09-24 #31 to kaithink:<br> DeityFox已给出方法,如果你还不太清楚就看看《DELPHI下深入WINDOWS核心编程》,上面对钩子介绍的相当详细。
K kaithink Unregistered / Unconfirmed GUEST, unregistred user! 2003-09-24 #32 谢谢楼上推荐,书我会找来看的<br>我不是偷懒光等别人的答案<br><br>这个问题在提出后我问遍了跟前所有认识的程序员(还有一个搞VC图形图像搞了好些年的)<br>没有人答得上来<br>自己也瞎试了几个下午而不可得<br>也难怪<br>大家长时间都在做数据库应用<br>弱是肯定的<br><br>每个我问到的人都会问我要干什么<br>我一开始说要加一个菜单项进去<br>于是每个人都说何必那么麻烦<br>弄个TPOPMENU把剪切粘贴删除一搞不是随便你整<br><br>这种回答我认为是现实的可取的<br>但是又有点无可奈何的感觉<br><br>用google,能想到的能组合的关键词全都试了,未有所获<br>偶尔有一两个和我一样钻了牛角尖的贴子也大都无果而终<br><br>这个问题的意义倒底在哪里<br>我自己已经搞不清楚了<br><br>上面用钩子找到的是否是右键菜单的句柄<br>我现时的水平(在未看书之前)暂时是不知道了<br>不过我还是谢谢所有关注这个贴子的朋友<br>如果后面我加入菜单成功(我想所有提这个问题的朋友基本就是这个目的)<br>我会把完整方案贴上来(只要大富翁不提示灌水)<br>以便有钻了这个牛角尖的朋友不会空手而回<br><br>这就把分散了
谢谢楼上推荐,书我会找来看的<br>我不是偷懒光等别人的答案<br><br>这个问题在提出后我问遍了跟前所有认识的程序员(还有一个搞VC图形图像搞了好些年的)<br>没有人答得上来<br>自己也瞎试了几个下午而不可得<br>也难怪<br>大家长时间都在做数据库应用<br>弱是肯定的<br><br>每个我问到的人都会问我要干什么<br>我一开始说要加一个菜单项进去<br>于是每个人都说何必那么麻烦<br>弄个TPOPMENU把剪切粘贴删除一搞不是随便你整<br><br>这种回答我认为是现实的可取的<br>但是又有点无可奈何的感觉<br><br>用google,能想到的能组合的关键词全都试了,未有所获<br>偶尔有一两个和我一样钻了牛角尖的贴子也大都无果而终<br><br>这个问题的意义倒底在哪里<br>我自己已经搞不清楚了<br><br>上面用钩子找到的是否是右键菜单的句柄<br>我现时的水平(在未看书之前)暂时是不知道了<br>不过我还是谢谢所有关注这个贴子的朋友<br>如果后面我加入菜单成功(我想所有提这个问题的朋友基本就是这个目的)<br>我会把完整方案贴上来(只要大富翁不提示灌水)<br>以便有钻了这个牛角尖的朋友不会空手而回<br><br>这就把分散了
W wlmmlw Unregistered / Unconfirmed GUEST, unregistred user! 2003-09-27 #33 请问菜单的柄是叫HMENU<br>窗口的柄是叫HWND,这两者有什么关系????<br><br>参考WM_ENTERIDLE可知道弹出式菜单(PopupMenu)其实还有一个关联(我还没弄清楚这两者的关系)着的窗口。<br>我们可以得到这个窗口柄TMessage(Message).LParam<br>但是如何从这个窗口上弄到HMENU....<br><br>Type<br> TMyEdit = class(TEdit)<br> public<br> procedure DefaultHandler(var Message); override;<br> procedure WndProc(var Message: TMessage); override;<br> end;<br><br>procedure TMyEdit.DefaultHandler(var Message);<br>begin<br>// inherited DefaultHandler(Message);<br> with TMessage(Message) do<br> begin<br> case Msg of<br> WM_ContextMenu: begin<br> (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_ContextMenu');<br> inherited DefaultHandler(Message);<br> //(Owner as TFrmTest).Caption := 'After DefaultHandler';<br> end;<br> WM_ENTERMENULOOP:<br> (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_ENTERMENULOOP');<br> WM_INITMENUPOPUP:<br> (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_INITMENUPOPUP');<br> else<br> inherited DefaultHandler(Message);<br> end;<br> end;<br>end;<br><br>procedure EnumChildProc(var wnd: HWND; lParam: LongInt);<br>begin<br> FrmTest.MmTest.Lines.Add(format('0x%x', [wnd]));<br>end;<br><br>procedure TMyEdit.WndProc(var Message: TMessage);<br>var<br> lpEnumFunc: Pointer;<br>begin<br>// inherited;<br> case Message.Msg of<br> WM_ENTERMENULOOP:<br> (Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_ENTERMENULOOP');<br> WM_INITMENUPOPUP:<br> (Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_INITMENUPOPUP');<br> WM_ENTERIDLE: begin<br> //(Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_ENTERIDLE');<br> if (Message.wParam = MSGF_MENU) then<br> //if (Message.lParam = Handle) then<br> (Owner as TFrmTest).MmTest.Lines.Add(<br> format('WndProc Menu Found MSGF_MENU 0x%x', [Message.LParam]));<br> //ShowWindow(Message.LParam, SW_HIDE);<br> //SetWindowPos(Message.LParam, 0, 10, 10, 20, 20, SWP_SHOWWINDOW);<br> //ShowWindow(Message.LParam, SW_SHOW);<br> lpEnumFunc := @EnumChildProc;<br> if EnumChildWindows(Message.LParam, lpEnumFunc, 0) = false then<br> (Owner as TFrmTest).MmTest.Lines.Add('EnumChildWindows Error');<br> if (IsMenu(GetMenu(Message.LParam))) then<br> (Owner as TFrmTest).Caption := 'Found MENU Handle'<br> else (Owner as TFrmTest).Caption := 'No Menu Handle Found';<br> end;<br> //else<br> // (Owner as TFrmTest).MmTest.Lines.Add('WndProc Msg else');<br> end;<br> inherited;<br>end;
请问菜单的柄是叫HMENU<br>窗口的柄是叫HWND,这两者有什么关系????<br><br>参考WM_ENTERIDLE可知道弹出式菜单(PopupMenu)其实还有一个关联(我还没弄清楚这两者的关系)着的窗口。<br>我们可以得到这个窗口柄TMessage(Message).LParam<br>但是如何从这个窗口上弄到HMENU....<br><br>Type<br> TMyEdit = class(TEdit)<br> public<br> procedure DefaultHandler(var Message); override;<br> procedure WndProc(var Message: TMessage); override;<br> end;<br><br>procedure TMyEdit.DefaultHandler(var Message);<br>begin<br>// inherited DefaultHandler(Message);<br> with TMessage(Message) do<br> begin<br> case Msg of<br> WM_ContextMenu: begin<br> (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_ContextMenu');<br> inherited DefaultHandler(Message);<br> //(Owner as TFrmTest).Caption := 'After DefaultHandler';<br> end;<br> WM_ENTERMENULOOP:<br> (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_ENTERMENULOOP');<br> WM_INITMENUPOPUP:<br> (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_INITMENUPOPUP');<br> else<br> inherited DefaultHandler(Message);<br> end;<br> end;<br>end;<br><br>procedure EnumChildProc(var wnd: HWND; lParam: LongInt);<br>begin<br> FrmTest.MmTest.Lines.Add(format('0x%x', [wnd]));<br>end;<br><br>procedure TMyEdit.WndProc(var Message: TMessage);<br>var<br> lpEnumFunc: Pointer;<br>begin<br>// inherited;<br> case Message.Msg of<br> WM_ENTERMENULOOP:<br> (Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_ENTERMENULOOP');<br> WM_INITMENUPOPUP:<br> (Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_INITMENUPOPUP');<br> WM_ENTERIDLE: begin<br> //(Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_ENTERIDLE');<br> if (Message.wParam = MSGF_MENU) then<br> //if (Message.lParam = Handle) then<br> (Owner as TFrmTest).MmTest.Lines.Add(<br> format('WndProc Menu Found MSGF_MENU 0x%x', [Message.LParam]));<br> //ShowWindow(Message.LParam, SW_HIDE);<br> //SetWindowPos(Message.LParam, 0, 10, 10, 20, 20, SWP_SHOWWINDOW);<br> //ShowWindow(Message.LParam, SW_SHOW);<br> lpEnumFunc := @EnumChildProc;<br> if EnumChildWindows(Message.LParam, lpEnumFunc, 0) = false then<br> (Owner as TFrmTest).MmTest.Lines.Add('EnumChildWindows Error');<br> if (IsMenu(GetMenu(Message.LParam))) then<br> (Owner as TFrmTest).Caption := 'Found MENU Handle'<br> else (Owner as TFrmTest).Caption := 'No Menu Handle Found';<br> end;<br> //else<br> // (Owner as TFrmTest).MmTest.Lines.Add('WndProc Msg else');<br> end;<br> inherited;<br>end;