Perangkat lunak yang saya kerjakan baru -baru ini, beberapa di antaranya perlu diselesaikan dengan memanggil perangkat lunak lain, tetapi perangkat lunak itu hanya memiliki file yang dapat dieksekusi dan tidak ada kode sumber sama sekali. Dimulai setelah program saya dimulai.
Berbicara tentang ini, saya yakin Anda memiliki beberapa ide awal untuk fungsi ini.
1) Hubungi createProcess () untuk membuka program target.
2) Gunakan FindWindow () untuk menemukan pegangan jendela dari program target.
3) Temukan pegangan kotak teks dan pesan dari tombol, atur teks menggunakan metode sendMessage (), dan picu acara.
Oke, ini memang sangat sederhana, tetapi ketika saya menerapkannya, saya menemukan bahwa hasilnya adalah: ketika program saya memulai dan membuka program target, jendela percikannya dan jendela utamanya akan ditampilkan, bahkan jika saya menggunakan FindWindow () Untuk menemukan pegangan jendela utama, dan hubungi SendMessage (WindowHandle, SW_HIDE) untuk menyembunyikan jendela, jendela utama akan ditampilkan sejenak.
Jadi bagaimana menyelesaikan masalah ini? , itu tidak berpengaruh. . . . Lanjutkan mencari dokumen. , dan jika ditugaskan setelah nama desktop, proses akan diluncurkan pada desktop yang ditentukan.
1) Pertama, buat desktop virtual.
const
Desktopname = 'mydesk';
Fdesktop: = createdesktop (desktopname, nil, nil, 0, generic_all, nil);
Beberapa desktop dapat dibuat di Windows, dan Switchdesktop () digunakan untuk beralih desktop mana yang ditampilkan. Windows sendiri diimplementasikan oleh Virtual Desktop Function. . bahan:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/enumdesktops.asp
2) Saat createProcess, tentukan program untuk dijalankan pada desktop yang baru saya hasilkan:
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;
Jika bukan createProcess (pchar (nama file), nil, nil, nil, nil, true, create_new_console+high_priority_class, nil, pchar (ekstraktfilePath (filepath)), startinfo, fproceInfo) kemudian mulai
MessageBox (Application.Handle, 'Error When Init Voice (5).', PCHAR (Application.Title), MB_ICONWARNING);
KELUAR;
akhir;
3) Gunakan FindWindow untuk menemukan jendela utama program ini
Awalnya saya menuliskan kode seperti ini:
Untuk I: = 0 hingga 60 Mulai // tunggu 30 detik untuk membuka jendela utama
WindowHandle: = findWindow (nil, 'windowcaption');
Jika WindowHandle <> 0 maka mulailah
merusak;
akhir;
Tidur (500);
akhir;
Namun, praktik telah membuktikan bahwa dengan cara ini, jendela yang tidak ada di desktop saat ini tidak dapat ditemukan.
Jawabannya adalah Anda dapat menggunakan fungsi setThreadDesktop (), yang dapat mengatur desktop tempat utas bekerja, jadi saya menambahkan kalimat lain sebelum kode di atas:
Jika tidak setThreaddesktop (fdesktop) maka mulailah
KELUAR;
akhir;
Namun, setelah program dijalankan, fungsi kembali salah, menunjukkan bahwa panggilan metode gagal.
Fungsi SetThreadDesktop akan gagal jika utas panggilan memiliki jendela atau kait pada desktop saat ini (kecuali parameter hdesktop adalah pegangan ke desktop saat ini).
Oh, ternyata tidak ada hal UI di utas yang perlu beralih desktop, tetapi saya menyebut metode ini di utas utama program, dan tentu saja akan gagal. Perlu menggunakannya, bukankah boleh mengikat utas "bersih" ke desktop baru, dan kemudian menggunakan metode findWindow () untuk menemukan windowhandle yang saya cari? Kodenya adalah sebagai berikut:
TfindWindowThread = class (tThread)
Pribadi
Fdesktop: Thandle;
FWindowHandle: Thandle;
terlindung
prosedur dieksekusi (); override;
publik
Konstruktor Create (AreaSuspended: Boolean; Const Adesktop: Thandle); Reintroduce;
Properti WindowHandle: Thandle Read fwindowhandle;
akhir;
{TFindWindowThread}
Prosedur tfindWindowThread.execute ();
var
I: Integer;
Mulai
// Buat utas saat ini temukan jendela di desktop baru!
Jika tidak setThreaddesktop (fdesktop) maka mulailah
KELUAR;
akhir;
Untuk I: = 0 hingga 60 Mulai // tunggu 30 detik untuk membuka jendela utama
Fwindowhandle: = findWindow (nil, pchar ('windowcaption'));
Jika fWindowHandle <> 0 maka mulailah
merusak;
akhir;
Tidur (500);
akhir;
akhir;
konstruktor tfindwindowthread.create (AreaResuspended: boolean; const adesktop: thandle);
Mulai
warisan create (AreaTeSuspended);
Fdesktop: = adesktop;
akhir;
Dan kode dalam program utama menjadi seperti ini:
FindWindowThread: = tFindWindowThread.create (false, fdesktop);
mencoba
FindWindowthread.waitfor;
FMainWindowHandle: = findWindowThread.windowhandle;
Akhirnya
FindWindowThread.Free;
akhir;
Jika FMainWindowHandle = 0 maka mulailah
MessageBox (Application.Handle, 'Error When Init Voice (6).', PCHAR (Application.Title), MB_ICONWARNING);
KELUAR;
akhir;
Haha, ini berhasil, sehingga Anda dapat menemukan pegangan jendela dengan lancar.
4) Akhirnya, gunakan pegangan jendela utama ini untuk menemukan pegangan editbox di dalam, sebagai berikut:
FedItWindow: = findWindowex (fmainwindowhandle, 0, pchar ('edit'), nil);
Saya telah menentukan nama kelas dari kotak teks ini di sini, dan nama ini dapat diperoleh dengan Spy ++.
Pekerjaan inisialisasi berakhir di sini. Jadi panggilan fungsi sama seperti biasa:
if (fmainwindowhandle = 0) atau (fedItwindow = 0) lalu mulailah
KELUAR;
akhir;
SendMessage (FedItWindow, WM_SETTEXT, 0, LongInt (@atext [1]));
SendMessage (FMainWindowHandle, WM_Command, $ 8012, $ 0);
Angka $ 8012 juga merupakan ID sumber daya yang diperoleh dengan menggunakan SPY ++.
Akhirnya, jangan lupa untuk menutup program dan melepaskan desktop virtual:
Jika fproceInfo.hprocess <> 0 maka mulailah
TerminateProcess (fproceInfo.hprocess, 0);
akhir;
Jika fdesktop <> 0 maka mulailah
Closedesktop (fdesktop);
akhir;
OK, ini hampir dengan sempurna mengimplementasikan fungsi program panggilan latar belakang, yang akan sepenuhnya transparan bagi pelanggan akhir, dan pelanggan tidak merasa bahwa ada program lain yang bekerja di latar belakang. Bukankah itu sangat bagus?
Jika Anda memiliki saran untuk perbaikan, atau pertukaran, Anda dapat mengirim ke: Tonyki [at] citiz.net