WPF e a interoperação de Win32

Este tópico fornece uma visão geral de como interoperar WPF e Win32 código. Windows Presentation Foundation (WPF) provides a rich environment for creating applications. However, when you have a substantial investment in Win32 code, it might be more effective to reuse some of that code.

Este tópico contém as seguintes seções.

  • WPF and Win32 Interoperation Basics
  • WPF Interoperation Projects
  • How WPF Uses Hwnds
  • Hosting WPF Content in a Microsoft Win32 Window
  • Hosting a Microsoft Win32 Window in WPF
  • Tabbing, Mnemonics, and Accelerators
  • Tópicos relacionados

WPF and Win32 Interoperation Basics

There are two basic techniques for interoperation between WPF and Win32 code.

  • Host WPF conteúdo em um Win32 janela. With this technique, you can use the advanced graphics capabilities of WPF within the framework of a standard Win32 window and application.

  • Host um Win32 janela no WPF conteúdo. Com essa técnica, você pode usar um personalizado existente Win32 o controle no contexto de outros WPF conteúdo e passar dados entre os limites.

Each of these techniques is conceptually introduced in this topic. Para uma ilustração mais orientado por código de hospedagem WPF em Win32, consulte Demonstra Passo a passo: Hospedagem de conteúdo do WPF no Win32. Para uma ilustração mais orientado por código de hospedagem Win32 em WPF, consulte Demonstra Passo a passo: Hospedando um controle do Win32 no WPF.

WPF Interoperation Projects

WPF APIs are managed code, but most existing Win32 programs are written in unmanaged C++. You cannot call WPF APIs from a true unmanaged program. No entanto, usando o /clr a opção com o Microsoft Visual C++ compilador, você pode criar um programa gerenciado misto onde você pode misturar perfeitamente gerenciado e API chamadas.

One project-level complication is that you cannot compile Extensible Application Markup Language (XAML) files into a C++ project. There are several project division techniques to compensate for this.

  • Criar um C# DLL que contém todos os seus XAML páginas como um assembly compilado e, então, o C++ executável incluem que DLL como referência.

  • Criar um C# executável para o WPF de conteúdo e a referência a um C++ DLL que contém o Win32 conteúdo.

  • Use Load para carregar qualquer XAML em tempo de execução, em vez de compilação de seu XAML.

  • Do not use XAML at all, and write all your WPF in code, building up the element tree from Application.

Use whatever approach works best for you.

Observação

Se você não tiver usado C++/CLI antes, você poderá notar algumas "new" palavras-chave como gcnew e nullptr nos exemplos de código de interoperação. Essas palavras-chave substitui a sintaxe mais antiga do sublinhado duplo (__gc) e fornecer uma sintaxe mais natural para código gerenciado em C++.Para saber mais sobre o C++/CLI recursos gerenciados, consulte Language Features for Targeting the CLR e Hello, C + + / CLI.

How WPF Uses Hwnds

To make the most of WPF "HWND interop", you need to understand how WPF uses HWNDs. For any HWND, you cannot mix WPF rendering with DirectX rendering or GDI / GDI+ rendering. This has a number of implications. Primarily, in order to mix these rendering models at all, you must create an interoperation solution, and use designated segments of interoperation for each rendering model that you choose to use. Also, the rendering behavior creates an "airspace" restriction for what your interoperation solution can accomplish. The "airspace" concept is explained in greater detail in the topic Visão geral de regiões de tecnologia.

Todos os WPF elementos na tela em última análise, respaldados por um HWND. Quando você cria um WPF Window, WPF cria um HWND de nível superior e usa um HwndSource para colocar o Window e seus WPF conteúdo dentro do HWND. O restante da sua WPF o conteúdo no aplicativo compartilhamentos que HWND singular. An exception is menus, combo box drop downs, and other pop-ups. Esses elementos criam sua própria janela de nível superior, razão pela qual um WPF menu potencialmente pode ir além da borda da janela HWND que contém o proprietário. Quando você usa HwndHost para colocar um HWND dentro de WPF, WPF informa Win32 como posicionar o novo filho HWND relativos a para o WPF Window HWND.

A related concept to HWND is transparency within and between each HWND. This is also discussed in the topic Visão geral de regiões de tecnologia.

Hosting WPF Content in a Microsoft Win32 Window

