HwndHost for Windows Form - Win32/WinForm互操作性

Nic*_*ick 19 c# c++ wpf interop winforms

我需要在Windows窗体控件中托管Win32窗口.我遇到了与WPF相同的问题,我通过使用HwndHost控件解决了这个问题.

我按照本教程:

演练:在WPF中托管Win32控件

Windows窗体中是否有任何等效控件?

我有一个Panel和它的Handle属性,我使用此句柄作为我的Direct2D渲染目标窗口的父级:

// Register the window class.
        WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };

        // Redraws the entire window if a movement or size adjustment changes the height 
        // or the width of the client area.
        wcex.style         = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc   = Core::WndProc;
        wcex.cbClsExtra    = 0;
        wcex.cbWndExtra    = sizeof(LONG_PTR);
        wcex.hInstance     = HINST_THISCOMPONENT;
        wcex.hbrBackground = nullptr;
        wcex.lpszMenuName  = nullptr;
        wcex.hCursor       = LoadCursor(nullptr, IDI_APPLICATION);
        wcex.lpszClassName = L"SVGCoreClassName";

        RegisterClassEx(&wcex);

hwnd = CreateWindow(
            L"SVGCoreClassName",        // class name
            L"",                        // window name
            WS_CHILD | WS_VISIBLE,      // style
            CW_USEDEFAULT,              // x
            CW_USEDEFAULT,              // y
            CW_USEDEFAULT,              // width
            CW_USEDEFAULT,              // height
            parent,                     // parent window
            nullptr,                    // window menu
            HINST_THISCOMPONENT,        // instance of the module to be associated with the window
            this);                      // pointer passed to the WM_CREATE message

...

hr = d2dFactory->CreateHwndRenderTarget(
        D2D1::RenderTargetProperties(),
        D2D1::HwndRenderTargetProperties(hwnd, size, D2D1_PRESENT_OPTIONS_IMMEDIATELY),
        &renderTarget);
Run Code Online (Sandbox Code Playgroud)

如果我使用HwndHostWPF 的父句柄,代码可以工作.但是如果我使用System.Windows.Forms.PanelHandle,它就不会呈现任何内容.

Han*_*ant 7

在Winforms中,您无需在WPF中创建有效的D2D1目标窗口.在WPF中这是必要的,因为控件本身不是窗口,并且没有Handle属性,即CreateHwndRenderTarget()需要的属性.

在Winforms中,Panel类已经是一个非常好的渲染目标,你可以使用它的Handle属性来告诉D2D1渲染的位置.你只需要告诉它停止自己绘画.在项目中添加一个新类并粘贴此代码:

using System;
using System.Windows.Forms;

class D2D1RenderTarget : Control {
    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        if (!this.DesignMode) {
            this.SetStyle(ControlStyles.UserPaint, false);
            // Initialize D2D1 here, use this.Handle
            //...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编译.将新控件拖放到表单上,替换现有面板.