Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ten temat zawiera omówienie sposobu współdziałania programu Windows Presentation Foundation (WPF) i kodu Win32. WPF zapewnia bogate środowisko do tworzenia aplikacji. Jednak jeśli masz znaczną inwestycję w kod Win32, bardziej skuteczne może być ponowne użycie niektórych fragmentów tego kodu.
Podstawy współpracy WPF i Win32
Istnieją dwie podstawowe techniki współdziałania między kodami WPF i Win32.
Hostowanie zawartości WPF w oknie Win32. Dzięki tej technice można użyć zaawansowanych funkcji graficznych WPF w ramach standardowego okna i aplikacji Win32.
Hostowanie okna Win32 w zawartości WPF. Dzięki tej technice możesz użyć istniejącej niestandardowej kontrolki Win32 w kontekście innej zawartości WPF i przekazać dane przez granice.
Każda z tych technik jest koncepcyjnie wprowadzana w tym temacie. Aby uzyskać bardziej zorientowaną na kod ilustrację hostingu WPF w win32, zobacz Przewodnik: hosting zawartości WPF w Win32. Aby uzyskać bardziej zorientowaną na kod ilustrację hostingu Win32 w WPF, zobacz Przewodnik: hosting kontrolki Win32 w WPF.
Projekty współdziałania WPF
Interfejsy API WPF są kodem zarządzanym, ale większość istniejących programów Win32 jest zapisywana w niezarządzanym języku C++. Nie można wywoływać interfejsów API WPF z prawdziwego niezarządzanego programu. Jednak za pomocą /clr opcji w kompilatorze programu Microsoft Visual C++ można utworzyć mieszany program niezarządzany, w którym można bezproblemowo mieszać zarządzane i niezarządzane wywołania interfejsu API.
Jednym z komplikacji na poziomie projektu jest to, że nie można skompilować plików języka XAML (Extensible Application Markup Language) w projekcie C++. Istnieje kilka technik dzielenia projektów, aby to zrekompensować.
Utwórz bibliotekę DLL języka C#, która zawiera wszystkie strony XAML jako skompilowany zestaw, a następnie utwórz plik wykonywalny języka C++ zawierający bibliotekę DLL jako odwołanie.
Utwórz plik wykonywalny języka C# dla zawartości WPF i utwórz odwołanie do biblioteki DLL języka C++, która zawiera zawartość win32.
Użyj Load polecenia , aby załadować dowolny kod XAML w czasie wykonywania, zamiast kompilować kod XAML.
Nie należy w ogóle używać języka XAML i pisać cały plik WPF w kodzie, tworząc drzewo elementów z pliku Application.
Użyj dowolnego podejścia, które działa najlepiej dla Ciebie.
Uwaga / Notatka
Jeśli wcześniej nie używasz języka C++/CLI, możesz zauważyć kilka "nowych" słów kluczowych, takich jak gcnew i nullptr w przykładach kodu współdziałania. Te słowa kluczowe zastępują starszą składnię podwójnego podkreślenia (__gc) i zapewniają bardziej naturalną składnię kodu zarządzanego w języku C++. Aby dowiedzieć się więcej o funkcjach zarządzanych języka C++/CLI, zobacz Rozszerzenia składników dla platform środowiska uruchomieniowego.
Jak WPF używa Hwnds
Aby jak najlepiej wykorzystać interop WPF "HWND", musisz zrozumieć, jak WPF używa HWNDs. W przypadku dowolnego HWND nie można mieszać renderowania WPF z renderowaniem DirectX lub renderowaniem GDI/ GDI+. Ma to wiele konsekwencji. Przede wszystkim, aby w ogóle mieszać te modele renderowania, należy utworzyć rozwiązanie międzyoperacyjne i użyć wyznaczonych segmentów współdziałania dla każdego modelu renderowania, którego chcesz użyć. Ponadto zachowanie renderowania wprowadza ograniczenie dotyczące "sfery działania", co może wpłynąć na możliwości rozwiązania interoperacyjnego. Pojęcie "przestrzeni powietrznej" zostało szczegółowo wyjaśnione w temacie Omówienie regionów technologii.
Wszystkie elementy WPF na ekranie są ostatecznie wspierane przez HWND. Podczas tworzenia WPF WPF program WPF Windowtworzy HWND najwyższego poziomu i używa elementu HwndSource , aby umieścić Window i jego zawartość WPF wewnątrz HWND. Pozostała część zawartości WPF w aplikacji udostępnia pojedynczą wartość HWND. Wyjątkiem są listy rozwijane pól kombi, menu i inne wyskakujące okienka. Te elementy tworzą własne okno najwyższego poziomu, dlatego menu WPF może potencjalnie przejść obok krawędzi okna HWND, który go zawiera. Gdy używasz HwndHost do umieszczenia HWND wewnątrz WPF, WPF informuje Win32, jak umieścić nowe HWND jako element podrzędny względem HWND WPF Window.
Powiązana koncepcja HWND to przezroczystość wewnątrz i między poszczególnymi elementami HWND. Omówiono to również w temacie Omówienie regionów technologii.
Hostowanie zawartości WPF w oknie Microsoft Win32
Kluczem do hostowania WPF w oknie Win32 jest HwndSource klasa . Ta klasa opakowuje zawartość WPF w oknie Win32, dzięki czemu zawartość WPF może być włączona do interfejsu użytkownika jako okno podrzędne. Poniższe podejście łączy win32 i WPF w jednej aplikacji.
Zaimplementuj zawartość WPF (element główny zawartości) jako klasę zarządzaną. Zazwyczaj klasa dziedziczy z jednej z klas, które mogą zawierać wiele elementów podrzędnych i/lub używane jako element główny, taki jak DockPanel lub Page. W kolejnych krokach ta klasa jest określana jako klasa zawartości WPF, a wystąpienia klasy są określane jako obiekty zawartości WPF.
Zaimplementuj aplikację systemu Windows przy użyciu języka C++/interfejsu wiersza polecenia. Jeśli zaczynasz od istniejącej niezarządzanej aplikacji w języku C++, zwykle możesz włączyć możliwość wywoływania kodu zarządzanego, zmieniając ustawienia projektu, aby uwzględnić flagę kompilatora
/clr(pełny zakres elementów, które mogą być konieczne do obsługi kompilacji/clrnie został opisany w tym temacie).Ustaw model wątkowania na STA (Single Threaded Apartment). WPF używa tego modelu wątkowania.
Obsługuj powiadomienie WM_CREATE w procedurze okna.
W programie obsługi (lub funkcji wywoływanej przez program obsługi) wykonaj następujące czynności:
Utwórz nowy HwndSource obiekt z oknem nadrzędnym HWND jako jego
parentparametrem.Utwórz wystąpienie klasy zawartości WPF.
Przypisz odwołanie do obiektu zawartości WPF do HwndSource właściwości obiektu RootVisual .
Właściwość HwndSource obiektu Handle zawiera uchwyt okna (HWND). Aby uzyskać HWND do użycia w części niezarządzanej aplikacji, przekształć
Handle.ToPointer()na HWND.
Zaimplementuj klasę zarządzaną zawierającą pole statyczne zawierające odwołanie do obiektu zawartości WPF. Ta klasa umożliwia uzyskanie odwołania do obiektu zawartości WPF z kodu Win32, ale co ważniejsze zapobiega niezamierzonemu usunięciu HwndSource przez mechanizm zbierania śmieci.
Odbieranie powiadomień z obiektu zawartości WPF przez dołączenie programu obsługi do co najmniej jednego zdarzenia obiektu zawartości WPF.
Komunikowanie się z obiektem zawartości WPF przy użyciu odwołania przechowywanego w polu statycznym w celu ustawienia właściwości, metod wywołania itp.
Uwaga / Notatka
Możesz wykonać niektóre lub wszystkie definicje klasy zawartości WPF dla kroku 1 w języku XAML, korzystając z domyślnej klasy częściowej klasy zawartości, o ile utworzysz oddzielną bibliotekę i się do niej odwołasz. Chociaż zazwyczaj uwzględniasz obiekt Application jako część kompilacji kodu XAML do zestawu, w rzeczywistości nie używasz tego Application w ramach współdziałania. Zamiast tego, korzystasz z jednej lub kilku klas bazowych dla plików XAML, na które wskazuje aplikacja, i odwołujesz się do ich klas częściowych. Pozostała część procedury jest zasadniczo podobna do przedstawionej powyżej.
Każdy z tych kroków jest zilustrowany za pomocą kodu w temacie Przewodnik: hostowanie zawartości WPF w win32.
Hostowanie okna Microsoft Win32 w WPF
Kluczem do hostowania okna Win32 w innej zawartości WPF jest HwndHost klasa . Ta klasa opakowuje okno w elemecie WPF, który można dodać do drzewa elementów WPF. HwndHost Obsługuje również interfejsy API, które umożliwiają wykonywanie takich zadań, jak przetwarzanie komunikatów dla okna hostowanego. Podstawowa procedura to:
Utwórz drzewo elementów dla aplikacji WPF (może to być kod lub znacznik). Znajdź odpowiedni i dopuszczalny punkt w drzewie elementów, w którym HwndHost można dodać implementację jako element podrzędny. W pozostałej części tych kroków ten element jest określany jako element rezerwowania.
Wykorzystaj HwndHost do stworzenia obiektu, który przechowuje zawartość Win32.
W tej klasie hosta przesłoń metodę HwndHostBuildWindowCore. Zwróć wartość HWND okna hostowanego. Możesz chcieć opakowować rzeczywiste kontrolki jako okno podrzędne zwróconego okna; Zawijanie kontrolek w oknie hosta zapewnia prosty sposób odbierania powiadomień z kontrolek przez zawartość WPF. Ta technika pomaga rozwiązać niektóre problemy z systemem Win32 dotyczące obsługi komunikatów na granicy hostowanej kontrolki.
Zastąp HwndHost metody DestroyWindowCore i WndProc. Celem jest przeprowadzenie czyszczenia i usunięcie odwołań do hostowanej zawartości, szczególnie jeśli utworzyłeś odwołania do niezarządzanych obiektów.
W pliku za pomocą kodu utwórz wystąpienie klasy hostingu kontrolek i utwórz je jako element podrzędny elementu rezerwowania. Zazwyczaj należy użyć procedury obsługi zdarzeń, takiej jak Loaded, lub użyć konstruktora klasy częściowej. Można jednak również dodać zawartość międzyoperacyjną za pomocą zachowania środowiska uruchomieniowego.
Przetwarzanie wybranych komunikatów okna, takich jak powiadomienia sterujące. Istnieją dwa podejścia. Obie zapewniają identyczny dostęp do strumienia komunikatów, więc wybór jest w dużej mierze kwestią wygody programistycznej.
Zaimplementuj przetwarzanie komunikatów dla wszystkich komunikatów (nie tylko zamykanie HwndHost komunikatów) w zastąpieniu metody WndProc.
Umożliw hostowanie elementu WPF na przetwarzanie komunikatów poprzez obsługę zdarzenia MessageHook. To zdarzenie jest zgłaszane dla każdego komunikatu wysyłanego do procedury okna głównego hostowanego okna.
Nie można przetwarzać komunikatów z okien, które są poza procesem przy użyciu polecenia WndProc.
Komunikowanie się z hostowanym oknem za pomocą Platform Invoke do wywołania funkcji niezarządzanej
SendMessage.
Wykonanie tych kroków powoduje utworzenie aplikacji, która działa z danymi wejściowymi myszy. Możesz dodać obsługę tabulacji dla swojego hostowanego okna, implementując interfejs IKeyboardInputSink.
Każdy z tych kroków jest zilustrowany za pomocą kodu w temacie Przewodnik: hostowanie kontrolki Win32 w WPF.
Okna (Hwnds) wewnątrz WPF
Możesz traktować HwndHost jako specjalną kontrolkę. (Technicznie, HwndHost jest klasą pochodną FrameworkElement , a nie klasą pochodną Control , ale można ją uznać za kontrolkę na potrzeby współdziałania).) HwndHost tworzy abstrakcję bazowego charakteru win32 hostowanej zawartości, tak aby pozostała część zawartości WPF była innym obiektem przypominającym kontrolkę, który powinien renderować i przetwarzać dane wejściowe. HwndHost zazwyczaj zachowuje się jak każdy inny element WPF FrameworkElement, chociaż istnieją pewne istotne różnice dotyczące wyjścia (rysowanie i grafika) oraz wejścia (mysz i klawiatura) wynikające z ograniczeń, jakie mogą obsługiwać bazowe HWND.
Znaczące różnice w zachowaniu wyjściowym
FrameworkElement, która jest klasą HwndHost bazową, ma sporo właściwości, które sugerują zmiany w interfejsie użytkownika. Obejmują one właściwości, takie jak FrameworkElement.FlowDirection, które zmieniają układ elementów w tym elemecie jako element nadrzędny. Jednak większość tych właściwości nie jest mapowana na możliwe odpowiedniki Win32, nawet jeśli takie odpowiedniki mogą istnieć. Zbyt wiele z tych właściwości i ich znaczenia są zbyt specyficzne dla technologii renderowania, aby mapowania były praktyczne. W związku z tym ustawienie właściwości, takich jak FlowDirection na, HwndHost nie ma wpływu.
HwndHost nie można obracać, skalować, przesuwać ani w inny sposób modyfikować przy użyciu przekształcenia.
HwndHost nie wspiera właściwości Opacity (mieszanie alfa). Jeśli zawartość wewnątrz HwndHost wykonuje operacje System.Drawing, które zawierają informacje alfa, to samo w sobie nie jest naruszeniem, ale HwndHost jako całość obsługuje tylko przezroczystość = 1.0 (100%).
HwndHost pojawi się ponad innymi elementami WPF w tym samym głównym oknie. Menu ToolTip lub ContextMenu wygenerowane jest osobnym oknem najwyższego poziomu, dlatego będzie działać poprawnie z HwndHost.
HwndHost nie uwzględnia regionu przycinania elementu nadrzędnego UIElement. Jest to potencjalnie problem, jeśli próbujesz umieścić klasę HwndHost w regionie przewijania lub Canvas.
Istotne różnice w zachowaniu wejściowym
Ogólnie rzecz biorąc, podczas gdy urządzenia wejściowe są objęte zakresem w regionie hostowanego HwndHost systemu Win32, zdarzenia wejściowe przechodzą bezpośrednio do win32.
Gdy mysz znajduje się nad HwndHost, aplikacja nie odbiera zdarzeń myszy WPF, a wartość właściwości WPF IsMouseOver będzie równa
false.Chociaż obiekt HwndHost ma fokus klawiatury, aplikacja nie będzie otrzymywać zdarzeń klawiatury WPF, a wartość właściwości IsKeyboardFocusWithin WPF będzie równa
false.Gdy fokus znajduje się w obiekcie HwndHost i przemieszcza się do innej kontrolki w ramach HwndHost, aplikacja nie otrzyma zdarzeń WPF GotFocus ani LostFocus.
Powiązane właściwości i zdarzenia rysika są analogiczne i nie zgłaszają informacji, podczas gdy rysik jest nad HwndHost.
Tabbing, Mnemoniki i Klawisze skrótu
Interfejsy IKeyboardInputSink i IKeyboardInputSite umożliwiają tworzenie bezproblemowego środowiska klawiatury dla mieszanych aplikacji WPF i Win32:
Nawigacja między składnikami Win32 i WPF za pomocą tabulatora
Mnemonics i akceleratory, które działają zarówno wtedy, gdy fokus znajduje się w składniku Win32, jak i w składniku WPF.
Klasy HwndHost i HwndSource zapewniają implementacje IKeyboardInputSink, ale mogą nie obsługiwać wszystkich komunikatów wejściowych potrzebnych do bardziej zaawansowanych scenariuszy. Przesłoń właściwe metody, aby uzyskać pożądane zachowanie klawiatury.
Interfejsy zapewniają obsługę tylko tego, co dzieje się w przypadku przejścia między regionami WPF i Win32. W regionie Win32, zachowanie tabulacji jest całkowicie kontrolowane przez zaimplementowaną logikę Win32 dotyczącą tabulacji, jeśli istnieje.
Zobacz także
.NET Desktop feedback