The key to hosting a WPF on a Win32 window is the HwndSource class. This class wraps the WPF content in a Win32 window, so that the WPF content can be incorporated into your user interface (UI) as a child window. The following approach combines the Win32 and WPF in a single application.

  1. Implementar o WPF o conteúdo (o elemento raiz do conteúdo) como uma classe de gerenciados. Typically, the class inherits from one of the classes that can contain multiple child elements and/or used as a root element, such as DockPanel or Page. Nas etapas subseqüentes, essa classe é conhecida como o WPF classe de conteúdo e as instâncias da classe são chamados de WPF objetos de conteúdo.

  2. Implement a Win32 application with C++/CLI. Se você estiver iniciando com um existente não gerenciado C++ aplicativo, você pode normalmente habilitá-lo chamar código gerenciado, alterando suas configurações de projeto para incluir o /clr Sinalizador do compilador (o escopo completo do que pode ser necessário para dar suporte a /clr compilação não está descrita neste tópico).

  3. Defina o modelo de segmentação para compartimento de segmentação única (STA). WPFusa o modelo de threading.

  4. Handle the WM_CREATE notification in your window procedure.

  5. Within the handler (or a function that the handler calls), do the following:

    1. Create a new HwndSource object with the parent window HWND as its parent parameter.

    2. Criar uma instância do seu WPF classe de conteúdo.

    3. Atribua uma referência para o WPF o objeto de conteúdo para o HwndSource objeto RootVisual propriedade.

    4. The HwndSource object Handle property contains the window handle (HWND). To get an HWND that you can use in the unmanaged part of your application, cast Handle.ToPointer() to an HWND.

  6. Implementar uma classe gerenciada que contém um campo estático que mantém uma referência para seu WPF objeto de conteúdo. Essa classe permite que você obtenha uma referência para o WPF o objeto de conteúdo de sua Win32 código, mas o mais importante é que ele impede que seu HwndSource sejam inadvertidamente coletados pelo lixo.

  7. Receber notificações da WPF o objeto de conteúdo, anexando um manipulador para um ou mais o WPF eventos de objeto de conteúdo.

  8. Se comunicar com o WPF o objeto de conteúdo usando a referência que é armazenado no campo para definir propriedades, chamar métodos estático, etc.

Observação

Você pode fazer algumas ou todas as WPF definição de classe de conteúdo para uma etapa em XAML usando a classe parcial do padrão da classe de conteúdo, se você produzir um assembly separado e, em seguida, fazer referência a ela. Embora você normalmente incluem um Application objeto como parte da compilação do XAML em um assembly, você não acaba usando que Application como parte de interoperação, você simplesmente usar um ou mais das classes de raiz para XAML arquivos chamados pelo aplicativo e referenciar suas classes parciais.The remainder of the procedure is essentially similar to that outlined above.

Each of these steps is illustrated through code in the topic Demonstra Passo a passo: Hospedagem de conteúdo do WPF no Win32.

Hosting a Microsoft Win32 Window in WPF

A chave para hospedar um Win32 janela dentro dos outros WPF o conteúdo é o HwndHost classe. Essa classe encapsula a janela em um WPF elemento que pode ser adicionado a uma WPF árvore de elemento. HwndHosttambém oferece suporte a APIs que permitem que você realize tarefas como processar mensagens para a janela hospedada. The basic procedure is:

  1. Criar uma árvore de elemento para um WPF aplicativo (pode ser por meio de código ou marcação). Find an appropriate and permissible point in the element tree where the HwndHost implementation can be added as a child element. In the remainder of these steps, this element is referred to as the reserving element.

  2. Derive from HwndHost to create an object that holds your Win32 content.

  3. In that host class, override the HwndHost method BuildWindowCore. Return the HWND of the hosted window. Talvez você queira ajustar o controle real como uma janela filho da janela retornada; os controles de quebra em uma janela de host fornece uma maneira simples para seu WPF o conteúdo para receber notificações de controles. This technique helps correct for some Win32 issues regarding message handling at the hosted control boundary.

  4. Override the HwndHost methods DestroyWindowCore and WndProc. The intention here is to process cleanup and remove references to the hosted content, particularly if you created references to unmanaged objects.

  5. In your code-behind file, create an instance of the control hosting class and make it a child of the reserving element. Typically you would use an event handler such as Loaded, or use the partial class constructor. But you could also add the interoperation content through a runtime behavior.

  6. Process selected window messages, such as control notifications. There are two approaches. Both provide identical access to the message stream, so your choice is largely a matter of programming convenience.

    • Implement message processing for all messages (not just shutdown messages) in your override of the HwndHost method WndProc.

    • Have the hosting WPF element process the messages by handling the MessageHook event. This event is raised for every message that is sent to the main window procedure of the hosted window.

    • You cannot process messages from windows that are out of process using WndProc.

  7. Communicate with the hosted window by using platform invoke to call the unmanaged SendMessage function.

