البرنامج الذي أعمل عليه مؤخرًا ، يجب إكمال بعضه عن طريق الاتصال بالبرامج الأخرى ، ولكن هذا البرنامج يحتوي فقط على ملفات قابلة للتنفيذ ولا يوجد رمز مصدر على الإطلاق. بدأت بعد بدء البرنامج.
الحديث عن هذا ، أعتقد أن لديك بعض الأفكار الأولية لهذه الوظيفة.
1) استدعاء CreateProcess () لفتح البرنامج الهدف.
2) استخدم FindWindow () للعثور على مقبض نافذة البرنامج المستهدف.
3) ابحث عن مقبض مربع النص و messageid من الزر ، وضبط النص باستخدام طريقة sendMessage () ، وتشغيل الحدث.
حسنًا ، هذا أمر بسيط للغاية بالفعل ، لكن عندما قمت بتطبيقه ، وجدت أن نتيجة ذلك كانت: عندما بدأ البرنامج وفتح البرنامج الهدف ، سيتم عرض نافذة الرش والنافذة الرئيسية ، حتى لو كنت أستخدم FindWindow () للعثور على مقبض النافذة الرئيسي ، واتصال SendMessage (WindowHandle ، SW_Hide) لإخفاء النافذة ، سيتم عرض النافذة الرئيسية للحظة.
إذن كيف أحل هذه المشكلة ، بالطبع ، أنا أبحث عن طريقة على CreateProcess (). ، ليس له أي تأثير. . . . استمر في البحث عن المستند. ، وإذا تم تعيينه بعد اسم سطح المكتب ، فسيتم إطلاق العملية على سطح المكتب المحدد.
1) أولاً ، إنشاء سطح مكتب افتراضي.
كونست
DesktOpName = 'mydesk' ؛
fdesktop: = createSkTop (DesktOpName ، nil ، nil ، 0 ، generic_all ، nil) ؛
يمكن إنشاء أجهزة الكمبيوتر المكتبية المتعددة في Windows ، ويمكن استخدام SwitchDesktop () للتبديل. يتم تنفيذ Windows نفسها بواسطة وظيفة سطح المكتب الافتراضية. . مادة:
http://msdn.microsoft.com/library/default.asp؟url=/library/en-us/dllproc/base/enumdesktops.asp
2) عند CreateProcess ، حدد البرنامج الذي سيتم تشغيله على سطح المكتب الذي تم إنشاؤه حديثًا:
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 ؛
إذا لم يكن CreateProcess (PCHAR (اسم الملف) ، NIL ، NIL ، NIL ، NIL ، TRUE ، CREATE_NEW_CONSOLE+HIGH_PRIORITY_CLASS ، NIL ، PCHAR (extractfilepath (filepath)) ، startInfo ، fproceinfo) ثم تبدأ
MessageBox (application.handle ، "خطأ عند init Voice (5). '، pchar (application.title) ، mb_iconwarning) ؛
مخرج؛
نهاية؛
3) استخدم FindWindow للعثور على النافذة الرئيسية للبرنامج
في البداية كتبت الكود مثل هذا:
لأني: = 0 إلى 60 لا تبدأ / /انتظر 30 ثانية لفتح النافذة الرئيسية
WindowHandle: = FindWindow (لا شيء ، "WindowCaption") ؛
إذا كان WindowHandle <> 0 ثم ابدأ
استراحة؛
نهاية؛
النوم (500) ؛
نهاية؛
ومع ذلك ، فقد أثبتت الممارسة أنه لا يمكن العثور على النافذة الموجودة في سطح المكتب الحالي.
الجواب هو أنه يمكنك استخدام وظيفة setThReadDeskTop () ، والتي يمكن أن تعدل سطح المكتب حيث يعمل مؤشر الترابط ، لذلك أضفت جملة أخرى قبل الرمز أعلاه:
إذا لم يكن setThReadDesktop (fdesktop) ثم ابدأ
مخرج؛
نهاية؛
ومع ذلك ، بعد تشغيل البرنامج ، تُرجع الوظيفة الخاطئة ، مما يشير إلى فشل استدعاء الطريقة.
ستفشل وظيفة setThReadDesktop إذا كان مؤشر ترابط الاتصال يحتوي على أي نوافذ أو خطافات على سطح المكتب الحالي (ما لم تكن معلمة HDESKTOP بمقبض لسطح المكتب الحالي).
أوه ، اتضح أنه لا يوجد شيء واجهة المستخدم في الخيط الذي يحتاج إلى تبديل سطح المكتب ، لكنني أسميت هذه الطريقة في الموضوع الرئيسي للبرنامج ، وبالطبع سيكون من السهل معرفة ذلك ، أنا فقط أنا فقط أنا فقط أنا فقط أعرف ذلك. تحتاج إلى استخدام واحد ليس على ما يرام لربط مؤشر ترابط "نظيف" لسطح المكتب الجديد ، ثم استخدم طريقة FindWindow () للعثور على WindowHandle الذي أبحث عنه؟ الرمز كما يلي:
tfindwindowthread = فئة (tthread)
خاص
fdesktop: Thandle ؛
fwindowhandle: Thandle ؛
محمية
الإجراء تنفيذ () ؛ تجاوز ؛
عام
إنشاء مُنشئ (Acreatesususeded: Boolean ؛ const adesktop: thandle) ؛ إعادة تقديم ؛
Property WindowHandle: Thandle اقرأ fwindowhandle ؛
نهاية؛
{tfindwindowthread}
الإجراء tfindwindowthRead.execute () ؛
var
أنا: عدد صحيح.
يبدأ
// اجعل سلسلة المواضيع الحالية تجد نافذة على سطح المكتب الجديد!
إذا لم يكن setThReadDesktop (fdesktop) ثم ابدأ
مخرج؛
نهاية؛
لأني: = 0 إلى 60 لا تبدأ / /انتظر 30 ثانية لفتح النافذة الرئيسية
fwindowhandle: = findWindow (nil ، pchar ('windowcaption')) ؛
إذا كان fwindowhandle <> 0 ثم ابدأ
استراحة؛
نهاية؛
النوم (500) ؛
نهاية؛
نهاية؛
مُنشئ tfindwindowthroad.create (Acreatesususeded: Boolean ؛ const adesktop: thandle) ؛
يبدأ
خلق ورث (AcreatesuseSpended) ؛
fdesktop: = adesktop ؛
نهاية؛
ويصبح الرمز في البرنامج الرئيسي هكذا:
FindWindowThread: = tfindwindowthread.create (false ، fdesktop) ؛
يحاول
FindWindowThread.WAITFOR ؛
fmainwindowhandle: = findwindowthread.windowhandle ؛
أخيراً
FindWindowThread.free ؛
نهاية؛
إذا كان fmainwindowhandle = 0 ثم ابدأ
MessageBox (application.handle ، "خطأ عند init Voice (6). '، pchar (application.title) ، mb_iconwarning) ؛
مخرج؛
نهاية؛
هاها ، إنه ناجح ، حتى تتمكن من العثور على مقبض النافذة بسلاسة.
4) أخيرًا ، استخدم مقبض النافذة الرئيسي هذا للعثور على مقبض Editbox Inside ، على النحو التالي:
feditwindow: = findWindowex (fmainwindowhandle ، 0 ، pchar ('edit') ، nil) ؛
لقد حددت اسم ClassName لمربع النص هذا هنا ، ويمكن الحصول على هذا الاسم باستخدام Spy ++.
ينتهي أعمال التهيئة هنا. لذا فإن دعوة الوظيفة هي نفسها كالمعتاد:
إذا (fmainwindowhandle = 0) أو (feditwindow = 0) ثم ابدأ
مخرج؛
نهاية؛
SendMessage (FeditWindow ، WM_Settext ، 0 ، longint (atext [1])) ؛
SendMessage (fmainwindowhandle ، WM_Command ، 8012 دولار ، $ 0) ؛
الرقم 8012 دولار هو أيضا معرف المورد الذي تم الحصول عليه باستخدام SPY ++.
أخيرًا ، لا تنس إغلاق البرنامج وإطلاق سراح سطح المكتب الظاهري:
إذا كان fproceinfo.hprocess <> 0 ثم ابدأ
TerminateProcess (fproceinfo.hprocess ، 0) ؛
نهاية؛
إذا كان fdesktop <> 0 ثم ابدأ
learesktop (fdesktop) ؛
نهاية؛
حسنًا ، هذا ينفذ بشكل مثالي وظيفة برنامج استدعاء الخلفية ، والذي سيكون شفافًا تمامًا للعميل النهائي ، ولا يشعر العميل ببساطة أن هناك برنامجًا آخر يعمل في الخلفية. أليس هذا جيدا جدا؟
إذا كان لديك أي اقتراحات للتحسين أو التبادل ، فيمكنك إرسال البريد إلى: Tonyki [AT] Citiz.net