⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uhook.pas

📁 其他应用程序加菜单 如何给exe文件加个 菜单
💻 PAS
字号:
unit UHook;

interface

uses Windows, Messages, SysUtils, Controls, Menus, Forms;//, Dialogs;

type
  TMyObject = class(TObject)
    procedure MenuClick(Sender: TObject);
  end;


procedure InstallHook(MainWnd, DestWnd: HWND); stdcall;
procedure UninstallHook; stdcall;


implementation

uses UShare;

var
  ControlAtom: TAtom;
  ControlAtomString: string;
  RM_GetObjectInstance: DWORD;  // 自定义的windows消息,供不同的进程间使用
  MyObject: TMyObject;

procedure TMyObject.MenuClick(Sender: TObject);
begin
  WinExec('notepad.exe', SW_NORMAL);
end;  

//======================================================
//改造Delphi的FindControl函数
function FindControl(Handle: HWnd): TWinControl;
var
  OwningProcess: DWORD;
begin
  Result := nil;
  if (Handle <> 0) and (GetWindowThreadProcessID(Handle, OwningProcess) <> 0) and
     (OwningProcess = GetCurrentProcessId) then
  begin
    if GlobalFindAtom(PChar(ControlAtomString)) = ControlAtom then
      Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)))
    else
      Result := Pointer(SendMessage(Handle, RM_GetObjectInstance, 0, 0));
  end;
end;

//======================================================
//秘密窗口的回调函数,真正的工作就在这里
function MsgWndProc(hwnd: HWND; Msg: UINT; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
var
  i: Integer;
  aForm: TForm;
  aMainMenu: TMainMenu;
  aMenuItem: TMenuItem;
begin
  case Msg of

    WM_DESTROY: PostMessage(P^.HostWnd, WM_Close, 0, 0);

    CM_BUILDMENU:
      begin
        Result := -1;
        if P^.DestWnd <> 0 then
        begin
          //调用我们改进的FindControl函数来寻找待打补丁程序的主窗口,非常重要!!!!
          aForm := Pointer(FindControl(P^.DestWnd));

          if aForm <> nil then begin
             //遍历窗体上的所有控件来定位主菜单,注意这里好像不能使用is和as操作符,只能用强制转换
             for i := 0 to aForm.ComponentCount-1 do begin
                 //请在这里对你找到的控件进行处理
                 //下面是我对TMainMenu进行的处理
                 if aForm.Components[i].ClassName = 'TMainMenu' then begin
                    aMainMenu := TMainMenu(aForm.Components[i]);
                    if aMainMenu.Items.Count>1 then begin
                       aMenuItem := TMenuItem.Create(aForm);
                       aMenuItem.Caption := '新增菜单';
                       aMenuItem.OnClick := MyObject.MenuClick;
                       aMainMenu.Items[0].Add(aMenuItem);
                    end; 
                    //Showmessage('增加菜单成功!')
                    Result := 1;
                    Break;
                 end;
             end;
          end;
        end;
        Exit;
      end;

  end;
  Result := DefWindowProc(hwnd, Msg, WParam, LParam);
end;
//======================================================

//======================================================
//我们的钩子程序,实际上该钩子没起作用,它只是处理流程的一个必须步骤
function GetMsgProc(Code: UINT; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
begin
  if Code = HC_ACTION then
  begin
  end;
  Result := CallNextHookEx(P^.hkMsg, Code, WParam, LParam);
end;

//======================================================
//安装钩子,目的是让我们的dll注入到待打补丁应用程序所在的进程空间
procedure InstallHook(MainWnd, DestWnd: HWND); stdcall;
begin
  if P^.hkMsg = 0 then
     P^.hkMsg := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, HInstance, 0);

  P^.HostWnd := MainWnd;
  P^.HostPID := GetCurrentProcessId;
  P^.DestWnd := DestWnd;
end;
//======================================================

//======================================================
//卸载钩子
procedure UninstallHook; stdcall;
begin
  if P^.hkMsg <> 0 then
  begin
    UnhookWindowsHookEx(P^.hkMsg);
    P^.hkMsg := 0;
  end;
end;
//======================================================

var
  DoClear: Boolean;
  DestProcess: Boolean = False;
  DestPID: DWORD;
  
  //窗口类定义
  UtilWindowClass: TWndClass = (
    style: 0;
    lpfnWndProc: @MsgWndProc;
    cbClsExtra: 0;
    cbWndExtra: 0;
    hInstance: 0;
    hIcon: 0;
    hCursor: 0;
    hbrBackground: 0;
    lpszMenuName: nil;
    lpszClassName: 'THook_Hxb_leiyuan');


initialization

  //======================================================
  // 建立内存镜像文件,供不同的进程来交换数据
  hMapFile := OpenFileMapping(FILE_MAP_WRITE, False, cMapFileName);
  DoClear := hMapFile = 0;
  if hMapFile = 0 then
    hMapFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE,
      0, SizeOf(TShareData), cMapFileName);
  P := MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 0);
  if DoClear then FillChar(P^, SizeOf(TShareData), 0);
  //======================================================

  //======================================================
  // 为不同的进程定义不同的windows消息,该消息将与调用进程绑定,特别要注意GetModuleHandle(nil)的使用
  ControlAtomString := Format('ControlOfs%.8X%.8X', [GetModuleHandle(nil), GetCurrentThreadID]);
  ControlAtom := GlobalAddAtom(PChar(ControlAtomString));
  RM_GetObjectInstance := RegisterWindowMessage(PChar(ControlAtomString)); //注册消息,供不同的进程间使用
  //======================================================

  //======================================================
  // 为待打补丁的程序所属的进程创建一个秘密窗口,该窗口是属于待打补丁的程序的(即它们在同一个进程空间),
  // 利用该秘密窗口,外界就可以来指挥待打补丁的程序
  if P^.DestWnd <> 0 then
  begin
    GetWindowThreadProcessId(P^.DestWnd, DestPID);
    if DestPID = GetCurrentProcessId then
    begin
      DestProcess := True;
      UtilWindowClass.hInstance := HInstance;
      RegisterClass(UtilWindowClass);
      P^.MsgWnd := CreateWindowEx(
        WS_EX_TOOLWINDOW,              // extended window style
        UtilWindowClass.lpszClassName, // pointer to registered class name
        UtilWindowClass.lpszClassName, // pointer to window name
        WS_POPUP,                      // window style
        0,                             // horizontal position of window
        0,                             // vertical position of window
        0,                             // window width
        0,                             // window height
        0,                             // handle to parent or owner window
        0,                             // handle to menu, or child-window identifier
        HInstance,                     // handle to application instance
        nil);                          // pointer to window-creation data
      PostMessage(P^.HostWnd, CM_MSGWNDCREATED, P^.MsgWnd, 1);
    end;
  end;
  //======================================================

finalization
  if DestProcess then
  begin
    DestroyWindow(P^.MsgWnd);
    PostMessage(P^.HostWnd, CM_MSGWNDCREATED, P^.MsgWnd, 0);
  end;
  GlobalDeleteAtom(ControlAtom);
  ControlAtomString := '';
  UnmapViewOfFile(P);
  CloseHandle(hMapFile);
end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -