نظرة عامة حول التشغيل التفاعلي ل Win32 و WPF

هذه صورة إلى يوفر نظرة عامة حول كيفية إلى تتفاعل WPFو Win32تعليمات برمجية. توفر Windows Presentation Foundation (WPF) بيئة منسق لإنشاء تطبيقات. مع ذلك، عند وجود استثمار حقيقية في تعليمات برمجية Win32، قد يكون أكثر فعالية إعادة استخدام بعض من هذه التعليمات البرمجية.

يشتمل هذا الموضوع على الأقسام التالية.

  • أساسيات التشغيل التفاعلي ل Win32 و WPF
  • مشاريع التشغيل التفاعلي WPF
  • كيفية استخدام WPF ل Hwnds
  • استضافة محتوى WPF في إطار Microsoft Win32
  • استضافة إطار Win32 Microsoft في WPF
  • التبويب‬, ‏‫التعليمات الرمزية القصيرة و المسرّعات‬
  • موضوعات ذات صلة

أساسيات التشغيل التفاعلي ل Win32 و WPF

هناك اثنين من الأساليب الأساسية للتشغيل التفاعلي بين التعليمات البرمجية WPF و Win32.

  • استضافة محتوى WPF في إطار Win32. يمكنك بواسطة هذه التقنية استخدام قدرات الرسومات المتقدمة من WPF داخل إطار عمل لإطار Win32 قياسي و تطبيق.

  • استضافة إطار Win32 في محتوى WPF. مع هذه التقنية يمكنك استخدام عنصر تحكم Win32 مخصص موجود في سياق من محتوى WPF أخر و تمرير البيانات عبر الحدود.

كل من هذه التقنيات يتم تقديمها مفهومياً في هذا الموضوع. للحصول على مزيد من التوضيح الخاص بالتعليمات البرمجية لاستضافة WPF في Win32, راجع الإرشادات التفصيلية: استضافة محتوى WPF في تطبيق Win32. للحصول على مزيد من التوضيح الخاص بالتعليمات البرمجية لاستضافة Win32 في WPF, راجع الإرشادات التفصيلية: استضافة عنصر تحكم Win32 بسيط في تطبيق WPF.

مشاريع التشغيل التفاعلي WPF

WPF واجهات API هي تعليمات برمجية مُدارة و لكن معظم برامج Win32 الموجودة مكتوبة في ++C غير المُدار. لا يمكنك استدعاء WPF واجهات API من برنامج غير مُدار حقيقي. مع ذلك، باستخدام خيار /clr مع مترجم ++Microsoft Visual C, يمكنك إنشاء برنامج مُدار-غير مُدار مختلط حيث يمكن بدون مشاكل مزج استدعاءات API المُدارة و الغير مُدارة.

أحد تعقيدات مستوى المشروع هو أنه لا يمكن ترجمة ملفات Extensible Application Markup Language (XAML) إلى مشروع ++C. توجد عدة أساليب قسمة المشروع لتعويض هذا.

  • قم بإنشاء #C DLLالتي تحتوي على كافة صفحات XAML الخاصة بك كتجميع مترجم و يجب أن يتضمن الملف القابل للتنفيذ ++C الخاص بك DLL كمرجع.

  • قم بإنشاء #C قابل للتنفيذ من أجل محتوى WPF، و اجعلها تشير إلى ++C DLL الذي يحتوي محتوى Win32.

  • استخدم Load لتحميل أي XAML في وقت التشغيل بدلاً من التحويل البرمجي لXAML الخاص بك.

  • لا تستخدم XAML و اكتب كافة WPF الخاص بك في التعليمات البرمجية, إنشاء شجرة عنصر من Application.

استخدام أي أسلوب يعمل بشكل أفضل لك.

ملاحظةملاحظة

