Aracılığıyla paylaş


WPF ve Win32 Birlikte Çalışması

Bu konu başlığında, Windows Presentation Foundation (WPF) ve Win32 kodunun birlikte nasıl çalışamaya yönelik bir genel bakış sunulmaktadır. WPF, uygulama oluşturmak için zengin bir ortam sağlar. Ancak, Win32 koduna önemli bir yatırım yaptığınızda, bu kodun bir kısmını yeniden kullanmak daha etkili olabilir.

WPF ve Win32 Birlikte Çalışma Temelleri

WPF ile Win32 kodu arasında birlikte çalışmak için iki temel teknik vardır.

  • WPF içeriğini win32 penceresinde barındır. Bu teknikle, standart bir Win32 penceresi ve uygulaması çerçevesinde WPF'nin gelişmiş grafik özelliklerini kullanabilirsiniz.

  • WPF içeriğinde win32 penceresi barındırma. Bu teknikle, diğer WPF içeriği bağlamında mevcut bir özel Win32 denetimini kullanabilir ve verileri sınırlar arasında geçirebilirsiniz.

Bu tekniklerin her biri kavramsal olarak bu konuda tanıtılmaktadır. Win32'de WPF barındırmaya ilişkin daha kod odaklı bir çizim için bkz . İzlenecek yol: Win32'de WPF İçeriği Barındırma. WPF'de Win32 barındırmaya ilişkin daha kod odaklı bir çizim için bkz . İzlenecek yol: WPF'de Win32 Denetimi Barındırma.

WPF Birlikte Çalışma Projeleri

WPF API'leri yönetilen koddur, ancak mevcut Win32 programlarının çoğu yönetilmeyen C++ dilinde yazılır. Gerçek bir yönetilmeyen programdan WPF API'lerini çağıramazsınız. Ancak, Microsoft Visual C++ derleyicisi ile seçeneğini kullanarak /clr , yönetilen ve yönetilmeyen API çağrılarını sorunsuz bir şekilde karıştırabileceğiniz karma bir yönetilen yönetilmeyen program oluşturabilirsiniz.

Proje düzeyinde bir karmaşıklık, Genişletilebilir Uygulama Biçimlendirme Dili (XAML) dosyalarını bir C++ projesinde derleyemezsiniz. Bunu telafi etmek için birkaç proje bölme tekniği vardır.

  • Derlenmiş derleme olarak tüm XAML sayfalarınızı içeren bir C# DLL oluşturun ve C++ yürütülebilir dosyanızın bu DLL'yi başvuru olarak içermesini sağlayın.

  • WPF içeriği için bir C# yürütülebilir dosyası oluşturun ve Win32 içeriğini içeren bir C++ DLL'sine başvurmasını sağlayın.

  • XAML'nizi derlemek yerine çalışma zamanında herhangi bir XAML yüklemek için kullanın Load .

  • XAML'yi hiç kullanmayın ve öğesinden öğe ağacını Applicationoluşturarak kodda tüm WPF'nizi yazın.

Size en uygun yaklaşımı kullanın.

Dekont

Daha önce C++/CLI kullanmadıysanız, birlikte çalışma kodu örneklerinde ve nullptr gibi gcnew bazı "yeni" anahtar sözcükler görebilirsiniz. Bu anahtar sözcükler eski çift alt çizgi söz diziminin (__gc) yerini alır ve C++ dilinde yönetilen kod için daha doğal bir söz dizimi sağlar. C++/CLI ile yönetilen özellikler hakkında daha fazla bilgi edinmek için bkz . Çalışma Zamanı Platformları için Bileşen Uzantıları.

WPF Hwnd'leri Nasıl Kullanır?

WPF "HWND birlikte çalışma" özelliğini kullanmak için WPF'nin HWND'leri nasıl kullandığını anlamanız gerekir. Herhangi bir HWND için WPF işlemesini DirectX işleme veya GDI / GDI+ işleme ile karıştıramazsınız. Bunun bir dizi etkisi vardır. Öncelikle, bu işleme modellerini bir arada kullanmak için bir birlikte çalışma çözümü oluşturmanız ve kullanmayı seçtiğiniz her işleme modeli için belirlenmiş birlikte çalışma kesimlerini kullanmanız gerekir. Ayrıca, işleme davranışı birlikte çalışma çözümünüzün gerçekleştirebileceği şeyler için bir "hava sahası" kısıtlaması oluşturur. "Hava sahası" kavramı, Teknoloji Bölgelerine Genel Bakış konusunda daha ayrıntılı olarak açıklanmıştır.

