C\mainwindowhandle is 0

Generally, when the program is run in a single instance, the running program can be activated when the program is run for the second time. Then you need to find the form handle of the program.

However, if the running program has been minimized or is not displayed in the taskbar, process The mainwindowhandle property may be 0, so you need other ideas to find the correct handle.

 

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

 

One drawback of method 1 is that if the main title of the program changes at any time, or the title may be repeated, it is not easy to find the minimized form handle.

 

The ideas after improvement of method 2 are as follows:

1. use process Getprocessesbyname() finds the running process, and finds the process whose process id is different from the current one The

2. if the process MainWindowHandle is 0, use FindWindowEx function to find all top-level window handles

3. use the GetWindowThreadProcessId function to determine whether the found handle belongs to the process

4. in step 3, you may find many top-level handles belonging to the form. You need to use the IsWindowVisible function to determine whether they are visible (the minimized form visibility is true, but the form position is moved to a negative coordinate value, which can not be seen on the desktop).

5. generally, you can find the correct form handle through step 4. If not, use the GetWindowRect function to find out whether the size of the form requires a handle to be found

6. after finding the correct handle, use ShowWindowAsync and setforegroupwindow functions to correctly activate the minimized form of the process.

 

Related functions:

        [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}";
        }
    }

 

The specific code will not be posted. Please pay attention to the following points:

 

1. it is necessary to call FindWindowEx circularly to find all desktop top-level handles

2. to determine whether the found handle is visible, use IsWindowVisible

3. after finding the correct handle, if it cannot be activated correctly, the ShowWindowAsync function can be called twice, such as 9 and 5

 

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

 

Tags: C#

Posted by adamata on Wed, 01 Jun 2022 02:02:12 +0530