إذا كنت لم تستخدم C++/CLI من قبل، قد تلاحظ بعض الكلمات "الجديدة" مثل gcnew و nullptr في أمثلة التعليمات البرمجية للتشغيل التفاعلي. هذه الكلمات الأساسية تحل محل بناء الجملة المزدوج و المسطر أسفل الأقدم ( __gc) و توفر بناء جملة طبيعية للتعليمات البرمجية المُدارة في ++C.لمزيد من المعلومات حول C++/CLI الميزات المُدارة, راجع Language Features for Targeting the CLR و Hello ، C + +/ CLI .

كيفية استخدام WPF ل Hwnds

لإجراء أكثر ما يمكن من WPF "HWND interop", تحتاج إلى فهم كيفية WPF يستخدم HWNDs. لأي HWDN, لا يمكن خلط تقديم WPF مع تقديم DirectX أو تقديم GDI / GDI+. ويكون لهذا عدد من ضمانات. بشكل أساسي، من أجل خلط نماذج التقديم هذه, يجب إنشاء حل التشغيل التفاعلي و و استخدام أجزاء من التشغيل التفاعلي لكل طراز تقديم الذي تختار استخدامه. أيضاً، سلوك التقديم ينشئ قيد "airspace" على ما يمكن لحل التشغيل التفاعلي الخاص بك تحقيقه. يتم شرح مفهوم "airspace" بتفصيل أكبر في موضوع التشغيل التفاعلي WPF: نظرة عامة p,g مناطق hgإطار و "airspace".

كل عناصر WPF على الشاشة يتم نسخها بواسطة HWND. عند إنشاء WPF Window، WPF ينشئ HWND ذو مستوى عالى و يستخدم HwndSource لوضع Window و محتوي WPF الخاص به داخل HWND. باقي محتوي WPF الخاص بك في التطبيق يشارك تلك HWND المفردة. استثناء هو القوائم, مربع التحرير السرد المنسدل و الإطارات المنبثقة الأخرى. تقوم هذه العناصر بإنشاء إطار المستوى العالي الخاص بهم، الذي هو سبب أن قائمة WPF من المحتمل أن تكون تتنقل بعد الحافة من إطار HWND الذي تحتويه. عند استخدام HwndHost لوضع HWND داخل WPF ، يقوم WPF بإعلام Win32 عن كيفية وضع التابع الجديد HWND نسبةً إلى WPF Window HWND.

مفهوم ذو الصلة ب HWND هو شفاف ضمن و بين كل HWND. يتم مناقشة ذلك أيضاً في موضوع التشغيل التفاعلي WPF: نظرة عامة p,g مناطق hgإطار و "airspace".

استضافة محتوى WPF في إطار Microsoft Win32

