Auf einem Window rumzeichnen geht so:
Delphi-Quellcode:
var dc:hdc;
//Device Context Handle
Canvas:Tcanvas;
myhandle:THandle;
begin
//Devicecontext eines Window Handles besorgen
//myhandle:=form1.Handle; //so
//myhandle:=button2.Handle; //oder so
//myhandle:=getforegroundwindow; //oder so
myhandle:=getdesktopwindow;
//oder so oder mit findwindow ...
dc:=getwindowdc(myhandle);
//TCanvas auf den Device Context setzen
canvas:=TCanvas.Create;
canvas.Handle:=
dc;
//Hier kann man ganz nach belieben malen
canvas.Brush.Color:=clbtnface;
canvas.Font.Color:=clred;
canvas.Font.Size:=15;
canvas.TextOut(0,0,'
Hallo');
//Speicher wieder freigeben
canvas.Free;
releasedc(myhandle,
dc);
end;
Ergänzung:
Mit folgendem Code kann man ein TImage finden, wenn man nur das WindowHandle, des übergeordneten Fensters hat:
(mein Testcode)
Delphi-Quellcode:
var pi,p,pm:ppointer;
s:string;
c:pchar;
i,a:integer;
begin
memo1.clear;
myhandle:=form1.handle; //myhandle ist das einzige, was ich benötige
p:=pointer(getwindowlong(myhandle,gwl_wndproc)+35);
pm:=p;
p:=p^;
p:=pointer(integer(p^)-44);
p:=p^;
c:=pchar(p);
s:='';
inc(c);
for i:=1 to pbyte(p)^ do begin
s:=s+c^;
inc(c);
end;
memo1.lines.Add(s); //classname des Windows
pm:=pointer(integer(pm^)+16);
for a:=0 to pinteger(integer(pm^)+8)^-1 do begin //von 0 bis componentcount
p:=pointer(integer(pm^)+4);
p:=pointer(integer(p^)+4*a);
pi:=p; //pi^ ist Zeiger auf ein Objekt
p:=p^;
p:=pointer(integer(p^)-44);
p:=p^;
c:=pchar(p);
s:='';
inc(c);
for i:=1 to pbyte(p)^ do begin
s:=s+c^;
inc(c);
end;
memo1.lines.Add(s); //classname einer Komponente
if s='TImage' then begin
memo1.lines.Add(inttostr(pinteger(integer(pi^)+$40)^)); //left
memo1.lines.Add(inttostr(pinteger(integer(pi^)+$44)^)); //top
memo1.lines.Add(inttostr(pinteger(integer(pi^)+$48)^)); //widht
memo1.lines.Add(inttostr(pinteger(integer(pi^)+$4C)^)); //height
end;
end;
Ich hab jetzt keine weiteren Kommentare, da ich nur ein wenig rumgespielt habe. Letztenendes macht es nix andere, als:
Delphi-Quellcode:
for i:=0 to Form1.componentcount-1 do begin
memo1.lines.add(Form1.component[i].classname);
//Und wenn classname TImage ist, dann noch die Abmaße aufschreiben
end;
Allerdings passiert dies ohne Zuhilfenahme der
VCL, bezieht sich allerdings strikt darauf.
Das funktioniert also für alle Programme, die mit Hilfe der
VCL programmiert wurden. Allerdings wird das ganze noch etwas umständlicher, wenn man sich in einem fremden Prozess befindet (siehe virtueller Addressraum).
PS: Diese ganze Type-casting zwischen integer und pointer könnte man sich natürlich mit
ASM sparen.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.