Switch to last active application like Alt-Tab
Asked Answered
C

2

4

ok, I have found many posts on finding a window by name, etc. What I have not found is how to find and switch the window application focus to last active window. The code I am showing below will give me the list of active applications in the task manager that are active.

What I can not figure out how to do is figure out what application was the last active application, and then switch to it. for example...

I have my custom winform application open.

I click a button

My application switches to the last active window / application.

Here is the working code I have so far. (this is the action on a button, and it expects that the application has a textbox named textbox1. you will also need to add using System.Diagnostics;

    private void button1_Click(object sender, EventArgs e)
    {

        Process[] procs = Process.GetProcesses();
        IntPtr hWnd;
        foreach (Process proc in procs)
        {
            if ((hWnd = proc.MainWindowHandle) != IntPtr.Zero)
            {
                textBox1.Text += (proc.ProcessName.ToString());
                textBox1.Text += "\t";
                textBox1.Text += (hWnd.ToString());
                textBox1.Text += "\r\n";
            }
        }         

    }
Cott answered 27/2, 2012 at 16:27 Comment(5)
#211004Affaire
I looked at this one already. It does not work for me. what class is HWND in? I do not seem to have System.Windows.Interop I have System.Runtime.InteropServices But it does not seem to be in this class.Cott
HWND comes from the Windows SDK and represents a window's handle.Affaire
Your comments do not help me with the information you have given. I posted this question because I have hit a dead end. I will look into the Windows SDK though.Cott
You don't need to "look into the Windows SDK". You just need a clearer guide. What you want to do is explained all over the internet. You just may not understand the jargon. For example: #6434975Echovirus
A
2

Since my comments didn't help you, here's a little resume (didn't test it though):

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

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

[DllImport("user32.dll", ExactSpelling = true)]
static extern IntPtr GetForegroundWindow();

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

const uint GA_PARENT = 1;
const uint GA_ROOT = 2;
const uint GA_ROOTOWNER = 3;

public IntPtr GetPreviousWindow()
{
        IntPtr activeAppWindow = GetForegroundWindow();
        if ( activeAppWindow == IntPtr.Zero )
            return IntPtr.Zero;

        IntPtr prevAppWindow = GetLastActivePopup(activeAppWindow);
        return IsWindowVisible(prevAppWindow) ? prevAppWindow : IntPtr.Zero;
 }

 public void FocusToPreviousWindow()
 {
     IntPtr prevWindow = GetPreviousWindow();
     if (  prevWindow != IntPtr.Zero )
         SetForegroundWindow(prevWindow);
 }
Affaire answered 27/2, 2012 at 17:5 Comment(4)
Thank you Vulkanino, The main issue is I have not really used the DLLImport many times and I do not understand the code fully. I am looking at the code you added and If I understand it correctly I would use the GetPreviousWindow to return the hwnd of the last active window. But when if I add a MessageBox.Show(GetPreviousWindow()); to a button action it tells me that the GetPreviousWindow expects a IntPtr of hwnd. I thought that is what it was finding for me.Cott
I am sorry, my mistake, the parameter is useless. I edit my answer to correct.Affaire
ok, so when I use this code vulkanino by placing the method in a button action it only returns the handle or what ever it is called for the application that the button is sitting on. (meaning it does not call the previous application)Cott
yes, it gives you the handle of the previous window, if you want to set the focus to it, you have to call SetForegroundWindow function explicitly. editing my answer just to add that.Affaire
H
5

Check this article out: http://www.whitebyte.info/programming/how-to-get-main-window-handle-of-the-last-active-window

Specifically, this code:

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
enum GetWindow_Cmd : uint
{
    GW_HWNDFIRST = 0,
    GW_HWNDLAST = 1,
    GW_HWNDNEXT = 2,
    GW_HWNDPREV = 3,
    GW_OWNER = 4,
    GW_CHILD = 5,
    GW_ENABLEDPOPUP = 6
}
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

[...]

IntPtr targetHwnd = GetWindow(Process.GetCurrentProcess().MainWindowHandle, (uint)GetWindow_Cmd.GW_HWNDNEXT);
while (true)
{
    IntPtr temp = GetParent(targetHwnd);
    if (temp.Equals(IntPtr.Zero)) break;
    targetHwnd = temp;
}
SetForegroundWindow(targetHwnd);
Heilman answered 27/2, 2012 at 16:59 Comment(2)
This does exactly what I was trying to do.Cott
Interesting note. This code works in my test windows form application but when I put it in the little utility I am playing with it does not switch to the previous application. It switches to an application that is just a process it seems.Cott
A
2

Since my comments didn't help you, here's a little resume (didn't test it though):

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

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

[DllImport("user32.dll", ExactSpelling = true)]
static extern IntPtr GetForegroundWindow();

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

const uint GA_PARENT = 1;
const uint GA_ROOT = 2;
const uint GA_ROOTOWNER = 3;

public IntPtr GetPreviousWindow()
{
        IntPtr activeAppWindow = GetForegroundWindow();
        if ( activeAppWindow == IntPtr.Zero )
            return IntPtr.Zero;

        IntPtr prevAppWindow = GetLastActivePopup(activeAppWindow);
        return IsWindowVisible(prevAppWindow) ? prevAppWindow : IntPtr.Zero;
 }

 public void FocusToPreviousWindow()
 {
     IntPtr prevWindow = GetPreviousWindow();
     if (  prevWindow != IntPtr.Zero )
         SetForegroundWindow(prevWindow);
 }
Affaire answered 27/2, 2012 at 17:5 Comment(4)
Thank you Vulkanino, The main issue is I have not really used the DLLImport many times and I do not understand the code fully. I am looking at the code you added and If I understand it correctly I would use the GetPreviousWindow to return the hwnd of the last active window. But when if I add a MessageBox.Show(GetPreviousWindow()); to a button action it tells me that the GetPreviousWindow expects a IntPtr of hwnd. I thought that is what it was finding for me.Cott
I am sorry, my mistake, the parameter is useless. I edit my answer to correct.Affaire
ok, so when I use this code vulkanino by placing the method in a button action it only returns the handle or what ever it is called for the application that the button is sitting on. (meaning it does not call the previous application)Cott
yes, it gives you the handle of the previous window, if you want to set the focus to it, you have to call SetForegroundWindow function explicitly. editing my answer just to add that.Affaire

© 2022 - 2024 — McMap. All rights reserved.