المفتاح لاستضافة WPF على إطار Win32 هو فئة HwndSource. هذه الفئة تلف محتوي WPF في إطار Win32، بحيث محتوى WPF يمكن أن يتم دمجه مع واجهة المستخدم (UI) الخاص بك كإطار تابع. يدمج الأسلوب التالي Win32 و WPF في تطبيق واحد.

  1. قم بتنفيذ محتوى WPF الخاص بك (عنصر جذر المحتوى) كفئة مُدارة. بشكل عام، ترث الفئة من أحد الفئات الذي يمكن أن تحتوي على عناصر تابعة متعددة و/أو تستخدم كعنصر جذر مثل DockPanel أو Page. في الخطوات اللاحقة, يتم الإشارة لهذه الفئة كفئة محتوى WPF و مثيلات الفئة يتم الإشارة إليها ككائنات محتوى WPF.

  2. تنفيذ تطبيق Win32 مع C++/CLI. إذا بدأت بتطبيق ++C غير مدار موجود، يمكنك عادةً تمكينه من استدعاء التعليمات البرمجية المدارة بواسطة تغيير إعدادات المشروع لتتضمن علامة برنامج التحويل البرمجي /clr (النطاق الكامل لما قد يكون ضروري لدعم التحويل البرمجي /clr الغير موضح في هذا الموضوع).

  3. تعيين ترابط طراز إلى مفرد للأجزاء مترابطة (STA). WPFيستخدم هذا نموذج مؤشر الترابط.

  4. قم بمعالجة إعلام WM_CREATE في إجراء الإطار الخاص بك.

  5. ضمن المعالج (أو دالة التي تستدعي المعالج) ، قم بما يلي:

    1. إنشاء كائن HwndSource جديد مع إطار الأصل HWDN كمعلمة parent.

    2. قم بإنشاء مثيل من فئة محتوي WPF الخاص بك.

    3. قم بتعيين مرجع إلى كائن محتوي WPF إلى خاصية RootVisual من كائن HwndSource.

    4. خاصية Handle من كائن HwndSource تحتوي على مؤشر الإطار (HWND). للحصول على HWND التي يمكنك استخدامه في الجزء غير المدار من التطبيق الخاص بك، حول Handle.ToPointer() إلى HWND.

  6. تنفيذ فئة مدارة التي تحتوي على حقل ثابت الذي يحتفظ بمرجع إلى كائن المحتوي WPF الخاص بك. تسمح هذه الفئة لك للحصول على مرجع إلى كائن محتوي WPF من التعليمات البرمجية Win32 الخاصة بك و لكن الأكثر الأهمية هو أنه يمنع HwndSource الخاص بك من أن يتم تجميع البيانات المهملة من دون قصد.

  7. تلقي إعلامات من كائن محتوي WPF عن طريق إرفاق معالج إلى واحد أو أكثر من أحداث كائن محتوى WPF.

  8. الاتصال مع كائن محتوى WPF باستخدام مرجع المخزن في حقل ثابت لتعيين الخصائص, استدعاء الأساليب, الخ

ملاحظةملاحظة

يمكنك القيام بعض أو كافة تعريف فئة محتوى WPF للخطوة الواحدة في XAML باستخدام الفئة الجزئية الافتراضية فئة المحتوى, في حالة إنشاء تجميع منفصل و ثم الرجوع إليه. على الرغم من أنك تضمّن عادة كائن Application كجزء من التحويل البرمجي لXAML إلى تجميع, لا تنتهي باستخدام ذلك Application كجزء من التشغيل التفاعلي ، فقط استخدم واحد أو أكثر من فئات الجذر لملفات XAML المشار إليها بواسطة التطبيق و تشير إلى الفئات الجزئية الخاصة بهم.يشبه باقي الإجراء ذلك الذي ورد ذكره أعلاه.

يتم توضيح كل من هذه الخطوات خلال التعليمات البرمجية في الموضوع الإرشادات التفصيلية: استضافة محتوى WPF في تطبيق Win32.

استضافة إطار Win32 Microsoft في WPF

