正确的方式(在.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是depricated。
- 如果应用程序B被最小化,则从用户的angular度来看,该function静静地失败。
那么做正确的方法是什么?
获取窗口句柄(hwnd),然后使用这个user32.dll函数:
VB.net声明:
Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Integer) As Integer
C#声明:
[DllImport("user32.dll")] public static extern int SetForegroundWindow(int hwnd)
一个考虑因素是,如果窗口最小化,这将不起作用,所以我写了下面的方法,也处理这种情况。 这里是C#代码,它应该是相当直接的将其迁移到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 nothing or not. if (bProcess != null) { // get the hWnd of the process IntPtr hwnd = bProcess.MainWindowHandle; if (hwnd == 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 nothing, so start it Process.Start(processName); } }
使用该代码,就像设置适当的stream程variables和调用BringMainWindowToFront("processName");
一样简单BringMainWindowToFront("processName");
还有另一种方法,它使用了不太知名的UI自动化API:
AutomationElement element = AutomationElement.FromHandle(process.MainWindowHandle); if (element != null) { element.SetFocus(); }
大多数情况下,如果可以切换到该窗口,这将工作。 Windows(安全性,UAC,特定configuration等)有很多限制,可能会阻止您更改最终用户的注意力。
我使用SetForegroundWindow来使另一个应用程序的窗口出现。
[DllImport("user32.dll")] static extern bool SetForegroundWindow(IntPtr hWnd);
我怎样才能从C#提供另一个过程焦点?
在你的项目中创build一个新类,并复制粘贴下面的代码。
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);
这里你正在调用函数来把焦点带到另一个应用程序的窗口。
在VB.Net中,您可以使用AppActivate函数。
Dim App As Process() = Process.GetProcessesByName("program.exe") If App.Length > 0 Then AppActivate(App(0).Id) End If
import:
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's minimized End If End Sub
用法:
FocusWindow("Notepad")
资料来源: http : //www.codeproject.com/Tips/232649/Setting-Focus-on-an-External-application#_rating