主程序注入dll到另一个程序中,然后HOOK监测到WM_WINDOWPOSCHANGED事件后就把WM_WINDOWPOSCHANGED中的WINDOWPOS结构体数据通过sendmessage发回到主程序中。
unit u_dllHook;interfaceuses
  Windows, SysUtils, Messages, Dialogs;const
  WM_USERCREATE = WM_USER + 122;
  WM_USERWINDOWPOSCHANGED = WM_USER + 123; // 定义一个消息来通知主程序
  WM_USERDESTROY = WM_USER + 124;function installDLL(ss: THandle): Boolean; stdcall; // 导出的2个函数 挂钩和解钩
function uninstallDLL: Boolean; stdcall;var
  ahook: HHOOK; // 钩子
  // F:TextFile;     //本来用来生成log文件调试钩子的.后来没有用了
  hmapFile: THandle; // 映像文件句柄
  pH: PHandle; // 保存主程序的句柄
  aName: array [0 .. 255] of Char; // 用来保存挂钩程序的exe名字的
  bBool: Boolean; // 是不是勾上了进程implementation// cbt钩子回调函数function CBTProc(icode: Integer; awParam: WPARAM; alParam: LPARAM): LongInt;
  stdcall;
var
  Data: TCWPStruct;
  WindowText, WindowClass: Array [0 .. 254] of Char;
begin
  Result := 0;
  // 根据msdn上面说的 如果icode小于0,就不进行处理,下一步
  if icode < 0 then
  begin
    Result := CallNextHookEx(ahook, icode, awParam, alParam);
    Exit;
  end;
  Data := (PCWPStruct(alParam))^;
  case Data.message of
    WM_WINDOWPOSCHANGED:
      begin
        if not bBool then
        begin
          //SendMessage(ph^,WM_USERWINDOWPOSCHANGED,data.hwnd,data.lParam);  此处发送消息回主程序lParam是一个WINDOWPOS指针,内容传不回去
        end;
      end;
    WM_DESTROY:
      begin
       
      end;
  end;
end;// 装钩子,传入主程序句柄
function installDLL(ss: THandle): Boolean; stdcall;
begin
  ahook := SetWindowsHookEx(WH_CALLWNDPROC, @CBTProc, HInstance, 0);
  // 全局cbt 钩子.
  Result := ahook <> 0;
  pH^ := ss
end;// 卸载钩子function uninstallDLL: Boolean; stdcall;
begin
  if ahook <> 0 then
  begin
    UnhookWindowsHookEx(ahook);
    Result := ahook = 0;
  end;
end;initialization// 先判断被钩进程的名字 是桌面进程就不钩了,因为容易被钩死掉
GetModuleFileName(0, aName, 256);
bBool := SameText(ExtractFileName(aName), 'Explorer.exe');
if not bBool then // 不是就生成映像文件
begin
  hmapFile := OpenFileMapping(FILE_MAP_WRITE, False, 'FollowMap');
  //
  if hmapFile = 0 then
    hmapFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf
        (THandle), 'FollowMap');
  if hmapFile = 0 then
    Exception.Create('不能创建内存映像');
  //
  pH := MapViewOfFile(hmapFile, FILE_MAP_WRITE or FILE_MAP_READ, 0, 0, 0);
  if pH = nil then
  begin
    CloseHandle(hmapFile);
    Exception.Create('不能共享内存');
  end;
end;finalization// 钩子在退出的时候关闭映像文件
if not bBool then
begin
  UnmapViewOfFile(pH);
  CloseHandle(hmapFile);
end;end.

