Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way (in .NET) to switch the focus to another application

This is what I have so far:

Dim bProcess = Process.GetProcessesByName("By").FirstOrDefault If bProcess IsNot Nothing Then     SwitchToThisWindow(bProcess.MainWindowHandle, True) Else     Process.Start("C:\Program Files\B\B.exe") End If 

It has two problems.

  1. Some people have told me that SwitchToThisWindow is deprecated.
  2. If application B is minimized, this function silently fails from the user's perspective.

So what's the right way to do this?

like image 634
Jonathan Allen Avatar asked Feb 23 '10 01:02

Jonathan Allen


People also ask

How do I close a different program in C#?

You can use the methods Process. Kill or Process. CloseMainWindow to stop a process.


2 Answers

Get the window handle (hwnd), and then use this user32.dll function:

VB.net declaration:

Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Integer) As Integer  

C# declaration:

[DllImport("user32.dll")] public static extern int SetForegroundWindow(int hwnd)  

One consideration is that this will not work if the window is minimized, so I've written the following method which also handles this case. Here is the C# code, it should be fairly straight forward to migrate this to VB.

[System.Runtime.InteropServices.DllImport("user32.dll")] [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)] private static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);  [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern int SetForegroundWindow(IntPtr hwnd);  private enum ShowWindowEnum {     Hide = 0,     ShowNormal = 1, ShowMinimized = 2, ShowMaximized = 3,     Maximize = 3, ShowNormalNoActivate = 4, Show = 5,     Minimize = 6, ShowMinNoActivate = 7, ShowNoActivate = 8,     Restore = 9, ShowDefault = 10, ForceMinimized = 11 };  public void BringMainWindowToFront(string processName) {     // get the process     Process bProcess = Process.GetProcessesByName(processName).FirstOrDefault();      // check if the process is running     if (bProcess != null)     {         // check if the window is hidden / minimized         if (bProcess.MainWindowHandle == IntPtr.Zero)         {             // the window is hidden so try to restore it before setting focus.             ShowWindow(bProcess.Handle, ShowWindowEnum.Restore);         }          // set user the focus to the window         SetForegroundWindow(bProcess.MainWindowHandle);     }     else     {         // the process is not running, so start it         Process.Start(processName);     } } 

Using that code, it would be as simple as setting the appropriate process variables and calling BringMainWindowToFront("processName");

like image 130
caesay Avatar answered Sep 22 '22 00:09

caesay


There is another way, which uses the not well-known UI Automation API:

AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle); if (element != null) {     element.SetFocus(); } 

Most of the time, this will work if it's possible to switch to that window. There are a lot of limitations in Windows (security, UAC, specific configuration, etc...) that can prevent you to change the end-user focus.

like image 27
Simon Mourier Avatar answered Sep 22 '22 00:09

Simon Mourier