【问题标题】:Switch to other instance of same application切换到同一应用程序的其他实例
【发布时间】:2011-09-07 20:07:51
【问题描述】:

如果某个事件发生,我希望我的 c# winform 应用程序切换到另一个正在运行的实例。

例如,如果我有一个只有一个按钮的应用程序,并且此时正在运行三个实例。现在如果我

  1. 在第一个实例中按下按钮,聚焦到第二个实例
  2. 在第二个实例中按下按钮,聚焦到第三个实例
  3. 在第三次按下按钮,聚焦到第一次

我该怎么做?

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    如果您知道其他实例的句柄,则只需调用 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 调用以获取更多示例,例如找到这个:

    How do I focus a foreign window?

    【讨论】:

    • 想想SetForegroundWindow的限制。您不能将任何窗口从任何进程带到前面。见:msdn.microsoft.com/en-us/library/ms633539(v=vs.85).aspx
    • 两个实例的窗口名称相同时如何切换?
    • 实例在您的控制范围内吗?启动时可以分配不同的名称吗?
    【解决方案2】:

    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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-05
      • 1970-01-01
      相关资源
      最近更新 更多