Подтвердить что ты не робот

HwndHost для Windows Form - совместимость с Win32/WinForm

Мне нужно разместить окно Win32 в элементе управления Windows Form. У меня была такая же проблема с WPF, и я решил эту проблему с помощью элемента управления HwndHost.

Я следовал этому руководству:

Пошаговое руководство. Хостинг Win32-элемента управления в WPF

Есть ли эквивалентный контроль в Windows Form?

У меня есть свойство 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.

4b9b3361

Ответ 1

То, что вам нужно было сделать в 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
            //...
        }
    }
}

Compile. Отбросьте новый элемент управления на свою форму, заменив существующую панель.

Ответ 2

Звучит как приложение MDI. Что-то вроде этого?

[DllImport("user32.dll")]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

[DllImport("user32.dll")]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

Form f = new Form();
Button b1 = new Button { Text = "Notepad" };
b1.Click += delegate {
    using (var p = Process.Start("notepad.exe")) {
        p.WaitForInputIdle();
        SetParent(p.MainWindowHandle, f.Handle);
        MoveWindow(p.MainWindowHandle, 50, 50, 300, 300, true);
    }
};
f.Controls.Add(b1);
Application.Run(f);