Link to home
Start Free TrialLog in
Avatar of rogerrr
rogerrr

asked on

Feng Yuan's WM_PAINT hook code in Delphi

Hello!


I tried to capture the image of a foreign window but my
attempt is not perfect because the captured image is not similar
to the original window's image. For example like Microsoft Excel's window.
See example: http://img3.freeimagehosting.net/image.php?6a8267869d.jpg


My hook code is the following:

Project:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

const
    MSG_PROJECT = WM_USER + $1000;

type
  TForm1 = class(TForm)
    hook_on: TButton;
    hook_off: TButton;
    send_wm_paint: TButton;
    Edit1: TEdit;
    procedure hook_onClick(Sender: TObject);
    procedure hook_offClick(Sender: TObject);
    procedure MSGHOOK(var Msg: TMessage); message MSG_PROJECT;
    procedure send_wm_paintClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    gp: TPoint;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var hook : integer;


procedure TForm1.MSGHOOK(var Msg: TMessage);
begin
    //if Msg.WParam<>0 then
end;


procedure TForm1.hook_onClick(Sender: TObject);
begin
hook:=SetWindowsHookEx(WH_CALLWNDPROC,
GetProcAddress(GetModuleHandle('NewWndDll'),'NewWindowHookCallBack'),
GetModuleHandle('NewWndDll'), 0);
hook_on.Enabled:=False;
hook_off.Enabled:=True;
end;

procedure TForm1.hook_offClick(Sender: TObject);
begin
UnhookWindowsHookEx(hook);
hook_off.Enabled:=False;
hook_on.Enabled:=True;
end;

procedure TForm1.send_wm_paintClick(Sender: TObject);
begin
SendMessage(FindWindow(nil,PChar(Edit1.Text)),WM_PAINT,0,0);
end;

initialization
MessageBox(0,pchar(intToStr(LoadLibrary('NewWndDll'))),'LoadLibrary',0);


end.



*****************************************************************************
*****************************************************************************

DLL:


library NewWndDll;

uses
   Windows,SysUtils,Classes,Dialogs,Messages,Graphics;

const
   MSG_PROJECT = WM_USER + $1000;

var
  MyHook : HHook;

function NewWindowHookCallBack(pCode: Integer; pHandle: WPARAM; pWindow: LPARAM): LRESULT; stdcall;
var
PCWP : ^CWPSTRUCT;
h: Hwnd;

  hbmScreen: HBitmap;
  hdcScreen, hdcCompatible : HDC;
  rect: TRect;
  bmp: TBitmap;
begin
PCWP:= Pointer(pWindow);
if PCWP^.Message = WM_PAINT then begin
h:=FindWindow(nil,'Microsoft Excel - Book1.xls'); //window to capture


       if PCWP.hwnd=h then
       begin
       hdcScreen:=GetWindowDC(PCWP.hwnd);
       hdcCompatible:=CreateCompatibleDC(hdcScreen);
       GetWindowRect(PCWP.hwnd, rect);
       hbmScreen:=CreateCompatibleBitmap(hdcScreen, rect.Right - rect.Left, rect.Bottom -
       rect.Top);
       SelectObject(hdcCompatible,hbmScreen);

       SendMessage(PCWP.hwnd,WM_PRINT, hdcCompatible,PRF_CHILDREN or PRF_CLIENT or PRF_ERASEBKGND or
       PRF_NONCLIENT or PRF_OWNED);

       bmp:=TBitmap.Create;
       try
       bmp.Handle:=hbmScreen;
       BitBlt(bmp.Canvas.Handle, 0, 0, rect.Right - rect.Left,rect.Bottom - rect.Top, hdcScreen, 0,
       0, SRCCOPY);
       ReleaseDc(0, hdcScreen);
       bmp.SaveToFile('C:\shot.bmp');
       finally
       bmp.Free;
       DeleteDC(hdcScreen);
       DeleteDC(hdcCompatible);
       end;


       end;


end;
    Result:=CallNextHookEx(MyHook, pCode, pHandle, pWindow);
end;


exports NewWindowHookCallBack index 1 name 'NewWindowHookCallBack';

end.



*****************************************************************************
*****************************************************************************

I found an article/code about WM_PAINT hook by Feng Yuan.
http://www.fengyuan.com/article/wmprint.html

Dll code: http://www.fengyuan.com/article/capture.zip

But this code written in VC++ and i don't understand it because it contains some unknown things for me and i'm not feel at home in VC++.  Please help me to translate this code to Delphi.

Thanks in advance!
Avatar of 2266180
2266180
Flag of United States of America image

haven't tested your code but maybe you want to try this one:
https://www.experts-exchange.com/questions/21945203/Capture-of-a-client-form.html 
it's not that complicated as the hooking solution ;)
Avatar of rogerrr
rogerrr

ASKER

Hello ciuly!

Thanks but your code is not perfect for me. :-(  My code (vide supra) works even if the captured window is obscured by other windows and/or visible partially (hang out the desktop)...

(I know the PrintWindow api too, but i want to try the Feng Yuan's solution.)

Thanks.
you can always bring forward the needed window :P

if no one takes the hit on this question until the weekend, post a reminder message and I'll try a translation ;)
Avatar of rogerrr

ASKER

OK! Thank you!
just looked over the c++ code. what a mess. quote from page:
Limitation
The Hook function only handles exported function whose first instruction is "MOV EAX, <DWORD_constant>". So the implementation shown here only applies to Windows NT/2000. Refer to Chapter 4 for more generic of restrictive API hooking solutions.

that doesn't look to good. anyway, just for hooking purposes we can use madshi madhook component.

but before getting into teh real deal, don't want to waste time translating something that does not work, so I have to ask: did you try it out? does it do what you want?
Avatar of rogerrr

ASKER

Hello!
Sorry for slow reply!

"did you try it out? does it do what you want?"

Yes, some days ago i did try a compiled verison (comiled by a friend)  and the captured image was true. I think (and according to others too) Feng Yuan's solution is the best way to capture a window.

Thank you!
ASKER CERTIFIED SOLUTION
Avatar of 2266180
2266180
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of rogerrr

ASKER

:-(  Yes the compiled dll is applicable in my application too, but i'd like to see the full code in 'Delphi language'. Please help me i can't translate it...plese!

Thanks!
Avatar of rogerrr

ASKER

Is there any hope for me?
well your problem is solved. why do you want the translation anyway?
Avatar of rogerrr

ASKER

Hello!

Because i want to learn from the code, and my only one legal developer ambient is Delphi. :-)