Ekrandaki tüm WPF öğeleri sonuçta bir HWND tarafından desteklenir. WPF oluşturduğunuzda, WPF Windowbir üst düzey HWND oluşturur ve ve WPF içeriğini HWND içine koymak Window için bir HwndSource kullanır. Uygulamadaki WPF içeriğinizin geri kalanı tekil HWND'yi paylaşır. Özel durum menüler, birleşik giriş kutusu açılan pencereleri ve diğer açılır pencerelerdir. Bu öğeler kendi üst düzey pencerelerini oluşturur. Bu nedenle WPF menüsü, onu içeren HWND penceresinin kenarından geçebilir. WPF'nin içine bir HWND koymak için kullandığınızda HwndHost WPF, Win32'ye yeni alt HWND'nin WPF Window HWND'ye göre nasıl konumlandıracağını bildirir.

HWND ile ilgili bir kavram, her HWND içinde ve arasında saydamlıktır. Bu konu, Teknoloji Bölgelerine Genel Bakış konusunda da ele alınmıştır.

Microsoft Win32 Penceresinde WPF İçeriği Barındırma

Win32 penceresinde WPF barındırmanın HwndSource anahtarı sınıfıdır. Bu sınıf, WPF içeriğini bir Win32 penceresine kaydırarak WPF içeriğinin kullanıcı arabiriminize alt pencere olarak eklenebilmesini sağlar. Aşağıdaki yaklaşım, Win32 ve WPF'yi tek bir uygulamada birleştirir.

  1. WPF içeriğinizi (içerik kök öğesi) yönetilen sınıf olarak uygulayın. Genellikle, sınıfı birden çok alt öğe içerebilen ve/veya veya gibi DockPanelPagebir kök öğe olarak kullanılan sınıflardan birini devralır. Sonraki adımlarda, bu sınıf WPF içerik sınıfı olarak adlandırılır ve sınıfın örnekleri WPF içerik nesneleri olarak adlandırılır.

  2. C++/CLI ile bir Windows uygulaması uygulayın. Mevcut yönetilmeyen bir C++ uygulamasıyla başlıyorsanız, genellikle proje ayarlarınızı derleyici bayrağını içerecek /clr şekilde değiştirerek yönetilen kodu çağırmasını etkinleştirebilirsiniz (derlemeyi desteklemek /clr için gerekli olabileceklerin tam kapsamı bu konu başlığında açıklanmaz).

  3. İş parçacığı modelini Tek İş Parçacıklı Daire (STA) olarak ayarlayın. WPF bu iş parçacığı modelini kullanır.

  4. Pencere yordamınızda WM_CREATE bildirimini işleyin.

  5. İşleyici (veya işleyicinin çağırdığını bir işlev) içinde aşağıdakileri yapın:

    1. Parametresi olarak parent üst pencere HWND'si ile yeni HwndSource bir nesne oluşturun.

    2. WPF içerik sınıfınızın bir örneğini oluşturun.

    3. NESNE RootVisual özelliğine WPF içerik nesnesine bir başvuru atayınHwndSource.

    4. HwndSource object Handle özelliği pencere tutamacını (HWND) içerir. Uygulamanızın yönetilmeyen bölümünde kullanabileceğiniz bir HWND almak için bir HWND'ye yayınlanmıştır Handle.ToPointer() .

  6. WPF içerik nesnenize başvuru tutan statik bir alan içeren yönetilen bir sınıf uygulayın. Bu sınıf, Win32 kodunuzdan WPF içerik nesnesine başvuru almanızı sağlar, ancak daha da önemlisi istemeden çöp toplamanızı HwndSource engeller.

  7. WPF içerik nesnesi olaylarından birine veya daha fazlasına işleyici ekleyerek WPF içerik nesnesinden bildirimler alın.

  8. Özellikleri, çağrı yöntemlerini vb. ayarlamak için statik alanda depoladığınız başvuruyu kullanarak WPF içerik nesnesiyle iletişim kurun.

Dekont

