c# - 适用于 Windows 窗体的 HwndHost - Win32/WinForm 互操作性

标签 c# c++ wpf winforms interop

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

我遵循了这个教程:

Walkthrough: Hosting a Win32 Control in WPF

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);

如果我将 HwndHost 父句柄与 WPF 一起使用,则代码有效。但如果我使用 System.Windows.Forms.Panel 句柄,它不会呈现任何内容。

最佳答案

您必须在 WPF 中执行的创建有效 D2D1 目标窗口的操作在 Winforms 中是不必要的。在 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
            //...
        }
    }
}

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

关于c# - 适用于 Windows 窗体的 HwndHost - Win32/WinForm 互操作性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29679667/

相关文章:

c++ - 可以在不取消引用的情况下增加指针仍然是段错误或具有其他(未)定义的肮脏吗?

c# - 我可以使用 WCF 接口(interface)作为 MVVM 模型吗?

c# - 在 MVVM WPF 应用程序中处理导航

c# - WPF 无法从 MouseDown 事件中获取触摸位置

c# - Convert.ToBoolean ("1") 在 C# 中抛出 System.Format 异常

C# 打印二维数组周围的边框

c++ - 将参数函数分配给类成员

c# - XAML WPF 数据网格 : reduce columns width to fit its content while scrolling except one

在 C++/CLI 中使用时未创建 C# 应用程序 log4net 日志文件

c# - RichTextBox 中的 Border.IsMouseOver(RichTextBox 中的 InlineUIContainer 不响应事件/触发器)