المفتاح لاستضافة إطار Win32 ضمن محتوى WPF هو فئة HwndHost. التفاف هذه الفئة نافذة في WPFالعناصر التي يمكن إضافتها إلى WPFشجرة العنصر. HwndHostويدعم أيضاواجهات APIالتي تسمح لك إلى القيام بمهام مثل الرسائل العملية لإطار مستضافة. الإجراء الأساسي هو:

  1. قم بإنشاء شجرة عنصر لتطبيق WPF (يمكن من خلال التعليمات البرمجية أو العلامات). اعثر على نقطة مناسبة و مسموح بها في شجرة العنصر حيث تطبيق HwndHost يمكن إضافته كعنصر تابع. في باقي الخطوات يتم الإشارة إلى هذا العنصر كعنصر المحتجز.

  2. اشتق من HwndHost لإنشاء كائن يحمل محتوى Win32 الخاص بك.

  3. في تلك الفئة المضيفة, تجاوز أسلوب HwndHost BuildWindowCore. قم بإرجاع HWND من الإطار المستضاف. قد تحتاج إلى لف عنصر أو أكثر من عناصر تحكم الفعلية كإطار تابع للإطار الذي تم إرجاعه; التفاف عناصر التحكم في الإطار المضيف يوفر طريقة بسيطة لمحتوى WPF الخاص بك لتلقي الإعلامات من عناصر التحكم. تساعد هذه التقنية تصحيح بعض مشكلات Win32 المتعلقة بمعالجة الرسالة في حدود عنصر التحكم المستضاف.

  4. تجاوز أساليب HwndHost DestroyWindowCore و WndProc. الرغبة هنا هي معالجة التنظيف و إزالة المراجع إلى المحتوى المستضاف, بشكل خاص في حالة إنشاء مراجع إلى الكائنات غير المدارة.

  5. في ملف التعليمات البرمجية الخلفية، قم بإنشاء مثيل من عنصر التحكم المستضيف للفئة و جعله تابع للعنصر المحتجز. يمكن عادةً استخدام معالج حدث مثل Loaded, أو استخدام منشئ فئة جزئية. ولكن يمكنك أيضاً إضافة محتوى الاستنتاج خلال سلوك وقت التشغيل.

  6. رسائل الإطار المحددة من قبل العملية مثل إعلامات عنصر التحكم. هناك أسلوبين. يوفر كلاً منهم وصول متطابق لدفق الرسالة لذلك اختيارك أمر هام جدا من ملاءمة البرمجة.

    • قم بتنفيذ معالجة الرسائل لكافة الرسائل (وليس فقط رسائل إيقاف التشغيل) في تجاوز الخاص بك لأسلوب HwndHost WndProc.

    • جعل عنصر WPFالمستضيف يعالج الرسائل عن طريق معالجة حدث MessageHook. يتم رفع هذا الحدث لكل رسالة يتم إرسالها إلى إجراء الإطار الرئيسي للإطار المستضاف.

    • يتعذر معالجة الرسائل من الإطارات التي من خارج العملية باستخدام WndProc.

  7. الاتصال مع الإطار المضيف باستخدام استدعاء النظام الأساسي لاستدعاء الدالة SendMessage الغير المدارة.

اتباع الخطوات التالية ينشئ تطبيق يعمل مع الإدخال الماوس. يمكنك إضافة دعم الجدولة لإطار المستضاف عن طريق تنفيذ واجهة IKeyboardInputSink.

يتم توضيح كل من هذه الخطوات خلال التعليمات البرمجية في الموضوع الإرشادات التفصيلية: استضافة عنصر تحكم Win32 بسيط في تطبيق WPF.

Hwnds داخل WPF

يمكنك اعتبار HwndHost كعنصر تحكم خاص. (من الناحية التقنية، HwndHost هو فئة مشتقة FrameworkElement, ليس فئة مشتقة Control, و لكن يمكن اعتباره عنصر تحكم لأغراض التشغيل التفاعلي.)HwndHost تجرد طبيعة Win32 الأساسية للمحتوى المستضاف حتى يعتبر باقي WPF المحتوى المستضاف ككائن شبه تحكم آخر و الذي يجب أي يعرض و يعالج الإدخال. HwndHost بشكل عام يسلك مثل أي WPF FrameworkElement أخر، على الرغم من أنه توجد بعض الاختلافات الهامة حول الناتج (الرسم و الرسومات) و الإدخال (لوحة المفاتيح و الماوس) استناداً إلى قيود ما يمكن دعمه HWNDs الأساسي.