Ayrı bir derleme oluşturup başvuruda bulunursanız, içerik sınıfının varsayılan kısmi sınıfını kullanarak XAML'de Birinci Adım için WPF içerik sınıfı tanımının bir kısmını veya tümünü yapabilirsiniz. Genellikle bir Application nesneyi XAML'yi derlemenin bir parçası olarak ekleseniz de, bunu birlikte çalışma işleminin bir parçası olarak kullanmazsınız Application , uygulama tarafından başvurulan XAML dosyaları için yalnızca bir veya daha fazla kök sınıf kullanır ve kısmi sınıflarına başvurursunuz. Yordamın geri kalanı temelde yukarıda açıklanana benzer.

Bu adımların her biri, İzlenecek Yol: Win32'de WPF İçeriği Barındırma başlığındaki kod aracılığıyla gösterilmiştir.

WPF'de Microsoft Win32 Penceresi Barındırma

Win32 penceresini diğer WPF içeriğinde barındırmanın HwndHost anahtarı sınıfıdır. Bu sınıf, bir WPF öğesi ağacına eklenebilen bir WPF öğesinde pencereyi sarmalar. HwndHost ayrıca barındırılan pencere için iletileri işleme gibi görevleri gerçekleştirmenize olanak sağlayan API'leri de destekler. Temel yordam:

  1. WPF uygulaması için bir öğe ağacı oluşturun (kod veya işaretleme yoluyla olabilir). Uygulamanın alt öğe olarak eklenebileceği öğe ağacında HwndHost uygun ve izin verilen bir nokta bulun. Bu adımların geri kalanında, bu öğeye ayırma öğesi denir.

  2. Win32 içeriğinizi barındıran bir nesne oluşturmak için öğesinden HwndHost türetin.

  3. Bu konak sınıfında yöntemini BuildWindowCoregeçersiz kılınHwndHost. Barındırılan pencerenin HWND'sini döndürür. Gerçek denetimleri döndürülen pencerenin alt penceresi olarak kaydırmak isteyebilirsiniz; denetimleri bir konak penceresinde sarmalama, WPF içeriğinizin denetimlerden bildirim alması için basit bir yol sağlar. Bu teknik, barındırılan denetim sınırında ileti işlemeyle ilgili bazı Win32 sorunlarını düzeltmeye yardımcı olur.

  4. HwndHost ve WndProcyöntemlerini DestroyWindowCore geçersiz kılın. Burada amaç, özellikle yönetilmeyen nesnelere başvurular oluşturduysanız, temizlemeyi işlemek ve barındırılan içeriğe başvuruları kaldırmaktır.

  5. Arka planda kod dosyanızda, denetim barındırma sınıfının bir örneğini oluşturun ve bunu ayırma öğesinin alt öğesi yapın. Genellikle gibi Loadedbir olay işleyicisi kullanırsınız veya kısmi sınıf oluşturucuyu kullanırsınız. Ancak birlikte çalışma zamanı davranışı aracılığıyla birlikte çalışma içeriği de ekleyebilirsiniz.

  6. Denetim bildirimleri gibi seçili pencere iletilerini işleme. İki yaklaşım vardır. her ikisi de ileti akışına aynı erişimi sağladığından, seçiminiz büyük ölçüde programlama kolaylığı açısından önemlidir.

    • yöntemini WndProcgeçersiz kılma işleminizde tüm iletiler (yalnızca kapatma iletileri için değil) için ileti işleme uygulayınHwndHost.

    • Barındırma WPF öğesinin olayı işleyerek iletileri işlemesini sağlayın MessageHook . Bu olay, barındırılan pencerenin ana pencere yordamına gönderilen her ileti için oluşturulur.

    • kullanarak WndProcişlem dışı olan pencerelerin iletilerini işleyemezsiniz.

  7. Yönetilmeyen SendMessage işlevi çağırmak için platform çağrısı kullanarak barındırılan pencereyle iletişim kurun.

Bu adımların izlenmesi, fare girişiyle çalışan bir uygulama oluşturur. Arabirimini uygulayarak IKeyboardInputSink barındırılan pencereniz için sekme desteği ekleyebilirsiniz.

Bu adımların her biri, İzlenecek Yol: WPF'de Win32 Denetimi Barındırma başlığındaki kod aracılığıyla gösterilmiştir.

WPF İçinde Hwnds

