当最小化到系统托盘中时,WPF窗口不会响应来自其他实例的PostMessage的消息

时间:2012-10-01 19:46:15

标签: wpf

我正在开展一项任务,当同一个应用程序的第二个实例启动时,从系统托盘恢复并最大化窗口。

第二个实例启动时无法获取互斥锁。它调用以下代码来表示第一个实例显示自己:

public static void ShowFirstInstance()

  {
     WinApi.PostMessage(
        (IntPtr)WinApi.HWND_BROADCAST, 
        WM_SHOWFIRSTINSTANCE, 
        IntPtr.Zero, 
        IntPtr.Zero);
  }

使用以下内容注册消息:

public static readonly int WM_SHOWFIRSTINSTANCE =
         WinApi.RegisterWindowMessage("WM_SHOWFIRSTINSTANCE|{0}", 250);

我在窗口后面的代码中跟踪以捕获消息并显示窗口:

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
      {
         if (msg == SingleInstance.WM_SHOWFIRSTINSTANCE)
         {
             WinApi.ShowToFront(hwnd);
         }

         return IntPtr.Zero;
      }

当我测试它时。每当第一个实例隐藏在系统托盘中时,消息就不会被捕获。我错过了什么吗?

谢谢,

1 个答案:

答案 0 :(得分:0)

以下是我过去如何做到这一点:

App.xaml.cs:

private static readonly Mutex Mutex = new Mutex(true, "{" + YourGuidHere + "}");

//return true if other instance is open, allowing for UI cleanup/suspension while shutdown() is completed
private bool EnforceSingleInstance()
{
    //try...catch provides safety for if the other instance is closed during Mutex wait
    try
    {
        if (!Mutex.WaitOne(TimeSpan.Zero, true))
        {
            var currentProcess = Process.GetCurrentProcess();

            var runningProcess =
                Process.GetProcesses().Where(
                    p =>
                    p.Id != currentProcess.Id &&
                    p.ProcessName.Equals(currentProcess.ProcessName, StringComparison.Ordinal)).FirstOrDefault();

            if (runningProcess != null)
            {
                WindowFunctions.RestoreWindow(runningProcess.MainWindowHandle);

                Shutdown();
                return true;
            }
        }

        Mutex.ReleaseMutex();
    }
    catch (AbandonedMutexException ex)
    {
        //do nothing, other instance was closed so we may continue
    }
    return false;
}

WindowFunctions:

//for enum values, see http://www.pinvoke.net/default.aspx/Enums.WindowsMessages
public enum WM : uint
{
    ...
    SYSCOMMAND = 0x0112,
    ...
}

//for message explanation, see http://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx
private const int SC_RESTORE = 0xF120;

public static void RestoreWindow(IntPtr hWnd)
{
    if (hWnd.Equals(0))
        return;

    SendMessage(hWnd,
                (uint)WM.SYSCOMMAND,
                SC_RESTORE,
                0);
}

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd,
                                        uint msg,
                                        uint wParam,
                                        uint lParam);