unit UHook;
interface
uses Windows, Messages, SysUtils, Controls, Grids, DBGrids, DBGridEh, DBGridEhImpExp, Classes;
procedure InstallHook(MainWnd, DestWnd: HWND); stdcall;
procedure UninstallHook; stdcall;
function GetHookedCell: PChar; stdcall;
implementation
uses UShare;
var
ControlAtom: TAtom;
ControlAtomString: string;
RM_GetObjectInstance: DWORD; // registered window message
function MyFindControl_test(Handle: HWnd): TWinControl;
type
PObjectInstance = ^TObjectInstance;
TObjectInstance = packed record
Code: Byte; { 短跳转 $E8 }
Offset: Integer; { CalcJmpOffset(Instance, @Block^.Code); }
Next: PObjectInstance; { MainWndProc 地址 }
Self: Pointer; { 控件对象地址 }
end;
var
wc: PObjectInstance;
begin
Result := nil;
wc := Pointer(GetWindowLong(Handle, GWL_WNDPROC));
if wc <> nil then
begin
Result := wc.Self;
end;
end;
function MyFindControl(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));
MessageBeep(MB_OK);
end;
end;
function MsgWndProc(hwnd: HWND; Msg: UINT; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
var
DG: TDBGridEh;
aName: array [0..255] of Char;
begin
case Msg of
CM_QUERYROW: //获取行数
begin
Result := -1;
if P^.DestWnd <> 0 then
begin
GetClassName(P^.DestWnd, aName, 256);
//if string(aName) = 'TDBGridEh' then MessageBeep(MB_OK);
DG := Pointer(MyFindControl(P^.DestWnd));
if DG <> nil then Result := DG.Height;
end;
Exit;
end;
CM_QUERYCOL: //获取列数
begin
Result := -1;
if P^.DestWnd <> 0 then
begin
GetClassName(P^.DestWnd, aName, 256);
//if string(aName) = 'TDBGridEh' then MessageBeep(MB_OK);
DG := Pointer(MyFindControl(P^.DestWnd));
if DG <> nil then Result := DG.Width;
end;
Exit;
end;
CM_HOOKCELL: //获取内容
begin
DG := Pointer(MyFindControl(P^.DestWnd));
//if DG <> nil then MessageBeep(MB_OK);
SaveDBGridEhToExportFile(TDBGridEhExportAsText, DG, 'c:/GridData.txt', true);
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;
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;
function GetHookedCell: PChar; stdcall;
begin
Result := P^.Text;
end;
var
DoClear: Boolean;
DestPID: DWORD;
DestProcess: Boolean = False;
UtilWindowClass: TWndClass = (
style: 0;
lpfnWndProc: @MsgWndProc;
cbClsExtra: 0;
cbWndExtra: 0;
hInstance: 0;
hIcon: 0;
hCursor: 0;
hbrBackground: 0;
lpszMenuName: nil;
lpszClassName: 'THookSGMsgWindow');
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);
//ControlAtomString := Format('ControlOfs%.8X%.8X', [GetModuleHandle(nil), GetCurrentThreadID]);
//ControlAtomString := Format('ControlOfs%.8X%.8X', [$50300000, $00000F50]);
//ControlAtomString := Format('ControlOfs%.8X%.8X', [$00400000, GetCurrentThreadID]);
ControlAtomString := Format('ControlOfs%.8X%.8X', [GetWindowLong(P^.DestWnd, GWL_HINSTANCE), GetWindowThreadProcessId(P^.DestWnd)]);
ControlAtom := GlobalAddAtom(PChar(ControlAtomString));
RM_GetObjectInstance := RegisterWindowMessage(PChar(ControlAtomString));
if P^.DestWnd <> 0 then
begin
GetWindowThreadProcessId(P^.DestWnd, DestPID);
if DestPID = GetCurrentProcessId then
begin
MessageBeep(MB_OK);
DestProcess := True;
//UtilWindowClass.hInstance := HInstance;
UtilWindowClass.hInstance := GetWindowLong(P^.DestWnd, GWL_HINSTANCE);
Windows.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
GetWindowLong(P^.DestWnd, GWL_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.