SetForegroundWindow only working while visual studio is open
Asked Answered
S

2

21

I'm trying to set with c# a process window to the foreground / focus (from an application that has no focus in that moment when doing it), therefore I'm using the user32.dll static extern bool SetForegroundWindow(IntPtr hWnd) method:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd); 
public void setFocus()
{
    SetForegroundWindow(process.MainWindowHandle);       
}

Every thing is working fine, but only if I have the visual studio 2008 open, I don't even need to to start the application from the VS08, it's enough to have the project open with it. The moment I'm closing the project my application can't set the other window to the foreground. The only result is that in the taskbar the other window is blue highlighted. The moment I'm going to open my project with the VS08 again it's working fine.

I have not the slightest idea why...I thought the problem could be that he can't import the dll but then it wouldn't be highlighted, and other win32 functions like static extern bool ShowWindow(IntPtr hWnd, IntPtr status); are working even when the project is closed.

Any solutions or hints for this problem?

Edit: I read the remarks for the function and I had the idea that my application has not the focus, so I tried this one:

[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
static extern bool AllowSetForegroundWindow(int procID);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); 
public void setAUTFocus()
{
    IntPtr hWnd = GetForegroundWindow();
    uint processID = 0;
    uint threadID = GetWindowThreadProcessId(hWnd, out processID);
    int intID = (int)processID;
    AllowSetForegroundWindow(intID);
    SetForegroundWindow(process.MainWindowHandle); 
}        

Now I'm searching for the window process that has focus at the moment and set the AllowSetForegroundWindow for this window and trying to set the focus on my window now. But the same problem, the moment I have the project in VS open it's working, if not I'm getting only the blue highlight in the taskbar.

During having my application running I can open / close the vs project, the moment it's open everything is working, the moment it's closed it's not working, I have no interaction with the VS project while running my application. Seriously I don't get it.

Subsonic answered 24/5, 2012 at 15:14 Comment(5)
see remarks in SetForeground window documentation msdn.microsoft.com/en-us/library/windows/desktop/…Synchroflash
so i have to call the function AllowSetForegroundWindow before, with the process id of the window thats in focus, when trying to put the other window to the front ?Subsonic
and i its not the answer why its working when the VS project is open, the current foreground window is never the VSSubsonic
it wasnt the answer, I just commented to draw your attention to that matterSynchroflash
This does not work for UWP since retrieving information about local processes is not supported on this platform.Jetta
S
31

After searching a few days on the internet I have found one posible simple solution to make SetForegroundWindow to work on windows 7: press Alt key before calling SetForegroundWindow.

public static void ActivateWindow(IntPtr mainWindowHandle)
    {
        //check if already has focus
        if (mainWindowHandle == GetForegroundWindow())  return;

        //check if window is minimized
        if (IsIconic(mainWindowHandle))
        {
            ShowWindow(mainWindowHandle, Restore);
        }

        // Simulate a key press
        keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);

        //SetForegroundWindow(mainWindowHandle);

        // Simulate a key release
        keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);

        SetForegroundWindow(mainWindowHandle);
    }

And the win32api imports

  private const int ALT = 0xA4;
  private const int EXTENDEDKEY = 0x1;
  private const int KEYUP = 0x2;
  private const uint Restore = 9;

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

  [DllImport("user32.dll")]
  private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

  [DllImport("user32.dll")]
  [return: MarshalAs(UnmanagedType.Bool)]
  private static extern bool IsIconic(IntPtr hWnd);

  [DllImport("user32.dll")]
  private static extern int ShowWindow(IntPtr hWnd, uint Msg);

  [DllImport("user32.dll")]
  private static extern IntPtr GetForegroundWindow();
Sedan answered 14/12, 2012 at 15:31 Comment(6)
Why do you need to press the Alt key?Breach
If you dont simulate the Alt key, setforgroundwindow it wont work properly. The program you want to switch to, it will flash in taskbar but not come in foreground. Setforgroundwindow works ok when you run your program from visual studio, debugging.Sedan
Thanks for the answer. Very strange behaviour by the way. I will be pleased to have an detailed explanation of this.Arrear
sorry, didn't tested on windows 10Sedan
It works on Windows 10 and you don't even have to simulate the alt key down, only upPeen
The only solution that has worked on Windows 11 (22H2) for me. The trick was the ALT key, and yes simulating only the ALT_UP worked. Thank youMarxismleninism
C
17

I had an issue with sending the Alt-key as it forced the window menu to open when I selected enter (instead of the OK button which is what I wanted).

This worked for me:

public static void ActivateWindow(IntPtr mainWindowHandle)
{
    //check if already has focus
    if (mainWindowHandle == GetForegroundWindow())  return;

    //check if window is minimized
    if (IsIconic(mainWindowHandle))
    {
        ShowWindow(mainWindowHandle, Restore);
    }

    // Simulate a key press
    keybd_event(0, 0, 0, 0);

    SetForegroundWindow(mainWindowHandle);
}
Cyprus answered 1/6, 2015 at 11:53 Comment(1)
keybd_event(0, 0, 0, 0); = Keys.NONE was internally filtered out in Windows 7. However, post Windows 10 it is not being filtered out by Windows and has an unexpected affect on the application. So use it if you are really sure of this.Heronry

© 2022 - 2024 — McMap. All rights reserved.