zoukankan      html  css  js  c++  java
  • 完美实现Wpf嵌套外部exe

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Controls;
    using System.Windows.Interop;
    
    namespace WpfDisplayExe
    {
        class EmbeddedApp : HwndHost, IKeyboardInputSink
        {
            [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);
            [DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true, CharSet = CharSet.Auto)]
            private static extern int SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam); //对外部软件窗口发送一些消息(如 窗口最大化、最小化等)
            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 const int WM_SYSCOMMAND = 0x0112;
            private const int SC_CLOSE = 0xF060;
            private const int SC_MINIMIZE = 0xF020;
            private const int SC_MAXIMIZE = 0xF030;
            private const uint WM_LBUTTONDOWN = 0x0201;
            private const uint WM_LBUTTONUP = 0x0202;
            private const int BM_CLICK = 0xF5;
    
            private Border WndHoster;
            private double screenW, screenH;
            private System.Diagnostics.Process appProc;
            private uint oldStyle;
            public 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();
                hwndHost = FindTheWindow();
                SendMessage(hwndHost, WM_SYSCOMMAND, SC_MINIMIZE, 0);
                //}   
                // 嵌入在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;
                newStyle &= ~WS_BORDER;
                SetWindowLong(hwndHost, GWL_STYLE, newStyle);
                //将窗口居中,实际上是将窗口的容器居中   
                RePosWindow(WndHoster, WndHoster.Width, WndHoster.Height);
    
                //将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);
                appProc.Kill();
                appProc.Close();
            }
    
            [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);
                Console.WriteLine(str.ToString());
                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);
            }
        }
    }

    调用的话,需要是在windows任务管理器中查看它的名字,上面的类你可以稍作修改。DestroyWindowCore是你窗口推出的时候。

    public MainWindow()
            {
                InitializeComponent();
                //加载.exe文件
                
               String path = @"D:VLCvlc.exe"; //VusionDTI  ImAgenGine_MRDP
                EmbeddedApp ea = new EmbeddedApp(asd, 100, 100, path, "VLC media player");
                asd.Child = ea;
            }
  • 相关阅读:
    mysql索引数据结构
    29. 使用参数化编写自动化测试用例
    28. Python编写自动化测试用例
    27. Unittest单元测试框架的介绍与使用
    26. 什么是单元测试
    25. Postman的使用
    24. 接口测试的意义
    23. requests安装与使用
    22. 如何编写接口文档
    21. Blog接口开发
  • 原文地址:https://www.cnblogs.com/ZaraNet/p/13717359.html
Copyright © 2011-2022 走看看