2016-02-18 69 views
-1

我有一个由系统托盘notifyIcon及其上下文菜单组成的应用程序。在program.cs代码中,我使用Mutex来检查程序的一个实例是否已经在运行,然后再启动一个新的程序。目前,如果一个已经运行,新的实例就在那里退出。相反,当用户试图启动应用程序的新实例时,我希望它在运行实例中触发notifyIcon的上下文菜单。有没有办法做到这一点?有没有一种很好的方法可以在已经运行的过程中调用方法并告诉它打开菜单?如果应用程序实例已在运行,请调用已运行实例中的方法

我找到this有趣的文章,它是指this的文章。两者都有一些非常有前途的代码,用于如何基本实现我想要的功能。但是,他们的代码覆盖了WndProc方法,而我所知甚少。当我使用他们的代码时,我得到了“找不到合适的方法覆盖”的错误,我收集的是因为我的notifyIcon和上下文菜单的主代码没有实际的形式,并且从我对here的有限理解中,WndProc是一种实际形式的方法。

我是否了解他们的解决方案和我得到正确的错误?如果不是,请解释一下,我很高兴学习。如果我理解,那么有没有办法做到这一点,让我只需触发一个notifyIcon的上下文菜单,而不必拥有一个实际的表单?

注意:为了记录,我的program.cs遵循提供的第二个链接中的确切格式。

如前所述,我Program.cs是几乎等同于一个在第二个环节,但在这里它只是要清楚:

using System; 
using System.Threading; 
using System.Windows.Forms; 

namespace Context_Menu 
{ 
    static class Program 
    { 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 

     static Mutex mutex = new Mutex(true, "{41264ee37e7688d64250ffb50dc681d2}"); 

     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 

      if (mutex.WaitOne(TimeSpan.Zero, true)) 
      { 
       Application.Run(new PCMLnotifyIcon()); 
       mutex.ReleaseMutex(); 
      } 
      else 
      { 
       // send our Win32 message to make the currently running instance 
       // jump on top of all the other windows 
       NativeMethods.PostMessage(
        (IntPtr)NativeMethods.HWND_BROADCAST, 
        NativeMethods.WM_SHOWME, 
        IntPtr.Zero, 
        IntPtr.Zero); 
      } 
     } 
    } 
} 

我NativeMethods类是等同于一个在链接的还有,像这样:

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

最后,PCMLNotifyIcon在很大程度上基于this指导,因此仅仅是没有伴随形式的NotifyIcon。下面有一个代码段示出其中I下降从所述第二链路的代码:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Reflection; 
using System.Windows.Forms; 

namespace Context_Menu 
{ 
    class PCMLnotifyIcon : ApplicationContext 
    { 
     private NotifyIcon niIcon; 
     private ContextMenuStrip cmsMenu; 
     private ToolStripMenuItem tsmiUpdate; 
     private ToolStripSeparator tssOne; 
     private ToolStripMenuItem tsmiQuickAdd; 
     private ToolStripSeparator tssTwo; 
     private ToolStripSeparator tssThree; 
     private ToolStripMenuItem tsmiSettings; 
     private ToolStripMenuItem tsmiAbout; 
     private ToolStripMenuItem tsmiFeedback; 
     private ToolStripMenuItem tsmiExit; 

     public PCMLnotifyIcon() 
     { 
      InitializeComponent(); 
     } 
     protected override void WndProc(ref Message m) 
     { 
      if (m.Msg == NativeMethods.WM_SHOWME) 
      { 
       ShowMe(); 
      } 
      base.WndProc(ref m); 
     } 

而给出的误差,如上面提到我怀疑是因为缺少一种形式:错误1

“Context_Menu .PCMLnotifyIcon.WndProc(REF System.Windows.Forms.Message)“:发现覆盖

+0

选择IPC。 _“我得到了错误”_ - 请发布您的代码。请参阅[mcve] – MickyD

+0

_“因为我的notifyIcon和上下文菜单的主代码没有实际的形式” - 您是否使用NotifyIcon而不嵌入“Form”中? – MickyD

+0

我的确如此。我正在使用此处详述的方法。 http://www.codeproject.com/Tips/627796/Doing-a-NotifyIcon-program-the-right-way-way- 原因是程序在启动时不需要表单。只是notifyIcon及其菜单。 – ms4sman

回答

1

我会提供一些代码,但我真的不知道你想实现什么没有合适的方法。相反,我会看看我是否可以指引你在正确的方向:)我已经在非常相似的情况下使用了一个IPC频道,取得了巨大的成功。但是,似乎这已经被赞成WCF弃用了。尽管如此,它看起来并不算太坏。您可以使用命名管道代替TCP,它应该非常高效。我认为你会发现这比窗口消息更可靠,它充其量是笨重的。您可以轻而易举地传递相当大且复杂的有效载荷。

看看这篇文章:https://gorillacoding.wordpress.com/2013/02/03/using-wcf-for-inter-process-communication/

这里是你可能会发现有用的另一个例子:http://adndevblog.typepad.com/cloud_and_mobile/2013/12/inter-process-communication-using-wcf.html

编辑:作为奖励,你可以放弃互斥赞成测试为的存在命名管道

+0

啊是的_.NET Remoting_。我同意作为一个直接的通信选择(即使是本地计算机),它已被弃用。尽管对于在沙盒插件系统中与子AppDomain进行通信,但是我离题了,但是对于这一天是有用的。顺便说一下,“IPC”只是指一个程序与另一个程序交谈的特征。它实际上并不涉及任何特定的运输;技术或协议。 .NET Remoting _是一个IPC_但它不是IPC_。 – MickyD

+0

_“我不确定MSMQ在哪里进入图片”_ - 哦,不,这是我的坏处。我看到_“比窗口消息”_并认为MSMQ。我现在看到OP在Windows消息泵上发布消息。对不起,好友 – MickyD

+0

是的,我可能已经更具体的重新IPC,这就是我所引用的:https://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.ipc.ipcchannel .aspx –

0

我讨厌翻转范例,但为什么你不选择使用管道之类的东西?恕我直言,这样做会容易得多。继续讨论手头的主要问题:在ShowMe();之后,输入return。像这样:

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == NativeMethods.WM_SHOWME) 
    { 
     ShowMe(); 
     return; // <-- right here! 
    } 
    base.WndProc(ref m); 
} 

HTH!

+0

感谢您的建议,但我不确定我明白这会有所帮助。但是,我试了一下,但我仍然遇到了WndProc的问题,实际上它并不是ApplicationContext的一个方法,而这正是我的类从中派生出来的。我认为这种方法仅适用于具有实际表单的情况。除非我在这里误解你。 – ms4sman

相关问题