1、封装一个句柄操作类IntPtrHelper.cs
public static class IntPtrHelper { public const int WS_SHOWMAXIMIZE = 3; //最大化显示窗口 public const int WS_SHOW = 5;//以原来大小和位置显示 /// <summary> /// 获取所有窗体 /// </summary> /// <returns></returns> public static List<WindowInfo> GetAllDesktopWindows() { List<WindowInfo> wndList = new List<WindowInfo>(); //enum all desktop windows 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.WindowName = sb.ToString(); //get window class GetClassNameW(hWnd, sb, sb.Capacity); wnd.ClassName = sb.ToString(); //add it into list wndList.Add(wnd); return true; }, 0); return wndList; } /// <summary> /// 定义委托 /// </summary> /// <param name="hWnd">The h WND.</param> /// <param name="lParam">The l parameter.</param> /// <returns></returns> private delegate bool Wndenumproc(IntPtr hWnd, int lParam); /// <summary> ///枚举所有的窗体 /// </summary> /// <param name="lpEnumFunc">The lp enum function.</param> /// <param name="lParam">The l parameter.</param> /// <returns></returns> [DllImport("user32.dll")] private static extern bool EnumWindows(Wndenumproc lpEnumFunc, int lParam); /// <summary> ///查找窗体tit /// </summary> /// <param name="hWnd">The h WND.</param> /// <param name="lpString">The lp string.</param> /// <param name="nMaxCount">The n maximum count.</param> /// <returns></returns> [DllImport("user32.dll")] private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount); /// <summary> ///查找窗体类名 /// </summary> /// <param name="hWnd">The h WND.</param> /// <param name="lpString">The lp string.</param> /// <param name="nMaxCount">The n maximum count.</param> /// <returns></returns> [DllImport("user32.dll")] private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpString, int nMaxCount); /// <summary> ///窗体置顶 /// </summary> /// <param name="hWnd">The h WND.</param> /// <param name="hWndInsertAfter">The h WND insert after.</param> /// <param name="x">The x.</param> /// <param name="y">The y.</param> /// <param name="Width">The width.</param> /// <param name="Height">The height.</param> /// <param name="flags">The flags.</param> /// <returns></returns> [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags); /// <summary> /// 该函数设置由不同线程产生的窗口的显示状态。 /// </summary> /// <param name="hWnd">窗口句柄</param> /// <param name="cmdShow">指定窗口如何显示。查看允许值列表,请查阅ShowWlndow函数的说明部分。</param> /// <returns>如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零。</returns> [DllImport("User32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); /// <summary> /// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。 /// </summary> /// <param name="hWnd">将被激活并被调入前台的窗口句柄。</param> /// <returns>如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零。</returns> [DllImport("User32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); /// <summary> /// 根据窗口标题查找窗体 /// </summary> /// <param name="lpClassName"></param> /// <param name="lpWindowName"></param> /// <returns></returns> [DllImport("user32.dll", EntryPoint = "FindWindow")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); } /// <summary> /// 窗体信息 /// </summary> public struct WindowInfo { /// <summary> /// The h WND /// </summary> public IntPtr HWnd; /// <summary> /// The window name /// </summary> public string WindowName; /// <summary> /// The class name /// </summary> public string ClassName; }
1、改造Program.cs的Main方法
/// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { Process instance = RunningInstance(); if (instance == null) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Frm_Main()); } else { HandleRunningInstance(instance); } }
这里面涉及到两个方法,一个是RunningInstance(),获取正在运行的程序进程;一个是HandleRunningInstance(),激活正在运行的程序。
看看怎么实现的:
/// <summary> /// 获取正在运行的实例,没有运行的实例返回null; /// </summary> public static Process RunningInstance() { try { Process current = Process.GetCurrentProcess(); var processes = Process.GetProcessesByName(current.ProcessName).Where(x => x.Id != current.Id).ToList(); foreach (Process process in processes) { if (process?.MainModule?.FileName == current.MainModule.FileName) { return process; } } return null; } catch { return null; } }
/// <summary> /// 显示已运行的程序。 /// </summary> public static void HandleRunningInstance(Process instance) { IntPtr hwnd = instance.MainWindowHandle; if (hwnd == IntPtr.Zero) { var wins = IntPtrHelper.GetAllDesktopWindows(); string winname = "窗体名称"; if (wins.Exists(x => x.WindowName.Contains(winname))) { var cla = wins.Where(x => x.WindowName.Contains(winname)).ToList(); cla.ForEach(x => { IntPtrHelper.ShowWindowAsync(x.HWnd, IntPtrHelper.WS_SHOWMAXIMIZE); IntPtrHelper.SetForegroundWindow(x.HWnd); }); } } else { IntPtrHelper.ShowWindowAsync(hwnd, IntPtrHelper.WS_SHOWMAXIMIZE); IntPtrHelper.SetForegroundWindow(hwnd); } }
激活正在运行的程序这里,我们遇到点问题,当程序缩小到托盘的时候,获取不到句柄信息,导致激活不了窗体
所以我们当获取到的句柄为IntPtr.Zero的时候,通过窗体名称遍历一下所有的进程,找到指定的进程,再激活
留下您的脚步
最近评论