C# MainWindowHandle为0的解决方法(2)

一般需要程序单例运行时,在第二次运行程序时,可以激活正在运行的程序。那么需要找到该程序的窗体句柄。

但如果运行程序已经最小化,或者没显示在任务栏,则Process.MainWindowHandle属性可能为0,则需要其他思路来找到正确的句柄。

 

方法1: https://www.cnblogs.com/xyz0835/p/3351424.html

 

方法1的有一个缺陷,就是如果程序的主标题随时在变化,或者标题有可能会重复,则不太方便找到已最小化的窗体句柄。

 

方法2改善后的思路如下:

1. 用Process.GetProcessesByName()查找在运行的进程,找出进程id与当前不同的进程. 

2. 如果进程MainWindowHandle为0,则利用FindWindowEx函数查找所有*窗体句柄

3. 利用GetWindowThreadProcessId函数,判断找出的句柄是否属于该进程

4. 步骤3中可能会找出不少属于该窗体的*句柄,那需要用IsWindowVisible函数判断其是否可见(最小化的窗体可见性是true,只是窗体位置移到了坐标负值,桌面上看不到)。

5.一般经过步骤4,就能找出正确的窗体句柄。如果还不对,则用GetWindowRect函数查找窗体的大小是否需要查找的句柄

6. 找到正确句柄后,使用ShowWindowAsync和SetForegroundWindow函数,就可以正确激活该进程的已最小化的窗体。

 

相关函数:

        [DllImport("user32.dll")]
        static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

        [DllImport("user32.dll")]
        static extern IntPtr GetWindowThreadProcessId(IntPtr window, out int process);

        [DllImport("user32.dll")]
        static extern IntPtr FindWindowEx(IntPtr parentWindow, IntPtr previousChildWindow, string windowClass, string windowTitle);

        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

        [DllImport("user32.dll")]
        static extern bool IsWindowVisible(IntPtr hWnd);

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;

        public int Width => Right - Left;

        public int Height => Bottom - Top;

        public override string ToString()
        {
            return $"{Left} {Top} {Width} {Height}";
        }
    }

 

具体代码就不贴出了,几个注意点:

 

1. 需要循环调用FindWindowEx找出所有桌面*句柄

2. 找出的句柄要判断是否可见,用IsWindowVisible判断

3. 找到正确句柄后,如不能正确激活,ShowWindowAsync函数可调用两次,传如9和5

 

ShowWindowAsync(hwnd, (int)ShowWindowFlag.SW_RESTORE); //9
ShowWindowAsync(hwnd, (int)ShowWindowFlag.SW_SHOW); //5
SetForegroundWindow(hwnd);

 

C# MainWindowHandle为0的解决方法(2)

上一篇:windows 创建隐藏账户


下一篇:C# 如何查询字符串前面有几个0