【发布时间】:2016-02-18 00:16:32
【问题描述】:
我有一个由系统托盘 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。这是一个 sn-p,显示了我从第二个链接中删除代码的位置:
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(参考 System.Windows.Forms.Message)': 找不到合适的方法来覆盖
【问题讨论】:
-
选择 IPC。 “我收到了错误” - 请发布您的代码。见minimal reproducible example
-
“因为我的 notifyIcon 和上下文菜单的主要代码没有实际的形式” - 您是否使用
NotifyIcon而不将其嵌入到Form中? -
我确实是。我正在使用这里详述的方法。 codeproject.com/Tips/627796/… 原因是程序启动时不需要表单。只是 notifyIcon 及其菜单。
-
我用要显示的代码更新了问题。就像我在原始问题中提到的那样,代码与第二个链接几乎没有变化,问题似乎在于我没有实际的形式。所以我假设这意味着我需要找到一种完全不同的方法来解决这个问题?