Last active
January 23, 2024 17:13
-
-
Save itsho/8b0e761d9114e27c8570fbf95465bbfc to your computer and use it in GitHub Desktop.
Hosting an app inside a WPF app (System.Windows.Interop)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
using System.Windows.Interop; | |
namespace HostingAppTest | |
{ | |
// based on https://stackoverflow.com/q/30186930/426315 | |
public class HwndHostEx : HwndHost | |
{ | |
private readonly IntPtr _childHandle; | |
public HwndHostEx(IntPtr handle) | |
{ | |
_childHandle = handle; | |
} | |
protected override HandleRef BuildWindowCore(HandleRef hwndParent) | |
{ | |
var childRef = new HandleRef(); | |
if (_childHandle != IntPtr.Zero) | |
{ | |
var childStyle = (IntPtr)(Win32API.WindowStyles.WS_CHILD | | |
// Child window should be have a thin-line border | |
Win32API.WindowStyles.WS_BORDER | | |
// the parent cannot draw over the child's area. this is needed to avoid refresh issues | |
Win32API.WindowStyles.WS_CLIPCHILDREN | | |
Win32API.WindowStyles.WS_VISIBLE | | |
Win32API.WindowStyles.WS_MAXIMIZE); | |
childRef = new HandleRef(this, _childHandle); | |
Win32API.SetWindowLongPtr(childRef, Win32API.GWL_STYLE, childStyle); | |
Win32API.SetParent(_childHandle, hwndParent.Handle); | |
} | |
return childRef; | |
} | |
protected override void DestroyWindowCore(HandleRef hwnd) | |
{ | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Diagnostics; | |
namespace HostingAppTest | |
{ | |
public class LoadingChildExample | |
{ | |
public void LoadChild() | |
{ | |
var procInfo = new ProcessStartInfo("calc.exe"); | |
var childProc = new Process(procInfo); | |
childProc.Start(); | |
var hostedChild = new HwndHostEx(childProc.MainWindowHandle); | |
// Any FrameworkElement that inherits from System.Windows.Controls.Decorator can host the child. | |
// No need to use WindowsFormsHost! | |
decoratorControl.Child = hostedChild; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
namespace HostingAppTest | |
{ | |
public class Win32API | |
{ | |
[DllImport("User32.dll")] | |
internal static extern IntPtr SetParent(IntPtr hwc, IntPtr hwp); | |
/// <summary> | |
/// This static method is required because legacy OSes do not support SetWindowLongPtr | |
/// </summary> | |
internal static IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, IntPtr dwNewLong) | |
{ | |
if (IntPtr.Size == 8) | |
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong); | |
else | |
return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32())); | |
} | |
[DllImport("user32.dll", EntryPoint = "SetWindowLong")] | |
private static extern int SetWindowLong32(HandleRef hWnd, int nIndex, int dwNewLong); | |
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")] | |
private static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, IntPtr dwNewLong); | |
[DllImport("user32.dll", EntryPoint = "GetWindowLong")] | |
private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex); | |
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")] | |
private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex); | |
/// <summary> | |
/// This static method is required because Win32 does not support GetWindowLongPtr directly | |
/// </summary> | |
internal static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex) | |
{ | |
if (IntPtr.Size == 8) | |
return GetWindowLongPtr64(hWnd, nIndex); | |
else | |
return GetWindowLongPtr32(hWnd, nIndex); | |
} | |
[DllImport("user32.dll")] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
internal static extern bool SetForegroundWindow(IntPtr hWnd); | |
[DllImport("user32.dll", SetLastError = true)] | |
internal static extern bool BringWindowToTop(IntPtr hWnd); | |
[DllImport("user32.dll", SetLastError = true)] | |
internal static extern bool BringWindowToTop(HandleRef hWnd); | |
internal const int GWL_STYLE = -16; | |
internal const int GWL_EXSTYLE = -20; | |
[Flags] | |
internal enum WindowStyles : uint | |
{ | |
WS_OVERLAPPED = 0x00000000, | |
WS_POPUP = 0x80000000, | |
WS_CHILD = 0x40000000, | |
WS_MINIMIZE = 0x20000000, | |
WS_VISIBLE = 0x10000000, | |
WS_DISABLED = 0x08000000, | |
WS_CLIPSIBLINGS = 0x04000000, | |
WS_CLIPCHILDREN = 0x02000000, | |
WS_MAXIMIZE = 0x01000000, | |
WS_BORDER = 0x00800000, | |
WS_DLGFRAME = 0x00400000, | |
WS_VSCROLL = 0x00200000, | |
WS_HSCROLL = 0x00100000, | |
WS_SYSMENU = 0x00080000, | |
WS_THICKFRAME = 0x00040000, | |
WS_GROUP = 0x00020000, | |
WS_TABSTOP = 0x00010000, | |
WS_MINIMIZEBOX = 0x00020000, | |
WS_MAXIMIZEBOX = 0x00010000, | |
WS_CAPTION = WS_BORDER | WS_DLGFRAME, | |
WS_TILED = WS_OVERLAPPED, | |
WS_ICONIC = WS_MINIMIZE, | |
WS_SIZEBOX = WS_THICKFRAME, | |
WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW, | |
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, | |
WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU, | |
WS_CHILDWINDOW = WS_CHILD, | |
//Extended Window Styles | |
WS_EX_DLGMODALFRAME = 0x00000001, | |
WS_EX_NOPARENTNOTIFY = 0x00000004, | |
WS_EX_TOPMOST = 0x00000008, | |
WS_EX_ACCEPTFILES = 0x00000010, | |
WS_EX_TRANSPARENT = 0x00000020, | |
//#if(WINVER >= 0x0400) | |
WS_EX_MDICHILD = 0x00000040, | |
WS_EX_TOOLWINDOW = 0x00000080, | |
WS_EX_WINDOWEDGE = 0x00000100, | |
WS_EX_CLIENTEDGE = 0x00000200, | |
WS_EX_CONTEXTHELP = 0x00000400, | |
WS_EX_RIGHT = 0x00001000, | |
WS_EX_LEFT = 0x00000000, | |
WS_EX_RTLREADING = 0x00002000, | |
WS_EX_LTRREADING = 0x00000000, | |
WS_EX_LEFTSCROLLBAR = 0x00004000, | |
WS_EX_RIGHTSCROLLBAR = 0x00000000, | |
WS_EX_CONTROLPARENT = 0x00010000, | |
WS_EX_STATICEDGE = 0x00020000, | |
WS_EX_APPWINDOW = 0x00040000, | |
WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE), | |
WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST), | |
//#endif /* WINVER >= 0x0400 */ | |
//#if(WIN32WINNT >= 0x0500) | |
WS_EX_LAYERED = 0x00080000, | |
//#endif /* WIN32WINNT >= 0x0500 */ | |
//#if(WINVER >= 0x0500) | |
WS_EX_NOINHERITLAYOUT = 0x00100000, // Disable inheritence of mirroring by children | |
WS_EX_LAYOUTRTL = 0x00400000, // Right to left mirroring | |
//#endif /* WINVER >= 0x0500 */ | |
//#if(WIN32WINNT >= 0x0500) | |
WS_EX_COMPOSITED = 0x02000000, | |
WS_EX_NOACTIVATE = 0x08000000 | |
//#endif /* WIN32WINNT >= 0x0500 */ | |
} | |
} | |
} |
Probably because Explorer.exe is the whole shell. And you can't host it.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
any idea why this is working fine for notepad and winver, but explorer.exe shows in a separate window?