(两年无解之题?)怎样获取TEdit的默认右键菜单(ContextMenu)的句柄 (200分)

  • 主题发起人 kaithink
  • 开始时间
晕 ,看了半天你的代码都没想出怎么搞<br>楼上,我以为你说不行呢<br><br>怎么试法,钩子我不会啊,我就想要句柄,你帮我写出来吧<br><br>42753005我的QQ号<br>kaithink@msn.com我的MSN<br><br>大家都加我啊,谈论问题直接些,结果我会贴在这里结贴,分数绝不含糊!
 
先收藏一下,
 
直接了当最好 谁能给一个可以运行原代码来?
 
在VCL中是不可能做到的,因为原始的Windows中的edit就有这个菜单。
 
我也收藏一下了!
 
{ 单元名称: MenuSubClass.pas<br>&nbsp; 功能简介: 通过Hook拦截菜单句柄,包括Tedit的右键菜单<br>&nbsp; &nbsp; &nbsp; &nbsp; 作者: Deityfox<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;QQ : 58193693<br>&nbsp; &nbsp; &nbsp; &nbsp; MSN: Deityfox@hotmail.com<br>}<br>unit MenuSubClass;<br><br>interface<br><br>uses<br>&nbsp; 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>&nbsp; TCallbackThunk = packed record<br>&nbsp; &nbsp; POPEDX: Byte;<br>&nbsp; &nbsp; MOVEAX: Byte;<br>&nbsp; &nbsp; SelfPtr: Pointer;<br>&nbsp; &nbsp; PUSHEAX: Byte;<br>&nbsp; &nbsp; PUSHEDX: Byte;<br>&nbsp; &nbsp; JMP: Byte;<br>&nbsp; &nbsp; JmpOffset: Integer;<br>&nbsp; end;<br><br><br>&nbsp; TMenuHookCallback =<br>&nbsp; &nbsp; &nbsp; procedure(code: Integer; wparam: WPARAM; lparam: LPARAM) of object;<br><br>&nbsp; TOSType=( Win32s,WinNT3,Win95,Win98,WinME,WinNT4,Win2000,WinXP,Win2003);<br>&nbsp; TMenuSubClass = class(TComponent)<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; log:tstringlist;<br>&nbsp; &nbsp; FHook &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : HHOOK;<br>&nbsp; &nbsp; FThunk,FThunk1 &nbsp; &nbsp; &nbsp; &nbsp;: TCallbackThunk;<br>&nbsp; &nbsp; bSysMenu &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Boolean;<br>&nbsp; &nbsp; NewProc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Pointer;<br>&nbsp; &nbsp; OldProc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Longint;<br>&nbsp; &nbsp; HookProc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Pointer;<br><br><br>&nbsp; &nbsp; function MenuCallBack(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT;stdcall;<br><br>&nbsp; protected<br>&nbsp; &nbsp; { Protected declarations }<br><br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; &nbsp; constructor Create(AOwner: TComponent); override;<br>&nbsp; &nbsp; destructor Destroy; override;<br><br><br>&nbsp; published<br>&nbsp; &nbsp; { Published declarations }<br>&nbsp; end;<br><br>procedure Register;<br><br>implementation<br><br>procedure Register;<br>begin<br>&nbsp; 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>&nbsp; lparam: LPARAM): LRESULT;<br>var<br>&nbsp; cwps: TCWPStruct;<br>&nbsp; lRet: Longint;<br>&nbsp; szClass: array[0..8] of char;<br>&nbsp; MenuHwnd:Hwnd;<br>begin<br>if (Code = HC_ACTION) then<br>begin<br>&nbsp; CopyMemory(@cwps, Pointer(lParam), SizeOf(CWPSTRUCT));<br>&nbsp; case cwps.message of<br>&nbsp; &nbsp; WM_CONTEXTMENU:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; //判断是否Tedit<br>&nbsp; &nbsp; &nbsp; GetClassName(cwps.wParam, szClass, Length(szClass)-1);<br>&nbsp; &nbsp; &nbsp; if (lstrcmpi(szClass,EDIT_CLASS) = 0) then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp;//Tedit 的句柄<br>&nbsp; &nbsp; &nbsp; &nbsp; log.add('TEdit Handle: '+inttostr(cwps.wParam));<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; WM_INITMENUPOPUP:<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; log.add('WM_INITMENUPOPUP ');<br>&nbsp; &nbsp; //判断是否系统菜单<br>&nbsp; &nbsp; if (getSystemmenu(cwps.hwnd,false)=cwps.wParam) or (hiword(cwps.lParam)&lt;&gt;0) then<br>&nbsp; &nbsp; &nbsp; bSysMenu:=true<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; bSysMenu:=false;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; //特殊的菜单??如果没有这个消息好像在9x有些菜单钩不住<br>&nbsp; &nbsp; WM_SPECIAL: //$01E2 SPECIAL Menu???<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; log.add('WM_SPECIAL '+inttostr(CWPs.hwnd));<br>&nbsp; &nbsp; &nbsp; GetClassName(cwps.hwnd, szClass, Length(szClass)-1);<br>&nbsp; &nbsp; &nbsp; &nbsp;// Window name for menu is #32768<br>&nbsp; &nbsp; &nbsp; &nbsp;if (lstrcmpi(szClass, MENU_CLASS) = 0) and (not bSysMenu) then<br>&nbsp; &nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.add('WM_SPECIAL '+inttostr(CWPs.hwnd));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//cwps.hwnd就是菜单的句柄 &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;////<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //可以对菜单进行子类化 <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; end;<br><br>&nbsp; &nbsp; WM_CREATE:<br>&nbsp; &nbsp; begin<br><br>&nbsp; &nbsp; &nbsp; GetClassName(cwps.hwnd, szClass, Length(szClass)-1);<br>&nbsp; &nbsp; &nbsp; &nbsp;// Window name for menu is #32768<br>&nbsp; &nbsp; &nbsp; &nbsp;if (lstrcmpi(szClass, MENU_CLASS) = 0) and (not bSysMenu) then<br>&nbsp; &nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.add('WM_CREATE '+inttostr(CWPs.hwnd));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//cwps.hwnd就是菜单的句柄 &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;////<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//可以对菜单进行子类化<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; WM_UNINITMENUPOPUP:bSysMenu:=false;<br>&nbsp; end;<br>&nbsp; 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>&nbsp; inherited Create(AOwner);<br>&nbsp; log:=tstringlist.Create;<br>&nbsp; if not (csDesigning in ComponentState) then<br>&nbsp; begin<br>&nbsp; &nbsp; FThunk.POPEDX:= $5A;<br>&nbsp; &nbsp; FThunk.MOVEAX:= $B8;<br>&nbsp; &nbsp; FThunk.SelfPtr:= Self;<br>&nbsp; &nbsp; FThunk.PUSHEAX:= $50;<br>&nbsp; &nbsp; FThunk.PUSHEDX:= $52;<br>&nbsp; &nbsp; FThunk.JMP:= $E9;<br>&nbsp; &nbsp; FThunk.JmpOffset:= Integer(@TMenuSubClass.MenuCallBack)-Integer(@FThunk.JMP)-5;<br>&nbsp; &nbsp; FHook:= SetWindowsHookEx(WH_CALLWNDPROC, TFNHookProc(@FThunk), 0, MainThreadID);<br>&nbsp; end;<br>end;<br><br>destructor TMenuSubClass.Destroy;<br>begin<br>&nbsp; log.SaveToFile('e:/log.txt');<br>&nbsp; log.Free;<br>&nbsp; if not (csDesigning in ComponentState) then<br>&nbsp; &nbsp; UnhookWindowsHookEx(FHook);<br>&nbsp; inherited Destroy;<br>end;<br>end.<br>
 
