Eine Software, an der ich kürzlich arbeite, von denen einige durch Aufrufen anderer Software abgeschlossen werden müssen, aber diese Software hat nur ausführbare Dateien und überhaupt keinen Quellcode. Begonnen, nachdem mein Programm gestartet wurde.
Apropos, ich glaube, Sie haben einige vorläufige Ideen für diese Funktion.
1) Rufen Sie CreateProcess () an, um das Zielprogramm zu öffnen.
2) Verwenden Sie FindWindow (), um den Fenstergriff des Zielprogramms zu finden.
3) Suchen Sie den Handle des Textfelds und die MessageID der Schaltfläche, setzen Sie den Text mit der Methode sendMessage () fest und lösen Sie das Ereignis aus.
OK, das ist in der Tat sehr einfach, aber als ich es implementiert habe, stellte ich fest, dass das Ergebnis dies war: Als mein Programm das Zielprogramm startete und öffnete () Um das Hauptfensterhandel zu finden und SendMessage (Fensterhand, SW_Hide) zu rufen, um das Fenster zu verbergen, wird das Hauptfenster für einen Moment angezeigt.
Wie kann ich zuerst dieses Problem lösen? Es hat keine Wirkung. . . . Suchen Sie weiter nach dem Dokument. und wenn es nach einem Desktop -Namen zugewiesen ist, wird der Prozess auf dem angegebenen Desktop gestartet.
1) Erstellen Sie zunächst einen virtuellen Desktop.
Const
DesktopName = 'mydesk';
FDesktop: = erstellte
Mehrere Desktops können in Windows erstellt werden, und SwitchDesktop () kann verwendet werden, um den Desktop anzuzeigen. Windows selbst wird durch virtuelle Desktop -Funktion implementiert. Material:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/enumdesktops.asp
2) Geben Sie beim Erstellen des Programms das Programm an, das auf meinem neu generierten Desktop ausgeführt werden soll:
var
StartInfo: tstartupinfo;
Fillchar (startinfo, sizeof (startinfo), 0);
StartInfo.cb: = sizeof (startInfo);
StartInfo.lpDesktop: = pchar (DesktopName);
StartInfo.wshowwindow: = sw_hide;
StartInfo.dwflags: = startf_useshowwindow;
StartInfo.hstderror: = 0;
StartInfo.hstdinput: = 0;
StartInfo.hstdoutput: = 0;
Wenn nicht CreateProcess (pchar (Dateiname), NIL, NIL, NIL, NIL, TRUE, CREATE_NEW_CONSOLE+HIGH_PRIORITY_CLASS, NIL, PCHER (ExtractFilepath (Filepath)), StartInfo, FprocEnfo), dann beginnen
MessageBox (application.Handle, 'Fehler bei Init Voice (5).', Pchar (application.title), mb_iconWarning);
Ausfahrt;
Ende;
3) Finden Sie FindWindow, um das Hauptfenster des Programms zu finden
Zuerst habe ich den Code wie diesen aufgeschrieben:
Für i: = 0 bis 60 Beginnen Sie // 30 Sekunden warten, um das Hauptfenster zu öffnen
Fensterhand: = findWindow (nil, 'Fensterkaption');
Wenn Fensterhandle <> 0 dann beginnen
brechen;
Ende;
Schlaf (500);
Ende;
Die Praxis hat jedoch bewiesen, dass das Fenster, das nicht im aktuellen Desktop ist, nicht gefunden werden soll.
Die Antwort lautet, dass Sie die Funktion setThreadDesktop () verwenden können, mit der der Desktop festgelegt werden kann, auf dem der Thread funktioniert. Daher habe ich einen weiteren Satz vor dem obigen Code hinzugefügt:
Wenn nicht SetThreadDesktop (fDesktop), beginnen Sie dann
Ausfahrt;
Ende;
Nachdem das Programm ausgeführt wurde, gibt die Funktion falsch zurück, was angibt, dass der Methodenaufruf fehlgeschlagen ist.
Die SetThreadDesktop -Funktion schlägt fehl, wenn der aufrufende Thread über Windows oder Hooks auf dem aktuellen Desktop verfügt (es sei denn, der Parameter hdesktop ist ein Handle zum aktuellen Desktop).
Oh, es stellt sich heraus, dass es in dem Thread keine UI -Sache gibt, die den Desktop wechseln muss, aber ich habe diese Methode im Haupt -Thread des Programms bezeichnet, und natürlich wird es leicht sein, dies zu wissen, ich bin nur, ich bin nur, ich bin nur, ich bin nur. Müssen Sie einen verwenden, ist es nicht in Ordnung, den "sauberen" Thread an den neuen Desktop zu binden, und dann die FindWindow () -Methode, um den Fensterhandle zu finden, nach dem ich suche? Der Code ist wie folgt:
TfindWindowthread = Klasse (tThread)
Privat
Fdesktop: Thandle;
Fwindowhandle: Thandle;
geschützt
Prozedur execute (); override;
öffentlich
Constructor Create (Acreatesuspended: boolean; const adesktop: Thandle); wiederinstitutieren;
Eigenschaftsfensterhand: Thandle Read Fwindowhandle;
Ende;
{TfindWindowthread}
procedure tfindWindowthread.execute ();
var
I: Ganzzahl;
Beginnen
// Erstellen Sie das aktuelle Thread -Fenster auf dem neuen Desktop!
Wenn nicht SetThreadDesktop (fDesktop), beginnen Sie dann
Ausfahrt;
Ende;
Für i: = 0 bis 60 Beginnen Sie // 30 Sekunden warten, um das Hauptfenster zu öffnen
FwindowHandle: = findWindow (nil, pChar ('Fensterkaption');
Wenn fwindowHandle <> 0 0 beginnen
brechen;
Ende;
Schlaf (500);
Ende;
Ende;
Konstruktor tfindwindowthread.create (acreatesuspended: boolean; const adesktop: Thandle);
Beginnen
erbte erstellen (Acreatesuspended);
FDesktop: = adesktop;
Ende;
Und der Code im Hauptprogramm wird wie folgt:
FindWindowthread: = tfindWindowthread.create (false, fDesktop);
versuchen
FindWindowthread.waitfor;
FmainwindowHandle: = findWindowthread.WindowHandle;
Endlich
FindWindowthread.Free;
Ende;
Wenn fmainwindowHandle = 0 beginnt
MessageBox (application.Handle, 'Fehler bei Init Voice (6).', Pchar (application.title), mb_iconWarning);
Ausfahrt;
Ende;
Haha, es ist erfolgreich, sodass Sie den Fenstergriff reibungslos finden können.
4) Verwenden Sie schließlich diesen Hauptfenstergriff, um den Editbox -Handle wie folgt zu finden:
FeditWindow: = findWindowex (fmainwindowHandle, 0, pchar ('edit'), nil);
Ich habe den Klassennamen dieses Textfelds hier angegeben, und dieser Name kann mit Spy ++ erhalten werden.
Die Initialisierungsarbeit endet hier. Der Funktionsaufruf ist also der gleiche wie üblich:
if (fmainwindowHandle = 0) oder (feditwindow = 0) dann beginnen
Ausfahrt;
Ende;
SendMessage (FeditWindow, Wm_SetText, 0, Longint (@atext [1]));
SendMessage (fmainwindowhandle, wm_command, $ 8012, $ 0);
Die Zahl $ 8012 ist auch die Ressourcen -ID, die mit SPY ++ erhalten wird.
Vergessen Sie nicht, das Programm zu schließen und den virtuellen Desktop zu veröffentlichen:
Wenn fprocEnfo.hprocess <> 0 beginnen, beginnen Sie
TerminateProcess (fprocEnfo.hprocess, 0);
Ende;
Wenn fDesktop <> 0 dann beginnen
Closedesktop (fDesktop);
Ende;
OK, dies implementiert fast perfekt die Funktion eines Hintergrundaufrufprogramms, das für den Endkunden völlig transparent ist, und der Kunde hat einfach nicht das Gefühl, dass ein anderes Programm im Hintergrund funktioniert. Ist es nicht sehr gut?
Wenn Sie Verbesserungs- oder Austauschvorschläge haben, können Sie pers Mail an: Tonyki [at] citic.net