Подтвердить что ты не робот

Правильный способ (в .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 сведено к минимуму, эта функция бесшумно терпит неудачу с точки зрения пользователя.

Итак, каков правильный способ сделать это?

4b9b3361

Ответ 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, конкретная конфигурация и т.д.), Которые могут помешать вам изменить фокус конечного пользователя.

Ответ 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