الاختلافات الجديرة بالذكر في سلوك الإخراج

  • FrameworkElement، و هو فئة أساس HwndHost، لديه خصائص قليلة التي يتضمن تغييرات إلى UI. هذه يتضمن الخصائص مثل FrameworkElement.FlowDirection، الذي يؤدي إلى تغيير تخطيط العناصر داخل هذا العنصر كالأصل. مع ذلك، لم يتم تعيين معظم هذه الخصائص إلى مكافئات Win32 المحتملة, حتى إن وجدت مثل هذه المكافئات. يوجد العديد من هذه الخصائص و تكون المعاني الخاصة بهم هم تقنية تقديم خاصة للتعيينات أن تكون عملية. لذلك، يتم تعيين هذه الخصائص مثل FlowDirection على HwndHost ليس له تأثير.

  • HwndHost لا يمكن تدويرها، تغيير حجمها، انحرافه، أو يتأثر بواسطة تحويل.

  • HwndHost لا يدعم خاصية Opacity(خلط ألفا). إذا كان المحتوى داخل HwndHost ينفذ عمليات System.Drawing الذي يتضمن معلومات ألفا, التي ليست انتهاك و لكن HwndHost بالكامل يدعم فقط تعتيم = 1.0 (100 %).

  • HwndHost سيظهر أعلى عناصر WPF الأخرى في نفس الإطار من مستوى عالي. مع ذلك، القائمة المُنشئة ToolTip أو ContextMenu هو إطار مستوى أعلى منفصل و لذلك ستعمل بشكل صحيح مع HwndHost.

  • HwndHost لا يحترم لقطة اقتصاص من UIElement الأصل. هذا من المحتمل أن يكون مشكلة في حالة محاولة وضع فئة HwndHost داخل منطقة تمرير أو Canvas.

الاختلافات الجديرة بالذكر في سلوك الإدخال

  • بشكل عام بينما يكون نطاق أجهزة الإدخال ضمن منطقة HwndHost المستضافة Win32 المنطقة، تتنقل أحداث الإدخال مباشرة إلى Win32.

  • بينما يكون الماوس فوق HwndHost، التطبيق الخاص بك لا يتلقى أحداث ماوس WPF, و القيمة من WPF خاصية IsMouseOver ستكون false.

  • بينما HwndHost يحتوي على تركيز لوحة المفاتيح, لن تتلقى التطبيق الخاص بك أحداث لوحة مفاتيح WPF و القيمة من WPF خاصية IsKeyboardFocusWithin سيكون false.

  • عندما يكون التركيز ضمن HwndHost و يتغير إلى عنصر تحكم آخر داخل HwndHost، لن يتلقى التطبيق الخاص بك WPF أحداث GotFocus أو LostFocus.

  • خصائص إبرة الفونوغراف المتعلقة و الأحداث متشابه, و لا يقوموا بإعلام المعلومات بينما إبرة الفونوغراف هي عبر HwndHost.

التبويب‬, ‏‫التعليمات الرمزية القصيرة و المسرّعات‬

واجهات IKeyboardInputSink و IKeyboardInputSite تسمح لك بإنشاء خبرة لوحة مفاتيح سلسة لتطبيقات WPF و Win32 المختلطة:

  • التبويب بين مكونات Win32 و WPF المكونات

  • التعليمات الرمزية القصيرة و المسرّعات‬ الذين يعملوا معاً عندما يكون التركيز ضمن مكون Win32 و عندما يكون داخل مكون WPF.

فئات HwndHost و HwndSource كلاً منهم يوفر تطبيقات من IKeyboardInputSink, و لكن قد لا يقوموا بمعالجة كل رسائل الإدخال المطلوبة من أجل السيناريوهات الأكثر تقدماً. تجاوز الطرق المناسبة للحصول على سلوك لوحة المفاتيح الذي تريده.

الواجهات فقط توفر دعمًا لما يحدث على الانتقال بين مناطق WPF و Win32. ضمن منطقة Win32، سلوك التبويب يكوت متحكم فيه تماماً من قبل منطق Win32 المطبّق للتبويب, إن وجد.

راجع أيضًا:

المرجع

HwndHost

HwndSource

System.Windows.Interop

المبادئ

الإرشادات التفصيلية: استضافة عنصر تحكم Win32 بسيط في تطبيق WPF

الإرشادات التفصيلية: استضافة محتوى WPF في تطبيق Win32