Following these steps creates an application that works with mouse input. Você pode adicionar o suporte de tabulação para a sua janela hospedada, Implementando o IKeyboardInputSink interface.

Each of these steps is illustrated through code in the topic Demonstra Passo a passo: Hospedando um controle do Win32 no WPF.

Hwnds Inside WPF

You can think of HwndHost as a special control. (Tecnicamente, HwndHost é um FrameworkElement derivada de classe, não um Control classe derivada, mas pode ser considerado um controle para fins de interoperação.) HwndHost abstrai base Win32 a natureza do conteúdo hospedado que o restante do WPF considera o conteúdo hospedado ser outro objeto semelhante ao controle, que deve processar e processo de entrada. HwndHostgeralmente se comporta como qualquer outra WPF FrameworkElement, embora algumas diferenças importantes ao redor de saída (desenho e elementos gráficos) e entrada (mouse e teclado) com base nas limitações dos quais os HWNDs subjacentes pode suporte.

Notable Differences in Output Behavior

  • FrameworkElement, which is the HwndHost base class, has quite a few properties that imply changes to the UI. These include properties such as FrameworkElement.FlowDirection, which changes the layout of elements within that element as a parent. No entanto, a maioria dessas propriedades não é mapeadas para o possível Win32 equivalentes, mesmo se tais equivalentes podem existir. Too many of these properties and their meanings are too rendering-technology specific for mappings to be practical. Portanto, a definição de propriedades, como FlowDirection em HwndHost tem nenhum efeito.

  • HwndHost cannot be rotated, scaled, skewed, or otherwise affected by a Transform.

  • HwndHost does not support the Opacity property (alpha blending). If content inside the HwndHost performs System.Drawing operations that include alpha information, that is itself not a violation, but the HwndHost as a whole only supports Opacity = 1.0 (100%).

  • HwndHost will appear on top of other WPF elements in the same top-level window. However, a ToolTip or ContextMenu generated menu is a separate top-level window, and so will behave correctly with HwndHost.

  • HwndHost does not respect the clipping region of its parent UIElement. This is potentially an issue if you attempt to put an HwndHost class inside a scrolling region or Canvas.

Notable Differences in Input Behavior

  • In general, while input devices are scoped within the HwndHost hosted Win32 region, input events go directly to Win32.

  • Enquanto o mouse está sobre o HwndHost, seu aplicativo não recebe WPF eventos de mouse e o valor da WPF propriedade IsMouseOver será false.

  • Enquanto o HwndHost tem o foco do teclado, seu aplicativo não receberá WPF eventos e o valor do teclado a WPF propriedade IsKeyboardFocusWithin será false.

  • Quando o foco está dentro do HwndHost e alterações de outro controle dentro a HwndHost, seu aplicativo não receberá o WPF eventos GotFocus ou LostFocus.

  • Related stylus properties and events are analogous, and do not report information while the stylus is over HwndHost.

Tabbing, Mnemonics, and Accelerators

The IKeyboardInputSink and IKeyboardInputSite interfaces allow you to create a seamless keyboard experience for mixed WPF and Win32 applications:

  • Navegação por TAB entre Win32 e WPF componentes

  • Mnemonics and accelerators that work both when focus is within a Win32 component and when it is within a WPF component.

The HwndHost and HwndSource classes both provide implementations of IKeyboardInputSink, but they may not handle all the input messages that you want for more advanced scenarios. Override the appropriate methods to get the keyboard behavior you want.

The interfaces only provide support for what happens on the transition between the WPF and Win32 regions. Dentro do Win32 região, comportamento de tabulação é totalmente controlado pelo Win32 implementado lógica para tabulações, se houver.

Consulte também

Referência

HwndHost

HwndSource

System.Windows.Interop

Conceitos

Demonstra Passo a passo: Hospedando um controle do Win32 no WPF

Demonstra Passo a passo: Hospedagem de conteúdo do WPF no Win32