解决方案 »

  1.   

    你搞得太复杂了,用WM_COPYDATA消息。
      

  2.   

    你的问题实际是发送结构体你不会发,而与钩子关系不大,如果你在多个exe中可以互相传递结构体,那么在钩子中也同理。
      

  3.   

    今天学习了一下WM_COPYDATA消息,做了一个例子:
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls, RzPanel, jpeg, RzShellDialogs;const
      WM_CopyDateDestory = wm_user + 100;  //self define messagetype
      TPerson = packed record
        Name :string[10];
        Age  :Integer;
    end;type
      Tserver = class(TForm)
        RzPanel1: TRzPanel;
        RzPanel2: TRzPanel;
        RzPanel3: TRzPanel;
        Edit1: TEdit;
        Edit2: TEdit;
        Button1: TButton;
        Edit3: TEdit;
        Image_D: TImage;
        RzPanel4: TRzPanel;
        RzPanel5: TRzPanel;
        Image_s: TImage;
        Button2: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private declarations }  public
        { Public declarations }
        procedure _WM_COPYDATA(var _Msg :TMessage);message WM_COPYDATA;
      end;var
      server: Tserver;
      _PictureMemoryStream :TMemoryStream;implementation{$R *.dfm}procedure Tserver._WM_COPYDATA(var _Msg :TMessage);
    var
      _CopyData :TCopyDataStruct;
      _Person   :TPerson;
      _MemStream :TMemoryStream;
      _MemSize   :Cardinal;
      _Buf :array of Char;
    begin
      if _Msg.Msg = WM_COPYDATA then
      begin
        if _Msg.WParam = $02 then
        begin
          _CopyData := PCopyDataStruct(_Msg.LParam)^;
          _Person   := TPerson(_CopyData.lpData^);
          Edit3.Text := _Person.Name + IntToStr(_Person.Age);
        end
        else if _Msg.WParam = $03 then
        begin
          _MemStream := TMemoryStream.Create;
          _CopyData  := PCopyDataStruct(_Msg.LParam)^;
          _MemSize   := _CopyData.cbData;      //mothod 1 ---------------------------------------------------------------
          SetLength(_Buf, _MemSize);
          Move(_CopyData.lpData^, _Buf[0], _MemSize);
          _MemStream.WriteBuffer(_Buf[0], _MemSize);
          //------------------------------------------------------------------------      //mothod 1 ---------------------------------------------------------------
          //_MemStream.WriteBuffer(_CopyData.lpData^, _MemSize);
          //------------------------------------------------------------------------
          _MemStream.SaveToFile('d:\1.jpg');
          _MemStream.Free;
          Image_D.Picture.LoadFromFile('d:\1.jpg');   
        end
        else if _Msg.Msg = WM_CopyDateDestory then
        begin
          if _PictureMemoryStream <> nil then
          begin
            _PictureMemoryStream.Free;
            _PictureMemoryStream := nil;
          end;
        end;
      end;
    end;
    procedure Tserver.Button1Click(Sender: TObject);
    var
      _CopyData :TCopyDataStruct;
      _Person   :TPerson;
    begin
      _Person.Name := Edit1.Text;
      _Person.Age  := StrToInt(Edit2.Text);  _CopyData.dwData := 0;
      _CopyData.cbData := SizeOf(_Person);
      _CopyData.lpData := @_Person;  SendMessage(Handle, WM_COPYDATA, $02, LongWord(@_CopyData));
    end;procedure Tserver.Button2Click(Sender: TObject);
    var
      _PictureCopyDat :TCopyDataStruct;
      _FileSize :Int64;
      _hwnd :HWND;
    begin
      if _PictureMemoryStream = nil then
        _PictureMemoryStream := TMemoryStream.Create;
        
      Image_s.Picture.Graphic.SaveToStream(_PictureMemoryStream);
      _PictureCopyDat.dwData := 0;
      _FileSize              := _PictureMemoryStream.Size;
      _PictureCopyDat.cbData := _FileSize;
      _PictureCopyDat.lpData := _PictureMemoryStream.Memory;
      _hwnd := FindWindow(nil,'client');
      if _hwnd <> 0 then
        SendMessage(_hwnd, WM_COPYDATA, $03, Cardinal(@_PictureCopyDat));//send other program  SendMessage(Handle, WM_COPYDATA, $03, Cardinal(@_PictureCopyDat)); //send this program
    end;procedure Tserver.FormCreate(Sender: TObject);
    begin
      _PictureMemoryStream := TMemoryStream.Create;
    end;procedure Tserver.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      if _PictureMemoryStream  <> nil then
      begin
        _PictureMemoryStream.Free;
        _PictureMemoryStream := nil;
      end;
    end;end.