C# 如何对焦外部窗口?
我有一个应用程序,它一次只能打开一个实例。为了实现这一点,我使用以下代码:C# 如何对焦外部窗口?,c#,.net,focus,C#,.net,Focus,我有一个应用程序,它一次只能打开一个实例。为了实现这一点,我使用以下代码: System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcesses(); System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess(); foreach (System.Diagno
System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcesses();
System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess();
foreach (System.Diagnostics.Process p in myProcesses)
{
if (p.ProcessName == me.ProcessName)
if (p.Id != me.Id)
{
//if already running, abort this copy.
return;
}
}
//launch the application.
//...
它很好用。我还希望它能够集中已经运行的副本的形式。也就是说,在返回之前,我想把这个应用程序的另一个实例放到前台
我该怎么做
回复:SetForeGroundWindow:
SetForeGroundWindow在某种程度上起作用:
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
//...
if (p.Id != me.Id)
{
//if already running, focus it, and then abort this copy.
SetForegroundWindow(p.MainWindowHandle);
return;
}
//...
如果窗口没有最小化,它会将窗口带到前台。令人惊叹的。
但是,如果窗口最小化,它将保持最小化状态
它需要取消最小化
通过切换到此窗口的解决方案(有效!):
我相信你会想用
您能抓取Process对象的MainWindowHandle属性并向其发送一条WM\u用户消息,您可以将其解释为“其他实例想让我站到前面来”完成旁注 你可以用
Process.GetProcessesByName(me.ProcessName)
而不是在系统上运行的所有进程上循环
更新
这类事情的规则…我也有同样的问题,而且对我来说效果最好。唯一的限制是必须安装XP sp1。我玩过SetForeGroundIndow和ShowWindow,它们在将窗口拉入视图时都有问题。与OP一样,我发现在最小化窗口时,仅使用
SetForeGroundIndow
是不够的。因为我不想使用切换到此窗口
,所以我选择了ShowWindow
,然后选择setforegroundindow
很适合我
private const SW_SHOWNORMAL = 1
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As integer) As Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Private Function SetForegroundWindow(ByVal hwnd As IntPtr) As Boolean
End Function
Sub SetForeground()
Dim processes As Process() = Process.GetProcessesByName("myprocess")
For Each p as Process in processes
ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL)
SetForegroundWindow(p.MainWindowHandle)
Next
End Sub
private const SW\u SHOWNORMAL=1
_
私有函数ShowWindow(ByVal hwnd作为IntPtr,ByVal nCmdShow作为整数)作为布尔值
端函数
_
私有函数SetForegroundWindow(ByVal hwnd作为IntPtr)作为布尔值
端函数
子集合前景()
Dim processs As Process()=Process.getProcessByName(“myprocess”)
对于流程中的每个p as流程
ShowWindow(p.MainWindowHandle,SW_SHOWNORMAL)
SetForegroundWindow(p.MainWindowHandle)
下一个
端接头
C#相当于汤姆·尤尔根斯的答案。对我来说很有魅力
private const int SW_SHOWNORMAL = 1;
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetForegroundWindow(IntPtr hwnd);
public void SetForeground()
{
Process[] processes = Process.GetProcessesByName("process name");
foreach (Process p in processes) {
ShowWindow(p.MainWindowHandle, SW_SHOWNORMAL);
SetForegroundWindow(p.MainWindowHandle);
}
}
这是桌面应用程序中非常常见的行为,我在创建新的WPF应用程序时经常必须这样做。因此,我创建了一个SingletonApp类,该类继承自应用程序:
public class SingletonApp : Application
{
private static readonly System.Threading.Mutex mutex;
private static readonly string processName;
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int flags);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hwnd);
static SingletonApp()
{
processName = Process.GetCurrentProcess().ProcessName;
mutex = new System.Threading.Mutex(false, $"Local\\{processName}");
}
/// <summary>
/// A base class for application needing to prevent multiple instances
/// </summary>
public SingletonApp()
{
if (!mutex.WaitOne(0, false))
{
// Give focus to existing instance before shutdown
BringToFront(processName);
Current.Shutdown();
}
}
public void BringToFront(string processName)
{
Process process = Process.GetProcessesByName(processName).FirstOrDefault();
if (process != null)
{
// In case of window is minimized
ShowWindow(process.MainWindowHandle, 1); // 1 = Normal
SetForegroundWindow(process.MainWindowHandle);
}
}
}
不要忘了更新App.xaml:
<utils:SingletonApp x:Class="MyApp.App"
[...]
xmlns:utils="clr-namespace:MyApp.Utils"
Startup="App_OnStartup">
有了它,在每一个新的桌面客户端上实现这种行为变得非常容易。可以做到这一点,但看起来很难看。如果SetForegroundWindow无法运行,这可能是一个很好的选择。检查窗口是否为圆锥形,如果是,请调用ShowWindow。但是请注意,链接的MSDN页面上会显示“[此功能不适用于一般用途。它可能会被更改或在后续版本的Windows中不可用。]”我们如何简化上述步骤,以便快速启动已经运行的应用程序?
public partial class App : SingletonApp
<utils:SingletonApp x:Class="MyApp.App"
[...]
xmlns:utils="clr-namespace:MyApp.Utils"
Startup="App_OnStartup">