C# 如何聚焦外窗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/444430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I focus a foreign window?
提问by Jude Allred
I have an application which may only have one instance of itself open at a time. To enforce this, I use this code:
我有一个应用程序,它一次可能只打开一个实例。为了强制执行此操作,我使用以下代码:
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.
//...
It works fine. I would also like it to be able to focus the form of the already-running copy. That is, before returning, I want to bring the other instance of this application into the foreground.
它工作正常。我也希望它能够聚焦已经运行的副本的形式。也就是说,在返回之前,我想把这个应用程序的另一个实例带到前台。
How do I do that?
我怎么做?
Re: SetForeGroundWindow:
回复:SetForeGroundWindow:
SetForeGroundWindow works, to a point:
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;
}
//...
This does bring the window to the foreground if it is not minimized. Awesome. If the window IS minimized, however, it remains minimized.
如果没有最小化,这确实会将窗口带到前台。惊人的。然而,如果窗口被最小化,它仍然是最小化的。
It needs to un-minimize.
它需要取消最小化。
Solution via SwitchToThisWindow (Works!):
通过 SwitchToThisWindow 的解决方案(有效!):
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
[STAThread]
static void Main()
{
System.Diagnostics.Process me = System.Diagnostics.Process.GetCurrentProcess();
System.Diagnostics.Process[] myProcesses = System.Diagnostics.Process.GetProcessesByName(me.ProcessName);
foreach (System.Diagnostics.Process p in myProcesses)
{
if (p.Id != me.Id)
{
SwitchToThisWindow(p.MainWindowHandle, true);
return;
}
}
//now go ahead and start our application ;-)
采纳答案by scottm
I had the same problem and SwitchToThisWindow()worked the best for me. The only limitation is that you must have XP sp1 installed. I played with SetForegroundWindow, ShowWindow, and they both had problems pulling the window into view.
我遇到了同样的问题,SwitchToThisWindow()对我来说效果最好。唯一的限制是您必须安装 XP sp1。我玩过 SetForegroundWindow、ShowWindow,它们都在将窗口拉入视图中时遇到了问题。
回答by cmsjr
回答by plinth
Can you grab MainWindowHandle property of the Process object and send it a WM_USER message that you can interpret as "some other instance wants to bring me to the front".
您能否获取 Process 对象的 MainWindowHandle 属性并向其发送 WM_USER 消息,您可以将其解释为“其他一些实例想要将我带到前面”。
回答by Jason Punyon
回答by Tom Juergens
Same as OP, I found that SetForegroundWindow
alone wasn't enough when the window was minimized. Since I didn't want to use SwitchToThisWindow
, I chose ShowWindow
followed by SetForegroundWindow
.
与 OP 相同,我发现SetForegroundWindow
当窗口最小化时,仅靠它是不够的。由于我不想使用SwitchToThisWindow
,我选择ShowWindow
了SetForegroundWindow
。
Works well for me!
对我来说效果很好!
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
回答by Nigrimmist
C# equivalent of Tom Juergens's answer. Works like a charm for me.
C# 相当于 Tom Juergens 的回答。对我来说就像一种魅力。
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);
}
}