楼上<br>正在试验中。。。
 
谁再帮我加一个加菜单项<br>我试了几次不得其法,加不进,否则无法知道那个句柄到底是不是右键菜单的句柄。
 
问题要有人来回答,<br>那就得经常顶~<br>就向做广告一样,收视率最重要呀~<br>我顶,我顶, 我帮你顶~<br>自已也要顶呀~<br>而且,会号召别人帮你顶,那才行~
 
楼上正解,我顶
 
to kaithink:<br>&nbsp; DeityFox已给出方法,如果你还不太清楚就看看《DELPHI下深入WINDOWS核心编程》,上面对钩子介绍的相当详细。
 
谢谢楼上推荐,书我会找来看的<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>这就把分散了
 
请问菜单的柄是叫HMENU<br>窗口的柄是叫HWND,这两者有什么关系????<br><br>参考WM_ENTERIDLE可知道弹出式菜单(PopupMenu)其实还有一个关联(我还没弄清楚这两者的关系)着的窗口。<br>我们可以得到这个窗口柄TMessage(Message).LParam<br>但是如何从这个窗口上弄到HMENU....<br><br>Type<br>&nbsp; TMyEdit = class(TEdit)<br>&nbsp; public<br>&nbsp; &nbsp; procedure DefaultHandler(var Message); override;<br>&nbsp; &nbsp; procedure WndProc(var Message: TMessage); override;<br>&nbsp; end;<br><br>procedure TMyEdit.DefaultHandler(var Message);<br>begin<br>// &nbsp;inherited DefaultHandler(Message);<br>&nbsp; with TMessage(Message) do<br>&nbsp; begin<br>&nbsp; &nbsp; case Msg of<br>&nbsp; &nbsp; &nbsp; WM_ContextMenu: begin<br>&nbsp; &nbsp; &nbsp; &nbsp; (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_ContextMenu');<br>&nbsp; &nbsp; &nbsp; &nbsp; inherited DefaultHandler(Message);<br>&nbsp; &nbsp; &nbsp; &nbsp; //(Owner as TFrmTest).Caption := 'After DefaultHandler';<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; WM_ENTERMENULOOP:<br>&nbsp; &nbsp; &nbsp; &nbsp; (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_ENTERMENULOOP');<br>&nbsp; &nbsp; &nbsp; WM_INITMENUPOPUP:<br>&nbsp; &nbsp; &nbsp; &nbsp; (Owner as TFrmTest).MmTest.Lines.Add('DefaultHandler WM_INITMENUPOPUP');<br>&nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; inherited DefaultHandler(Message);<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br>end;<br><br>procedure EnumChildProc(var wnd: HWND; lParam: LongInt);<br>begin<br>&nbsp; FrmTest.MmTest.Lines.Add(format('0x%x', [wnd]));<br>end;<br><br>procedure TMyEdit.WndProc(var Message: TMessage);<br>var<br>&nbsp; lpEnumFunc: Pointer;<br>begin<br>// &nbsp;inherited;<br>&nbsp; case Message.Msg of<br>&nbsp; &nbsp; WM_ENTERMENULOOP:<br>&nbsp; &nbsp; &nbsp; (Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_ENTERMENULOOP');<br>&nbsp; &nbsp; WM_INITMENUPOPUP:<br>&nbsp; &nbsp; &nbsp; (Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_INITMENUPOPUP');<br>&nbsp; &nbsp; WM_ENTERIDLE: begin<br>&nbsp; &nbsp; &nbsp; //(Owner as TFrmTest).MmTest.Lines.Add('WndProc WM_ENTERIDLE');<br>&nbsp; &nbsp; &nbsp; if (Message.wParam = MSGF_MENU) then<br>&nbsp; &nbsp; &nbsp; &nbsp; //if (Message.lParam = Handle) then<br>&nbsp; &nbsp; &nbsp; &nbsp; (Owner as TFrmTest).MmTest.Lines.Add(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; format('WndProc Menu Found MSGF_MENU 0x%x', [Message.LParam]));<br>&nbsp; &nbsp; &nbsp; &nbsp; //ShowWindow(Message.LParam, SW_HIDE);<br>&nbsp; &nbsp; &nbsp; &nbsp; //SetWindowPos(Message.LParam, 0, 10, 10, 20, 20, SWP_SHOWWINDOW);<br>&nbsp; &nbsp; &nbsp; &nbsp; //ShowWindow(Message.LParam, SW_SHOW);<br>&nbsp; &nbsp; &nbsp; &nbsp; lpEnumFunc := @EnumChildProc;<br>&nbsp; &nbsp; &nbsp; &nbsp; if EnumChildWindows(Message.LParam, lpEnumFunc, 0) = false then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(Owner as TFrmTest).MmTest.Lines.Add('EnumChildWindows Error');<br>&nbsp; &nbsp; &nbsp; &nbsp; if (IsMenu(GetMenu(Message.LParam))) then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (Owner as TFrmTest).Caption := 'Found MENU Handle'<br>&nbsp; &nbsp; &nbsp; &nbsp; else (Owner as TFrmTest).Caption := 'No Menu Handle Found';<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; //else<br>&nbsp; &nbsp; // &nbsp;(Owner as TFrmTest).MmTest.Lines.Add('WndProc Msg else');<br>&nbsp; end;<br>&nbsp; inherited;<br>end;
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
624
import
I
I
回复
0
查看
556
import
I
顶部