Правильный способ (в .NET) переключить фокус на другое приложение
Это то, что у меня есть до сих пор:
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
У него две проблемы.
- Некоторые люди сказали мне, что SwitchToThisWindow лишен.
- Если приложение B сведено к минимуму, эта функция бесшумно терпит неудачу с точки зрения пользователя.
Итак, каков правильный способ сделать это?
Ответы
Ответ 1
Получить дескриптор окна (hwnd), а затем использовать эту функцию user32.dll:
Объявление VB.net:
Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Integer) As Integer
Объявление С#:
[DllImport("user32.dll")] public static extern int SetForegroundWindow(int hwnd)
Одно из соображений заключается в том, что это не сработает, если окно сведено к минимуму, поэтому я написал следующий метод, который также обрабатывает этот случай. Вот код С#, он должен быть достаточно прямым, чтобы перенести это на 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);
}
}
Используя этот код, это будет так же просто, как установка соответствующих переменных процесса и вызов BringMainWindowToFront("processName");
Ответ 2
Существует другой способ, который использует не известный API автоматизации пользовательского интерфейса:
AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle);
if (element != null)
{
element.SetFocus();
}
В большинстве случаев это будет работать, если можно переключиться на это окно. В Windows существует множество ограничений (безопасность, UAC, конкретная конфигурация и т.д.), Которые могут помешать вам изменить фокус конечного пользователя.
Ответ 3
Я использовал SetForegroundWindow, чтобы сделать окно из другого приложения.
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
Как мне задать другой фокус процесса с С#?
Ответ 4
Создайте новый класс в своем проекте и скопируйте в него код ниже.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace MyProject
{
public class ProcessHelper
{
public static void SetFocusToExternalApp(string strProcessName)
{
Process[] arrProcesses = Process.GetProcessesByName(strProcessName);
if (arrProcesses.Length > 0)
{
IntPtr ipHwnd = arrProcesses[0].MainWindowHandle;
Thread.Sleep(100);
SetForegroundWindow(ipHwnd);
}
}
//API-declaration
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
}
}
Теперь скопируйте вставьте указанный ниже код в требуемую область.
string procName = Process.GetCurrentProcess().ProcessName;
ProcessHelper.SetFocusToExternalApp(procName);
Здесь вы вызываете функцию для приведения фокуса в другое окно приложения.
Ответ 5
В VB.Net вы можете использовать AppActivate.
Dim App As Process() = Process.GetProcessesByName("program.exe")
If App.Length > 0 Then
AppActivate(App(0).Id)
End If
Ответ 6
Импорт
Imports System.Runtime.InteropServices
Поместите это в модуль
<DllImport("user32.dll")> _
Private Function SetForegroundWindow(hWnd As IntPtr) As Boolean
End Function
Public Sub FocusWindow(ByVal ProcessName As String)
Dim p As System.Diagnostics.Process = System.Diagnostics.Process.GetProcessesByName(ProcessName).FirstOrDefault
If p IsNot Nothing Then
SetForegroundWindow(p.MainWindowHandle)
SendKeys.SendWait("~") ' maximize the application if it minimized
End If
End Sub
Использование:
FocusWindow("Notepad")
Источник: http://www.codeproject.com/Tips/232649/Setting-Focus-on-an-External-application#_rating