2020-09-23

完美实现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:\VLC\vlc.exe"; //VusionDTI ImAgenGine_MRDP   EmbeddedApp ea = new EmbeddedApp(asd, 100, 100, path, "VLC media player");   asd.Child = ea;  }

 

原文转载:http://www.shaoqun.com/a/477559.html

cicpa:https://www.ikjzd.com/w/1375

执御:https://www.ikjzd.com/w/717.html

extra:https://www.ikjzd.com/w/1736


usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Runtime.InteropServices;usingSystem.Text;usingSystem.Threading;usingSystem.Threading.Tasks;usingSystem.Windows.Controls;usingSy
asinseed:https://www.ikjzd.com/w/533
识货:https://www.ikjzd.com/w/1745
多国海关与中国联网,严打低价报关行为!:https://www.ikjzd.com/home/100349
亚马逊英国呼吁所有卖家在3月5日前提供VAT号:https://www.ikjzd.com/home/261
贸易公司常见的4种"猪队友"工厂,如何避开?:https://www.ikjzd.com/home/109517

No comments:

Post a Comment