■ HwndHost 클래스를 사용해 WPF 윈도우 내부에서 메모장 윈도우를 호스팅하는 방법을 보여준다.
▶ WindowLongFlag.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
namespace TestProject { /// <summary> /// 윈도우 LONG 플래그 /// </summary> public enum WindowLongFlag : int { /// <summary> /// GWL_EXSTYLE /// </summary> GWL_EXSTYLE = -20, /// <summary> /// GWLP_HINSTANCE /// </summary> GWLP_HINSTANCE = -6, /// <summary> /// GWLP_HWNDPARENT /// </summary> GWLP_HWNDPARENT = -8, /// <summary> /// GWL_ID /// </summary> GWL_ID = -12, /// <summary> /// GWL_STYLE /// </summary> GWL_STYLE = -16, /// <summary> /// GWL_USERDATA /// </summary> GWL_USERDATA = -21, /// <summary> /// GWL_WNDPROC /// </summary> GWL_WNDPROC = -4, /// <summary> /// DWLP_USER /// </summary> DWLP_USER = 0x8, /// <summary> /// DWLP_MSGRESULT /// </summary> DWLP_MSGRESULT = 0x0, /// <summary> /// DWLP_DLGPROC /// </summary> DWLP_DLGPROC = 0x4 } } |
▶ CustomHwndHost.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
using System; using System.Runtime.InteropServices; using System.Windows.Interop; namespace TestProject { /// <summary> /// 커스텀 윈도우 핸들 호스트 /// </summary> public class CustomHwndHost : HwndHost { //////////////////////////////////////////////////////////////////////////////////////////////////// Import ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 윈도우 LONG 설정하기 - SetWindowLong(windowHandle, flag, value) /// <summary> /// 윈도우 LONG 설정하기 /// </summary> /// <param name="windowHandle">윈도우 핸들</param> /// <param name="flag">플래그</param> /// <param name="value">값</param> /// <returns>처리 결과</returns> [DllImport("user32")] private static extern int SetWindowLong(IntPtr windowHandle, WindowLongFlag flag, int value); #endregion #region 부모 설정하기 - SetParent(childWindowHandle, parentWindowHandle) /// <summary> /// 부모 설정하기 /// </summary> /// <param name="childWindowHandle">자식 윈도우 핸들</param> /// <param name="parentWindowHandle">부모 윈도우 핸들</param> /// <returns>이전 부모 윈도우 핸들</returns> [DllImport("user32")] private static extern IntPtr SetParent(IntPtr childWindowHandle, IntPtr parentWindowHandle); #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// WS_CHILD /// </summary> private const int WS_CHILD = 0x40000000; /// <summary> /// 자식 윈도우 핸들 /// </summary> private IntPtr childWindowHandle = IntPtr.Zero; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - CustomHwndHost(childWindowHandle) /// <summary> /// 생성자 /// </summary> /// <param name="childWindowHandle">자식 윈도우 핸들</param> public CustomHwndHost(IntPtr childWindowHandle) { this.childWindowHandle = childWindowHandle; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 윈도우 만들기 (코어) - BuildWindowCore(parentWindowHandleRef) /// <summary> /// 윈도우 만들기 (코어) /// </summary> /// <param name="parentWindowHandleRef">부모 윈도우 핸들 참조</param> /// <returns>자식 윈도우 핸들 참조</returns> protected override HandleRef BuildWindowCore(HandleRef parentWindowHandleRef) { HandleRef childWIndowHandleRef = new HandleRef(); if(this.childWindowHandle != IntPtr.Zero) { SetWindowLong(this.childWindowHandle, WindowLongFlag.GWL_STYLE, WS_CHILD); SetParent(this.childWindowHandle, parentWindowHandleRef.Handle); childWIndowHandleRef = new HandleRef(this, this.childWindowHandle); } return childWIndowHandleRef; } #endregion #region 윈도우 제거하기 (코어) - DestroyWindowCore(windowHandleRef) /// <summary> /// 윈도우 제거하기 (코어) /// </summary> /// <param name="windowHandleRef">윈도우 핸들 참조</param> protected override void DestroyWindowCore(HandleRef windowHandleRef) { } #endregion } } |
▶ MainWindow.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<Window x:Class="TestProject.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="800" Height="600" Title="HwndHost 클래스 : WPF 윈도우 내부에서 메모장 윈도우 호스팅하기" FontFamily="나눔고딕코딩" FontSize="16"> <Grid Margin="10" Background="Transparent" UseLayoutRounding="True" SnapsToDevicePixels="True"> <Border Name="border" BorderThickness="1" BorderBrush="Black" /> </Grid> </Window> |
▶ MainWindow.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
using System.Diagnostics; using System.Windows; namespace TestProject { /// <summary> /// 메인 윈도우 /// </summary> public partial class MainWindow : Window { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainWindow() /// <summary> /// 생성자 /// </summary> public MainWindow() { InitializeComponent(); #region 노트패드 프로세스를 생성한다. Process process = new Process(); process.StartInfo.FileName = "notepad.exe"; process.StartInfo.Arguments = null; process.Start(); process.WaitForInputIdle(100); #endregion CustomHwndHost host = new CustomHwndHost(process.MainWindowHandle); this.border.Child = host; } #endregion } } |