WindowManager.cs 8.5 KB
using Common;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TheMachine
{
    public class WindowManager
    {
        public static List<WindInfo> windInfos = new List<WindInfo>();
        static string baseDir = Application.StartupPath + @"\Modules\";
        public static void Start()
        {
            foreach (var item in windInfos)
            {
                try
                {
                    if (ProcessUtil.IsRun(item.Name))
                    {
                        ProcessUtil.CloseProcess(item.Name);
                        Thread.Sleep(2000);
                    }
                    item.ProcessInfo = ProcessUtil.StartProcess(item.Name, baseDir + $"{item.Name}\\", 60000);
                }
                catch (Exception ex)
                {
                    LogUtil.error($"程序{item.Name}启动失败", ex);
                }
            }
        }
        public static void Show()
        {
            foreach (var item in windInfos)
                item.WindowHandle = WindowUtil.PutIntoForm(item.Parent, item.Name);
        }
        public static void Hide()
        {
            foreach (var item in windInfos)
            {
                if (item.WindowHandle != IntPtr.Zero)
                {
                    item.WindowHandle = IntPtr.Zero;
                    WindowUtil.RemoveFromForm(item.Name);
                }

            }
        }
    }
    public class WindInfo
    {
        public string Name { get; set; }
        public IntPtr WindowHandle { get; set; }
        public Panel Parent { get; set; }
        public Process ProcessInfo { get; set; }

        public const string IPCamera = "IPCamera";
    }
    public class WindowUtil
    {
        public const int WM_CLOSE = 0x0010;
        static List<Process> SubProcesses = new List<Process>();
        public static Process OpenExe(Panel panel, string appName, string titleName, string baseDir = @".\")
        {
            if (appName == null || appName == string.Empty) return null;
            Process process = null;
            IntPtr appWin = IntPtr.Zero;
            try
            {
                process = ProcessUtil.StartProcess(appName, baseDir);

            }
            catch (Exception ex)
            {
                // MessageBox.Show(fm, ex.Message, "Error");
                return process;
            }

            return process;
        }
        public static IntPtr PutIntoForm(Panel panel, string titleName)
        {
            IntPtr appWin = FindWindow(null, titleName);
            if (appWin == IntPtr.Zero)
            {
                appWin = GetDesktopWindows(titleName);
            }
            // Put it into this form
            SetParent(appWin, panel.Handle);

            // Remove border and whatnot
            // SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);

            // Move the window to overlay it on this window
            MoveWindow(appWin, 0, 0, panel.Width + 2, panel.Height, true);
            return appWin;
        }
        public static void Resize(Panel panel, string titleName)
        {
            IntPtr appWin = FindWindow(null, titleName);
            if (appWin != IntPtr.Zero)
                WindowUtil.MoveWindow(appWin, 0, 0, panel.Width, panel.Height, true);
        }
        public static void RemoveFromForm(string titleName)
        {
            IntPtr appWin = FindWindow(null, titleName);
            // Put it into this form
            SetParent(appWin, IntPtr.Zero);
        }
        /// <summary>
        /// 找到某个窗口与给出的类别名和窗口名相同窗口 
        /// </summary>
        /// <param name="lpClassName">类别名</param>
        /// <param name="lpWindowName">窗口名</param>
        /// <returns>成功找到返回窗口句柄,否则返回null</returns>
        [DllImport("user32.dll")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        /// <summary>
        /// 切换到窗口并把窗口设入前台,类似 SetForegroundWindow方法的功能
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <param name="fAltTab">True代表窗口正在通过Alt/Ctrl +Tab被切换</param>
        [DllImport("user32.dll ", SetLastError = true)]
        public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

        /// <summary>
        ///  设置窗口的显示状态 
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <param name="cmdShow">指示窗口如何被显示</param>
        /// <returns>如果窗体之前是可见,返回值为非零;如果窗体之前被隐藏,返回值为零</returns>
        [DllImport("user32.dll", EntryPoint = "ShowWindow", CharSet = CharSet.Auto)]
        public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);


        [DllImport("user32.dll", SetLastError = true)]
        private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        /// <summary>
        /// 改变指定窗口的位置和尺寸
        /// </summary>
        /// <param name="hwnd">窗口句柄</param>
        /// <param name="x">窗口左侧的新位置</param>
        /// <param name="y">窗口顶部的新位置</param>
        /// <param name="nWidth">窗口的新宽度</param>
        /// <param name="nHeight">窗口的新高度</param>
        /// <param name="bRepaint">指示是否重新绘制窗口。 如果此参数为 TRUE,窗口将收到消息。 如果参数为 FALSE,则不会重新绘制任何类型的参数。 这适用于工作区、非client 区域 (,包括标题栏和滚动条) ,以及由于移动子窗口而发现父窗口的任何部分</param>
        /// <returns>该函数成功,则返回值为非零值</returns>
        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, bool bRepaint);

        [DllImport("user32.dll")]
        private static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, string lparam);
        [DllImport("user32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(IntPtr hwnd, int Msg, int wParam, int lParam);
        [DllImport("user32.dll")]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll")]
        private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll")]
        private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount);
        private delegate bool WNDENUMPROC(IntPtr hWnd, int lParam);

        //寻找系统的全部窗口
        public static WindowInfo[] GetAllDesktopWindows()
        {
            List<WindowInfo> wndList = new List<WindowInfo>();
            EnumWindows(delegate (IntPtr hWnd, int lParam)
            {
                WindowInfo wnd = new WindowInfo();
                StringBuilder sb = new StringBuilder(256);
                //get hwnd
                wnd.hWnd = hWnd;
                //get window name
                GetWindowTextW(hWnd, sb, sb.Capacity);
                wnd.szWindowName = sb.ToString();
                //get window class
                GetClassNameW(hWnd, sb, sb.Capacity);
                wnd.szClassName = sb.ToString();
                Console.WriteLine("Window handle=" + wnd.hWnd.ToString().PadRight(20) + " szClassName=" + wnd.szClassName.PadRight(20) + " szWindowName=" + wnd.szWindowName);
                //add it into list
                wndList.Add(wnd);
                return true;
            }, 0);
            return wndList.ToArray();
        }

        public static IntPtr GetDesktopWindows(string windowName, StringComparison comparison = StringComparison.Ordinal)
        {
            WindowInfo[] allWindow = WindowUtil.GetAllDesktopWindows();
            var wnd = allWindow.FirstOrDefault(s => s.szWindowName.StartsWith(windowName, comparison));// s.szWindowName.Equals(windowName, comparison)
            return wnd.hWnd;
        }
    }
    public struct WindowInfo
    {
        public IntPtr hWnd;
        public string szWindowName;
        public string szClassName;
    }
}