Özel bir kontrol olarak düşünebilirsiniz HwndHost . (Teknik olarak, HwndHost türetilmiş bir FrameworkElement sınıftır, türetilmiş bir Control sınıftır, ancak birlikte çalışma amaçları için bir denetim olarak kabul edilebilir.) HwndHost barındırılan içeriğin temel Win32 doğasını özetler; böylece WPF'nin geri kalanı barındırılan içeriği başka bir denetim benzeri nesne olarak kabul eder ve girişi işlemelidir. HwndHost genellikle herhangi bir WPF FrameworkElementgibi davranır, ancak temel alınan HWND'lerin destekleyebilecekleri sınırlamalara bağlı olarak çıkış (çizim ve grafikler) ve giriş (fare ve klavye) ile ilgili bazı önemli farklılıklar vardır.

Çıkış Davranışındaki Önemli Farklar

  • FrameworkElement, temel sınıfıdır ve kullanıcı arabiriminde HwndHost değişiklik olduğunu ima eden birkaç özelliğe sahiptir. Bunlar, öğe içindeki öğelerin düzenini üst öğe olarak değiştiren gibi FrameworkElement.FlowDirectionözellikleri içerir. Ancak, bu özelliklerin çoğu, bu tür eşdeğerler mevcut olsa bile olası Win32 eşdeğerleriyle eşlenmez. Bu özelliklerin ve anlamlarının çok fazla olması, eşlemelerin pratik olması için çok fazla işleme teknolojisine özgü. Bu nedenle, gibi FlowDirectionHwndHost özellikleri ayarlamanın hiçbir etkisi yoktur.

  • HwndHost dönüşümden döndürülemez, ölçeklendirilemez, çarpıtılamaz veya başka bir şekilde etkilenmez.

  • HwndHost özelliği (alfa karıştırma) desteklemez Opacity . içindeki HwndHost içerik alfa bilgileri içeren işlemler gerçekleştiriyorsa System.Drawing , bu kendisi bir ihlal değildir, ancak HwndHost bütün olarak yalnızca Opaklık = 1,0 (%100) değerini destekler.

  • HwndHost aynı üst düzey pencerede diğer WPF öğelerinin üstünde görünür. Ancak, ToolTip veya ContextMenu oluşturulan menü ayrı bir üst düzey penceredir ve bu nedenle ile HwndHostdoğru şekilde davranır.

  • HwndHost üst UIElementöğesinin kırpma bölgesine saygı göstermez. Bir sınıfı bir kaydırma bölgesi veya Canvasiçine yerleştirmeye HwndHost çalışırsanız, bu olası bir sorundur.

Giriş Davranışındaki Önemli Farklar

  • Genel olarak, giriş cihazlarının kapsamı barındırılan HwndHost Win32 bölgesi içinde olsa da, giriş olayları doğrudan Win32'ye gider.

  • Fare üzerindeyken HwndHostuygulamanız WPF fare olaylarını almaz ve WPF özelliğinin IsMouseOver değeri olur false.

  • klavye odağına HwndHost sahip olsa da uygulamanız WPF klavye olaylarını almaz ve WPF özelliğinin IsKeyboardFocusWithin değeri olur false.

  • Odak içinde HwndHost olduğunda ve içinde başka bir denetime değiştiğinde HwndHostuygulamanız WPF olaylarını GotFocus veya LostFocusalmayacaktır.

  • İlgili ekran kalemi özellikleri ve olayları benzerdir ve ekran kalemi sona ererken HwndHostbilgileri raporlamaz.

Sekme, Anımsatıcılar ve Hızlandırıcılar

IKeyboardInputSink ve IKeyboardInputSite arabirimleri karma WPF ve Win32 uygulamaları için sorunsuz bir klavye deneyimi oluşturmanıza olanak tanır:

  • Win32 ve WPF bileşenleri arasında sekme

  • Odak bir Win32 bileşeni içinde olduğunda ve bir WPF bileşeni içinde olduğunda çalışan anımsatıcılar ve hızlandırıcılar.

HwndHost ve HwndSource sınıflarının IKeyboardInputSinkher ikisi de uygulamasını sağlar, ancak daha gelişmiş senaryolar için istediğiniz tüm giriş iletilerini işlemeyebilir. İstediğiniz klavye davranışını elde etmek için uygun yöntemleri geçersiz kılın.

Arabirimler yalnızca WPF ile Win32 bölgeleri arasındaki geçişte ne olacağı konusunda destek sağlar. Win32 bölgesinde, sekme davranışı, varsa, sekmeleme için uygulanan Win32 mantığı tarafından tamamen denetlenmektedir.

Ayrıca bkz.