c# c++ wpf winforms interop

c# - HwndHost para Windows Form-Interoperabilidad Win32/WinForm



c++ wpf (2)

Necesito alojar una ventana de Win32 en un control de Windows Form. Tuve el mismo problema con WPF y resolví este problema utilizando el control HwndHost .

Seguí este tutorial:

Tutorial: Alojamiento de un control de Win32 en WPF

¿Hay algún control equivalente en Windows Form?

Tengo un Panel y su propiedad Handle , uso este manejador como padre de mi ventana de destino de procesamiento 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);

El código funciona si uso el HwndHost principal de HwndHost con WPF. Pero no muestra nada si uso System.Windows.Forms.Panel Handle.


Lo que tuvo que hacer en WPF para crear una ventana de destino D2D1 válida no es necesario en Winforms. Era necesario en WPF porque los controles no son ventanas en sí mismos y no tienen una propiedad Handle, la que necesita CreateHwndRenderTarget ().

En Winforms, la clase Panel ya es un objetivo de renderizado perfectamente bueno, puede usar su propiedad Handle para decirle a D2D1 dónde debe renderizar. Solo hay que decirle que deje de pintarse. Agrega una nueva clase a tu proyecto y pega este código:

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 //... } } }

Compilar. Coloque el nuevo control en su formulario, reemplazando el panel existente.


Suena como una aplicación MDI. ¿Algo como esto?

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