【发布时间】:2011-09-07 20:07:51
【问题描述】:
如果某个事件发生,我希望我的 c# winform 应用程序切换到另一个正在运行的实例。
例如,如果我有一个只有一个按钮的应用程序,并且此时正在运行三个实例。现在如果我
- 在第一个实例中按下按钮,聚焦到第二个实例
- 在第二个实例中按下按钮,聚焦到第三个实例
- 在第三次按下按钮,聚焦到第一次
我该怎么做?
【问题讨论】:
如果某个事件发生,我希望我的 c# winform 应用程序切换到另一个正在运行的实例。
例如,如果我有一个只有一个按钮的应用程序,并且此时正在运行三个实例。现在如果我
我该怎么做?
【问题讨论】:
如果您知道其他实例的句柄,则只需调用 Windows API:SetForegroundWindow:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
您可以使用 FindWindow API 调用来获取其他实例的句柄,例如:
public static int FindWindow(string windowName)
{
int hWnd = FindWindow(null, windowName);
return hWnd;
}
您可以在 SO 中搜索这些 api 调用以获取更多示例,例如找到这个:
【讨论】:
SetForegroundWindow 是一个很好的解决方案。另一种方法是使用命名Semaphores 向其他应用程序发送信号。
最后,您可以寻找一个Inter-Process Communication (IPC) 解决方案,它允许您在进程之间发送消息。
我编写了一个简单的 .Net XDMessaging 库,让这变得非常简单。使用它,您可以将指令从一个应用程序发送到另一个应用程序,并且在最新版本中甚至可以传递序列化对象。这是一个使用频道概念的多播实现。
应用1:
IXDBroadcast broadcast = XDBroadcast.CreateBroadcast(
XDTransportMode.WindowsMessaging);
broadcast.SendToChannel("commands", "focus");
应用程序2:
IXDListener listener = XDListener.CreateListener(
XDTransportMode.WindowsMessaging);
listener.MessageReceived+=XDMessageHandler(listener_MessageReceived);
listener.RegisterChannel("commands");
// process the message
private void listener_MessageReceived(object sender, XDMessageEventArgs e)
{
// e.DataGram.Message is the message
// e.DataGram.Channel is the channel name
switch(e.DataGram.Message)
{
case "focus":
// check requires invoke
this.focus();
break;
case "close"
this.close();
break;
}
}
【讨论】: