Win32 ve WPF Arasında İleti Döngüleri Paylaşma

bu konuda, ' de var olan ileti döngüsü kullanılarak Dispatcher veya birlikte çalışabilirlik kodunuzun Win32 tarafında ayrı bir ileti döngüsü oluşturarak Windows Presentation Foundation (WPF) ile birlikte çalışma için bir ileti döngüsünün nasıl uygulanacağı açıklanmaktadır.

ComponentDispatcher ve Ileti döngüsü

Birlikte çalışma ve klavye olay desteği için normal bir senaryo, IKeyboardInputSink veya gibi zaten uygulanmış sınıflardan alt sınıflara uygulanır IKeyboardInputSinkHwndSourceHwndHost . Ancak, klavye havuzu desteği, birlikte çalışma sınırlarınız genelinde ileti gönderirken ve alırken sahip olabileceğiniz tüm olası ileti döngüsü gereksinimlerini gidermez. Windows Presentation Foundation (WPF), bir uygulama iletisi döngüsü mimarisini şekillendirmesine yardımcı olmak için, ComponentDispatcher bir ileti döngüsünün izlenecek basit protokolü tanımlayan sınıfını sağlar.

ComponentDispatcher , birkaç üye sunan statik bir sınıftır. Her yöntemin kapsamı, çağıran iş parçacığına örtülü olarak bağlanır. Bir ileti döngüsü, bu API 'lerden bazılarını kritik zamanlarda çağırmalıdır (bir sonraki bölümde tanımlandığı gibi).

ComponentDispatcher diğer bileşenlerin (klavye havuzu gibi) dinleyebileceği olayları sağlar. DispatcherSınıf uygun bir dizide tüm uygun ComponentDispatcher yöntemleri çağırır. Kendi ileti döngünüzü uyguıyorsanız, kodunuz ComponentDispatcher benzer bir şekilde çağrılmasından sorumludur.

ComponentDispatcherBir iş parçacığında çağırma yöntemleri yalnızca o iş parçacığında kayıtlı olan olay işleyicilerini çağırır.

Ileti döngüleri yazma

Aşağıda, ComponentDispatcher kendi ileti döngünüzü yazarsanız kullanacağınız üyelerin denetim listesi verilmiştir:

  • PushModal: ileti döngünüz, iş parçacığının kalıcı olduğunu göstermek için bunu çağırmalıdır.

  • PopModal: ileti döngünüz, iş parçacığının kalıcı olmayan olarak döndürüldüğünü göstermek için bunu çağırmalıdır.

  • RaiseIdle: ileti döngünüz ComponentDispatcher , olayı oluşturması gerektiğini göstermek için bunu çağırmalıdır ThreadIdle . ComponentDispatcher ise yükseltmeyecektir ThreadIdleIsThreadModaltrue , ancak ileti döngüleri, RaiseIdleComponentDispatcher kalıcı durumundayken buna yanıt veremese de, çağrı yapmak için seçim gösterebilir.

  • RaiseThreadMessage: ileti döngünüz, yeni bir iletinin kullanılabilir olduğunu göstermek için bunu çağırmalıdır. Dönüş değeri, bir olayın dinleyicisinin iletiyi işlemediğini belirtir ComponentDispatcher . RaiseThreadMessageDöndürürse true (işlenmiş), dağıtıcı iletiyle birlikte hiçbir şey yapmaz. Dönüş değeri ise false , Dispatcher 'ın Win32 işlevini çağırması beklenir TranslateMessage ve sonra öğesini çağırın DispatchMessage .

ComponentDispatcher ve mevcut Ileti Işlemeyi kullanma

Aşağıda, ComponentDispatcher DEVRALıNAN WPF ileti döngüsüne güveniyorsanız kullanacağınız üyelerin denetim listesi verilmiştir.

  • IsThreadModal: uygulamanın kalıcı olup olmadığını döndürür (örneğin, bir kalıcı ileti döngüsü itilmiş). ComponentDispatcher Bu durum, sınıfı ileti döngüsünden bir sayı ve çağrı sakladığı için bu durumu izleyebilir PushModalPopModal .

  • ThreadFilterMessage ve ThreadPreprocessMessage Olaylar, temsilci etkinleştirmeleri için standart kuralları izler. Temsilciler belirtilmemiş bir düzende çağrılır ve ilki iletiyi işlenmiş olarak işaretlese bile tüm temsilciler çağrılır.

  • ThreadIdle: boşta işleme yapmak için uygun ve verimli bir zaman gösterir (iş parçacığı için başka bir bekleyen ileti yoktur). ThreadIdle iş parçacığı kalıcı ise oluşturulmaz.

  • ThreadFilterMessage: ileti göndericisinin işlediği tüm iletiler için oluşturulur.

  • ThreadPreprocessMessage: sırasında işlenmemiş tüm iletiler için oluşturulur ThreadFilterMessage .

Olay ThreadFilterMessage veya ThreadPreprocessMessage olaydan sonra, olay handled verilerinde başvuruya göre geçirilen parametre olduğunda bir ileti işlenir olarak kabul edilir true . , Varsa olay işleyicileri iletiyi yoksaymalıdır handledtrue çünkü bu, farklı işleyici iletiyi önce ele aldığı anlamına gelir. Her iki olaya yönelik olay işleyicileri iletiyi değiştirebilir. Dağıtıcı değiştirilmiş iletiyi göndermeli ve özgün değiştirilmemiş iletiyi almalıdır. ThreadPreprocessMessage Tüm dinleyicilerine dağıtılır, ancak mimari amaç yalnızca, hedeflenen iletilerin iletiye yanıt olarak kodu çağırması gereken HWND 'yi içeren en üst düzey pencere olur.

HwndSource ComponentDispatcher olaylarını nasıl değerlendirir

HwndSourceÜst düzey bir pencere (üst HWND yoksa) ise, ile kaydedilir ComponentDispatcher . ThreadPreprocessMessageTetiklenir ve ileti veya alt pencereler için tasarlanıyorsa,, HwndSourceHwndSourceIKeyboardInputSink.TranslateAcceleratorTranslateCharOnMnemonic klavye havuzu sırasını çağırır.

HwndSourceÜst düzey bir pencere (bir üst HWND varsa) değilse, işleme uygulanmaz. Yalnızca üst düzey pencerenin işleme yapması beklenir ve birlikte çalışabilirlik senaryosunun parçası olarak klavye havuzu desteğiyle bir üst düzey pencere olması beklenir.

WndProcBir üzerinde, HwndSource ilk Çağrılmakta olan uygun bir klavye havuzu yöntemi olmadan çağrılırsa, uygulamanız gibi daha üst düzey klavye olaylarını alacaktır KeyDown . Ancak, erişim anahtarı desteği gibi istenen klavye giriş modeli özelliklerini atladan klavye havuzu yöntemleri çağrılmaz. Bu durum ileti döngüsünün ilgili iş parçacığını doğru bir şekilde bilgilendirmediği ComponentDispatcher veya üst HWND doğru klavye havuzu yanıtlarını çağırmadığı için meydana gelebilir.

Yöntemini kullanarak bu ileti için kancalar eklediyseniz, klavye havuzuna giden bir ileti HWND 'ye gönderilmeyebilir AddHook . İleti, ileti göndericisi düzeyinde doğrudan işlenmiş ve işleve gönderilmemiş olabilir DispatchMessage .

Ayrıca bkz.