如何从可执行文件中打开应用程序主界面,而不是在c#中的托盘图标上

mur*_*ki5 2 c# forms show tray

这是场景,我打开我的应用程序然后托盘图标显示,如果我双击托盘图标,将显示主界面.如果我再次打开我的应用程序,主界面应该被给予焦点或如果它还没有显示那么它应该显示而不是打开我的应用程序的另一个实例.

这是我的代码的样子:

//Program.cs
.....

if(myAppIsNotRunningYet) //the program has not been open yet
{
MyTray = new MyTray();
Application.Run();
}

else //the program is already on the tray
{
//the code to give focus to the mainForm or open it up if not yet open
}

//MyTray.cs
.....
public MyTray()
{
notifyIcon = new NotifyIcon();
....
notifyIcon.Visible = true;
}

private void notifyIcon_DoubleClick(object sender, EventArgs e)
{
MainForm mainForm = new MainForm();
mainForm.ShowDialog();
}
Run Code Online (Sandbox Code Playgroud)

Phi*_*ace 5

编辑:好的,似乎要正确覆盖WndProc,你必须使用一个/可见的表单.以下是使用MessageFilter的不同解决方案.这确实有效,所以希望你能从这里开始!

 internal sealed class Program
 { 
  /// <summary>
  /// Program entry point.
  /// </summary>
  [STAThread]
  public static void Main(string[] args)
  {
    bool newMutex;
    System.Threading.Mutex mutex = new System.Threading.Mutex(true, "{9F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}", out newMutex);

     // Attempt aquire the mutex
     if(newMutex)
     {
      // If we are able to aquire the mutex, it means the application is not running.
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);

         // Create the new tray icon
         MyTray myTray = new MyTray();

         Application.AddMessageFilter(myTray);
         Application.Run();

         // Release the mutex on exit
         mutex.ReleaseMutex();
     }
     else
     {
        // If the aquire attempt fails, the application is already running
        // so we broadcast a windows message to tell it to wake up.
         NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_SHOWME, IntPtr.Zero, IntPtr.Zero);
     }
     }
 }
}

internal class NativeMethods
 {
     public const int HWND_BROADCAST = 0xffff;
     public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");

     [DllImport("user32")]
     public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

     [DllImport("user32")]     
     public static extern int RegisterWindowMessage(string message);
 }

 public class MyTray : IMessageFilter
 {
  private NotifyIcon notifyIcon = new NotifyIcon();
  private Form myForm = new Form();

  public MyTray()
  {
     this.notifyIcon.Icon = System.Drawing.Icon.FromHandle(new System.Drawing.Bitmap(16,16).GetHicon());
     this.notifyIcon.Visible = true;
     this.notifyIcon.DoubleClick += delegate(object sender, EventArgs e) { ShowForm(); };
  }

     void ShowForm()
     {
        this.notifyIcon.Visible = false;            
        this.myForm.ShowDialog();   
        this.notifyIcon.Visible = true;
      }

    public bool PreFilterMessage(ref Message m)
    {
       // If the message is the 'show me' message, then hide the icon and show the form.
       if(m.Msg == NativeMethods.WM_SHOWME)
       {
            if (!this.myForm.Visible)
            {
                ShowForm();
                return true; // Filter the message
            }
       }

       return false; // Forward the message
    }
 }
Run Code Online (Sandbox Code Playgroud)

编辑:我把一个更接近你的场景的样本放在一起:

 internal sealed class Program
 {
  static System.Threading.Mutex mutex = new System.Threading.Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");

  /// <summary>
  /// Program entry point.
  /// </summary>
  [STAThread]
  private static void Main(string[] args)
  {
   // Attempt aquire the mutex
         if(mutex.WaitOne(TimeSpan.Zero, true))
         {
          // If we are able to aquire the mutex, it means the application is not running.
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);

             // Create the new tray icon
             MyTray myTray = new MyTray();

             Application.Run();

             // Release the mutex on exit
             mutex.ReleaseMutex();
         }
         else
         {
            // If the aquire attempt fails, the application is already running
            // so we broadcast a windows message to tell it to wake up.
             NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_SHOWME, IntPtr.Zero, IntPtr.Zero);
         }
     }
 }

 internal class NativeMethods
 {
     public const int HWND_BROADCAST = 0xffff;
     public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");

     [DllImport("user32")]
     public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

     [DllImport("user32")]     
     public static extern int RegisterWindowMessage(string message);
 }

 public class MyTray : Control
 {
  private NotifyIcon notifyIcon = new NotifyIcon();

  public MyTray()
  {
   this.notifyIcon.Visible = true;
  }

  /// <summary>
  /// This method listens to all windows messages either broadcast or sent to this control
  /// </summary>
  protected override void WndProc(ref Message m)
  {
   // If the message is the 'show me' message, then hide the icon and show the form.
   if(m.Msg == NativeMethods.WM_SHOWME)
   {
    this.notifyIcon.Visible = false;
    using (Form mainForm = new Form())
    {
     mainForm.ShowDialog();
     this.notifyIcon.Visible = true;
    }  
   }
   else
   {
    base.WndProc(ref m);    
   }   
  }
 }
Run Code Online (Sandbox Code Playgroud)

编辑: 我在C#中找到了一个结合了互斥锁和Windows消息的示例:

C#.NET单实例应用程序



互斥锁可能是最好的方法.将此与应用程序侦听的自定义Windows消息相结合,使其自身成为焦点(请参阅VB.NET,VB6和C#通过Window Messaging进行进程间通信).

查看此示例: C# - 单个应用程序实例