2016-02-18 71 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

相關問題