Re: Zugriff auf ein TImage einer externen Anwendung
Also ich muss nochmal korrigieren ...
mit dem "neuen" Code von dir, killt sich das Programm nicht mehr selbst, sondern bringt lediglich eine Zugriffsverletzung und das Form schließt sich, das Programm selbst bleibt offen. Zudem hab ich mal folgendes Versucht, was nicht funktioniert:
Delphi-Quellcode:
Ohne die delay Funktion würde sich das eigene Programm aufhängen, aber es kommt kein ergebnis zurück und das Ziel-Form hängt sich dann auch nicht auf, als ob irgendwie die Adressen nicht angesprochen werden.
procedure TForm1.Button1Click(Sender: TObject);
begin memo1.clear; myhandle:=findwindow(nil,'PImage'); if myhandle=0 then exit; memo1.Lines.add('window found!'); delay(1000); startobservation; //eine Besipielanfrage an die newwndProc communicate('Image2',sImageSize); //hier oder in einer anderen Funktion können noch mehr solche Anfragen gestartet werden delay(1000); stopobservation; end; D.h. also wenn das myhandle und startobservation im FormCreate ist funzt es, so nicht. Was deine Frage betrifft was für eine Software das ist, kann ich nur sagen das es sich um eine Präsentationssoftware handelt. Das die Software in Delphi programmiert ist, ist zu 100% sicher, zum einen durch die Formulare die ich in ResHack ermittelt hab und zum anderen wenn ich die Software im HexEditor anschaue steht auch Delphi drin, und das schreibt meines wissens nur Delphi rein. ;-) Welche Version von Delphi, kann ich leider nicht sagen, du kannst schon recht haben das da ne ältere Version hinter steckt. Da ich so langsam die Vermutung hab das die Namen die ich ermittelt hatte, zur Laufzeit vielleicht anders lauten, kann ich irgendwie eine Liste aller Elemente, also die Namen und ggf. die Klasse dazu die auf dem Form existieren auslesen? Mit den Klassen hatten wir das ja schonmal, wobei er mit der grund Version ich glaub auf Seite 1 des Threads, aufhängt bzw. Zugriffsverletzung bekommt (also eigenes Programm). Ich glaub langsam wird kompliziert, oder? :) |
Re: Zugriff auf ein TImage einer externen Anwendung
Zitat:
Zitat:
Zitat:
Zitat:
Für ein Delphi 4 wüsste ich noch, wo eine Lizenz ungenutzt herumliegt. Aber das jetzt zu installieren um auf Verdacht weiterzusuchen....nicht unbedingt. Es war ein Versuch wert. Schade dass er nicht geklappt hat. War aber mal ne schöne Übung. Es ist halt recht schwer auf die Ferne jetzt noch etwas am Code zu drehen. Du müsstest wahrscheinlich selber noch ein bisschen probieren. Als erstes würde ich ständig Messages senden, wenn er wieder eine Codezeile geschafft hat. Dadurch weisst du wo er hängen bleibt. Ich kann dir das mit dem Classname in die letzte Variante noch mal reinprogrammieren. Dürfte aber nix bringen. Die Namen der Komponenten kann man zur Laufzeit meines Wissens nicht mehr ändern. |
Re: Zugriff auf ein TImage einer externen Anwendung
Ok, in deinem TestProgramm ist ein Laufzeitproblem.
[Nebenbei: Seit wann gibts denn die delay-Funktion wieder. Die kenne ich noch aus Turbo Pascal, aber mein D7 hat die nicht.] Du musst eigentlich nicht zwischen findwindo und startobservation warten, sondern zwischen startobservation und communicate. Das Problem ist wie in einer MultiThreadanwendung. die haben wir eigentlich auch. Nur das unser Nebenthread auch gelich in einem anderen Process ist. Der letzte Befehl in Startobservation ist "CreateRemoteThread" Da wird der neue Thread gestartet. Das dauert aber meistens eine Weile. In der Zeit ist unse rHauptthread schon längst in communicate bei sendmessage angekommen. Schickt als eine Message und wartet auf Antwort. Da aber unser Nebenthread die wndProc-Funktion noch nicht umgelenkt hat, kriegen wir keine Antwort und warten ewig. Und deswegen wird in dem Nebenthread (also eigentlich in der neuen wndProc) auch nicht die Info-Prozedur aufgerufen. Und weil die Zugriffsverletzungen nur dort passieren, passiert dann eben nix. Edit: Die Idee ist ja auch, nicht alles hintereinander zu machen, sondern erst einmalig startobservation. Und dann bei Gelegenheit (von mir aus) hundertmal communicate. Soviel du halt an Infos brauchst. In der ganzen Zeit seit startobservation bekommst du auch die WM_Paint Messages mit. Und ganz am Ende des Programms rufst du einmal stopobservation. |
Re: Zugriff auf ein TImage einer externen Anwendung
So, ich hab die Sache mit Classname wieder reingebracht, dürfte aber wie gesagt nicht viel bringen.
folgende Änderungen vom letzten Mal:
Delphi-Quellcode:
type TSearchtype=(sImageSize,sCaption,sImageSizefromClassname);
Delphi-Quellcode:
procedure Info(memory:Pmemory;wparam,lparam:cardinal); stdcall;
//Die bisherige Funktion zum ermitteln und senden der Infos bezüglich TImage und TLabel var pi,p,pm:ppointer; i:integer; a:cardinal; c:pchar; left,top,width,height:smallint; same:boolean; SearchType:TSearchType; vgl:array[0..31] of char; vgllength:integer; index:word; begin Searchtype:=TSearchType(lparam mod 65536); index:=lparam div 65536; //Da Strings nicht über Messages gesendet werden können, benötigen wir ein Atom vgllength:=memory^.GlobalGetAtomName(wparam,@vgl,32); wparam:=0; lparam:=0; p:=pointer(cardinal(memory^.oldwindowproc)+9); pm:=pointer(integer(p^)+16); for a:=0 to pinteger(integer(pm^)+8)^-1 do begin //von 0 bis componentcount p:=pointer(cardinal(pm^)+4); p:=pointer(cardinal(p^)+4*a); pi:=p; //pi^ ist Zeiger auf ein Objekt if searchtype=simagesizefromclassname then begin p:=p^; p:=pointer(cardinal(p^)-44); end else p:=pointer(cardinal(p^)+8); p:=p^; c:=pchar(p); if (pbyte(p)^=vgllength)or(SearchType<>sImagesizefromClassname) then begin if SearchType=sImagesizefromClassName then inc(c); same:=false; for i:=1 to vgllength do begin if vgl[i-1]<>c^ then break; same:=i=vgllength; inc(c); end; if same then begin dec(index); if (index=0)or(SearchType<>sImagesizefromClassname) then begin if SearchType=sCaption then begin p:=pointer(cardinal(pi^)+$64); wparam:=cardinal(p^); c:=pchar(p^); while c^<>#0 do begin inc(c); inc(lparam); end; inc(memory^.backmsg); end else begin left:=pinteger(integer(pi^)+$40)^; top:=pinteger(integer(pi^)+$44)^; width:=pinteger(integer(pi^)+$48)^; height:=pinteger(integer(pi^)+$4C)^; wparam:=left*65536+top; lparam:=width*65536+height; end; break; end; end; end; end; //Ergebnis Nach Hause senden memory^.Postmessage(memory^.backwnd,memory^.backmsg,wparam,lparam); end;
Delphi-Quellcode:
Und die Testroutine:
procedure TForm1.communicate(vgl:string;Searchtype:TsearchType;index:word=0);
//Eine Anfrage an unsere neue WndProc starten var wparam,lparam:cardinal; begin wparam:=globaladdAtom(pchar(vgl)); //String in ein Atom laden; Nr. des Atoms in wparam if searchtype=sImageSizefromclassname then lparam:=cardinal(Searchtype)+index*65536 else lparam:=cardinal(Searchtype); sendmessage(myhandle,mymsg,wparam,lparam); //Message für unsere newwndproc; und warten bis sie dort verarbeitet wurde globaldeleteatom(wparam); //Atom wieder löschen end;
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin //Besipielanfragen an die newwndProc communicate('TImage',sImageSizefromclassname,2); communicate('Image2',sImageSize); communicate('Label1',sCaption); //hier oder in einer anderen Funktion können noch mehr solche Anfragen gestartet werden end; |
Re: Zugriff auf ein TImage einer externen Anwendung
Das Delay ist eine Funktion die ich hier irgendwo aus dem Board gezogen hab.
Das Problem warum ich das mit dem start/stopobservation in ein buttonclick gesetzt hab, ist jenes weil das spezielle Form was die TImages enthält nicht permanent geöffnet ist, was ich dann auch noch irgendwie z.B. mit Timer überprüfen muss. |
Re: Zugriff auf ein TImage einer externen Anwendung
Aslo entweder du baust dann die Verzögerung ein nach startobservation (ein einfaches Sleep(100) dürfte aber ausreichen) oder ich sende aus dem Remotethread eine Message, dass alles vorbereitet ist:
Delphi-Quellcode:
//Deklaration in TForm1
procedure GetReadyMsg(var msg:TMessage);message mymsg+3; . . . function injectThread(memory:Pmemory):integer;stdcall; //Die eigentliche Thread-Funktion //Hauptaufgabe: einklinken und am Ende wieder ausklinken unserer neuen WndProc //dazwischen nur sleep, bis die Message mymsg+1 and die neue WndProc kommt begin memory^.running:=true; memory^.oldwindowProc:=memory^.getwindowlong(memory^.watchwnd,gwl_wndproc); memory^.getInfoFunc:=@memory^.getInfo; memory^.setwindowlong(memory^.watchwnd,gwl_wndproc,memory); memory^.Postmessage(memory^.backwnd,memory^.backmsg+3,0,0); //Message, dass alles eingerichtet/vorbereitet ist while memory^.running do memory^.sleep(200); memory^.setwindowlong(memory^.watchwnd,gwl_wndproc,memory^.oldwindowproc); result:=0; memory^.exitthread(0); end;
Delphi-Quellcode:
Aber, wenn du gleich stopobservation aufrufst, dann bekommst du ja nicht mehr mit, wenn das Window eine WM_Paint Message zum neuzeichnen bekommt.
procedure Tform1.GetReadyMsg(var msg:TMessage);
begin //wird automatisch vom Remotethread "gestartet", wenn er soweit ist communicate('TImage',sImageSizefromclassname,2); communicate('Image2',sImageSize); communicate('Label1',sCaption); stopobservation; //hier oder später end; procedure TForm1.Button1Click(Sender: TObject); begin memo1.clear; myhandle:=findwindow(nil,'PImage'); if myhandle=0 then exit; startobservation; end; Du kannst übrigens auch das Erstellen und das Entfernen des Formulars ereignisgesteuert überwachen. Aber solange wir das mit dem Communicate, also die Info-funktion nicht hinbekommen, brauchen wir den Rest nicht mehr zu probieren. Da bräuchten wir wirklich die entspr. Delphiversion. |
Re: Zugriff auf ein TImage einer externen Anwendung
Zitat:
Hier mal neben bei die Delay-Prozedur:
Delphi-Quellcode:
Die benutze ich in Verbindung mit Windows-Diensten, damit der Prozess nicht mit 100% Auslastung fährt.
procedure Delay(Milliseconds: Integer);
var Tick: DWord; Event: THandle; begin Event := CreateEvent(nil, False, False, nil); try Tick := GetTickCount + DWord(Milliseconds); while (Milliseconds > 0) and (MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) <> WAIT_TIMEOUT) do begin Application.ProcessMessages; if Application.Terminated then Exit; Milliseconds := Tick - GetTickcount; end; finally CloseHandle(Event); end; end; |
Re: Zugriff auf ein TImage einer externen Anwendung
Hmm hab grad nochmal rum getestet... das Ergebnis ist leider sehr enttäuschend. Kurz um: Zugriffsverletzung im Ziel-Programm.
Gut dann müsste man mal eine andere Taktik angehen. Lassen wir mal das mit dem finden der TImage. Passt zwar jetzt nicht zum Topic, aber es gibt noch noch eine andere Möglichkeit die TLabel zu finden als über die Adress-Rechnung oder? Ich hatte früher mal so sachen gehabt, aber die zu finden, dürften schwierig sein. Die Position und die größe der TImage lässt sich zur Not auch noch manuell und fix programmieren, aber ich brauch auf alle Fälle den Text der Labels. |
Re: Zugriff auf ein TImage einer externen Anwendung
Bei TLabel besteht genau dasselbe Problem, wie bei TImage. Es hat kein Window-Handle. Ansonsten könnet man mit einer WM_GetText Message o.ä. daran kommen. Also es bedarf zum Beispiel nur weniger Schritte um die Playlist aus dem Win-Media Player herauszubekommen, auch im Explorer kann man recht einfach von außen mitlesen. Aber dort benutzt Microsoft halt die grundlegenden Window-Typen aus ihrer eigenen Win-API. TLabel ist aber nur ein Objekt in Delphi, was halt immer auf das formular gezeichnet wird. es hat sogar eine eigene WndProc-Funktion. die wird aber nur über das Parent-window angesteuert. wenn wir die Finden könnten wie sogar den Text bekommen. Aber wie?
Da muss ich erstmal mindestens eine Nacht drüber schlafen. Ich hatte vorhin vesucht noch eine Exception-Behandlung mit einzubauen (in die Info). Aber die funktioniert nicht. Da geht das Programm im Fehlerfall dann einfach aus, ohne sich irgendwie abzumelden und ohne Fehlermeldung. Im eigenen Programm funktioniert die Exceptionbehandlung wunderbar. Musste sie ja in ASM schreiben, weil das try..except ja gleich wieder Klassen instanziert. |
Re: Zugriff auf ein TImage einer externen Anwendung
Also kurz zum Verständnis, ein RichEdit (sei es nun von Delphi oder generell) besitzt ein eigenes Handle, ein Memo auch? nur ein Label wird in dem sinne sozusagen einfach nur draufgezeichnet, d.h. der Text existiert schon irgendwo im Hauptprogramm?
Früher hatte ich ja mal ein Programm mit dem ich RichEdit und ich glaub auch Memos auslesen konnte, aber das eben ohne Adress-Rechnung. Das ganze war einfacher gestrickt. Hab aber wie gesagt den Code nicht mehr zumindest müsste ich wenn doch in tiefen Archiven graben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:15 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz