在WPF程序中嵌入Win32程序。

 

    原理请看, http://msdn.microsoft.com/zh-cn/library/ms752055(VS.90).aspx
小结
    重写BuildWindowCore,返回一个Win32的窗口指针,并将Win32窗口的父窗口设置成BuildWindowCore传入的窗口句柄。
    需要注意的是Win32窗口Style增加WS_STYLE属性。
public class EmbeddedApp : HwndHost { [DllImport("user32.dll")] private static extern int SetParent(IntPtr hWndChild, IntPtr hWndParent); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern uint SetWindowLong(IntPtr hwnd, int nIndex, uint newLong); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern uint GetWindowLong(IntPtr hwnd, int nIndex); [DllImport("user32.dll")] private static extern int EnumWindows(CallBackPtr callPtr, ref WindowInfo WndInfoRef); [DllImport("User32.dll")] static extern int GetWindowText(IntPtr handle, StringBuilder text, int MaxLen); [DllImport("user32.dll")] public static extern int GetWindowRect(IntPtr hwnd, ref RECT rc); internal const int GWL_WNDPROC = (-4), GWL_HINSTANCE = (-6), GWL_HWNDPARENT = (-8), GWL_STYLE = (-16), GWL_EXSTYLE = (-20), GWL_USERDATA = (-21), GWL_ID = (-12); internal const uint WS_CHILD = 0x40000000, WS_VISIBLE = 0x10000000, LBS_NOTIFY = 0x00000001, HOST_ID = 0x00000002, LISTBOX_ID = 0x00000001, WS_VSCROLL = 0x00200000, WS_BORDER = 0x00800000, WS_POPUP = 0x80000000; private const int HWND_TOP = 0x0; private const int WM_COMMAND = 0x0112; private const int WM_QT_PAINT = 0xC2DC; private const int WM_PAINT = 0x000F; private const int WM_SIZE = 0x0005; private const int SWP_FRAMECHANGED = 0x0020; private Border WndHoster; private double screenW, screenH; private System.Diagnostics.Process appProc; private uint oldStyle; private IntPtr hwndHost; private String appPath; public EmbeddedApp(Border b, double sW, double sH, String p, String f) { WndHoster = b; screenH = sH; screenW = sW; appPath = p; WinInfo = new WindowInfo(); WinInfo.winTitle = f; } protected override HandleRef BuildWindowCore(HandleRef hwndParent) { hwndHost = FindTheWindow(); if (hwndHost == null) { appProc = new System.Diagnostics.Process(); appProc.StartInfo.FileName = appPath; appProc.Start(); Thread.Sleep(1000); hwndHost = FindTheWindow(); } // 嵌入在HwnHost中的窗口必须要 设置为WS_CHILD风格 oldStyle = GetWindowLong(hwndHost, GWL_STYLE); uint newStyle = oldStyle; //WS_CHILD和WS_POPUP不能同时存在。有些Win32窗口,比如QQ的窗口,有WS_POPUP属性,这样嵌入的时候会导致程序错误 newStyle |= WS_CHILD; newStyle &= ~WS_POPUP; SetWindowLong(hwndHost, GWL_STYLE, newStyle); //将窗口居中,实际上是将窗口的容器居中 RePosWindow(WndHoster, screenW, screenH); //将netterm的父窗口设置为HwndHost SetParent(hwndHost, hwndParent.Handle); return new HandleRef(this, hwndHost); } protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd) { SetWindowLong(hwndHost, GWL_STYLE, oldStyle); SetParent(hwndHost, (IntPtr)0); } [StructLayout(LayoutKind.Sequential)] public struct RECT { public int left; public int top; public int right; public int bottom; } [StructLayout(LayoutKind.Sequential)] public struct WindowInfo { public String winTitle; public RECT r; public IntPtr hwnd; } public delegate bool CallBackPtr(IntPtr hwnd, ref WindowInfo WndInfoRef); private static CallBackPtr callBackPtr; private WindowInfo WinInfo; public static bool CallBackProc(IntPtr hwnd, ref WindowInfo WndInfoRef) { StringBuilder str = new StringBuilder(512); GetWindowText(hwnd, str, str.Capacity); if (str.ToString().IndexOf(WndInfoRef.winTitle, 0) >= 0) { WndInfoRef.hwnd = hwnd; GetWindowRect(hwnd, ref (WndInfoRef.r)); } return true; } public IntPtr FindTheWindow() { callBackPtr = new CallBackPtr(CallBackProc); EnumWindows(callBackPtr, ref WinInfo); return WinInfo.hwnd; } public void RePosWindow(Border b, double screenW, double screenH) { double width = WinInfo.r.right - WinInfo.r.left; double height = WinInfo.r.bottom - WinInfo.r.top; double left = (screenW - width) / 2; double right = (screenW - width) / 2; double top = (screenH - height) / 2; double bottom = (screenH - height) / 2; b.Margin = new Thickness(left, top, right, bottom); } } 使用示例: 在XAML中增加一个Border元素WndHost。然后在WPF程序的构造函数中添加如下代码 ================================ this.InitializeComponent(); String path; RegistryKey hkml = Registry.LocalMachine; RegistryKey softWare = hkml.OpenSubKey("SOFTWARE"); RegistryKey TX = softWare.OpenSubKey("Tencent"); RegistryKey QQ2009 = TX.OpenSubKey("QQ2009"); path = QQ2009.GetValue("install").ToString() + "//bin//QQ.exe"; EmbeddedApp ea = new EmbeddedApp(WndHost, this.Width, this.Height, path,"QQ2010"); WndHost.Child = ea; EmbeddedApp ea = new EmbeddedApp(WndHost, this.Width, this.Height, path,"QQ2010"); WndHost.Child = ea;

你可能感兴趣的:(在WPF程序中嵌入Win32程序。)