如何显示长度超过 63 个字符的系统托盘工具提示?

发布于 2024-07-14 05:47:07 字数 124 浏览 4 评论 0原文

如何显示长度超过 63 个字符的系统托盘工具提示? NotifyIcon.Text 有 63 个字符的限制,但我发现 VNC Server 有更长的工具提示。

我怎样才能完成 VNC Server 所做的事情?

How can I show a systray tooltip longer than 63 chars? NotifyIcon.Text has a 63 chars limit, but I've seen that VNC Server has a longer tooltip.

How can I do what VNC Server does?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

黎歌 2024-07-21 05:47:07

实际上,这是 Text 属性的属性设置器中的一个错误。 Windows 窗体内 NOTIFYICONDATA 的 P/Invoke 声明使用 128 个字符的限制。 你可以用 Reflection 来破解它:

using System;
using System.Windows.Forms;
using System.Reflection;

    public class Fixes {
      public static void SetNotifyIconText(NotifyIcon ni, string text) {
        if (text.Length >= 128) throw new ArgumentOutOfRangeException("Text limited to 127 characters");
        Type t = typeof(NotifyIcon);
        BindingFlags hidden = BindingFlags.NonPublic | BindingFlags.Instance;
        t.GetField("text", hidden).SetValue(ni, text);
        if ((bool)t.GetField("added", hidden).GetValue(ni))
          t.GetMethod("UpdateIcon", hidden).Invoke(ni, new object[] { true });
      }
    }

Actually, it is a bug in the property setter for the Text property. The P/Invoke declaration for NOTIFYICONDATA inside Windows Forms uses the 128 char limit. You can hack around it with Reflection:

using System;
using System.Windows.Forms;
using System.Reflection;

    public class Fixes {
      public static void SetNotifyIconText(NotifyIcon ni, string text) {
        if (text.Length >= 128) throw new ArgumentOutOfRangeException("Text limited to 127 characters");
        Type t = typeof(NotifyIcon);
        BindingFlags hidden = BindingFlags.NonPublic | BindingFlags.Instance;
        t.GetField("text", hidden).SetValue(ni, text);
        if ((bool)t.GetField("added", hidden).GetValue(ni))
          t.GetMethod("UpdateIcon", hidden).Invoke(ni, new object[] { true });
      }
    }
计㈡愣 2024-07-21 05:47:07

来自 Win32 NOTIFYICONDATA 结构 的 MSDN 文档:

sz提示

指定标准文本的以 null 结尾的字符串
工具提示。 最多可以有 64 个
字符,包括终止符
空字符。

对于 Windows 2000(Shell32.dll 版本 5.0)及更高版本,szTip 可以具有
最多 128 个字符,包括
终止空字符。

看起来 Windows 窗体库支持这里的最低公分母。

From the MSDN documentation on the Win32 NOTIFYICONDATA structure:

szTip

A null-terminated string that specifies the text for a standard
ToolTip. It can have a maximum of 64
characters, including the terminating
null character.

For Windows 2000 (Shell32.dll version 5.0) and later, szTip can have
a maximum of 128 characters, including
the terminating null character.

It looks like the Windows Forms library supports the lowest common denominator here.

吃不饱 2024-07-21 05:47:07

扩展 bk1e 的正确答案。

在底层,WinForms 中的系统托盘图标被实现为 Win32 通知图标。 因此,winforms 版本具有与本机版本一样的所有限制。 工具提示大小限制只是一个示例。

Expanding on bk1e's correct answer.

Under the hood, a system tray icon in WinForms is implemented as a Win32 Notify Icon. Therefore the winforms version has all of the limitations as the native one. The tooltip size limitation is just one example.

半岛未凉 2024-07-21 05:47:07

我最近遇到了类似的问题。 我没有侵入后端,而是实现了一种解决方法,它利用了 BalloonTipText,它可以容纳相当多的字符。

工具提示显示在托盘图标上的第一个 MouseMove 事件上,并且工具提示显示 2 秒。 工具提示关闭后,可以通过新的 MouseMove 事件重新打开。

此解决方案的唯一缺点是,当用户离开图标区域时,无法以编程方式关闭气球,因此它只会在超时后或用户单击小 X 按钮时消失。

请注意,标题和文本可以随时在程序中的其他位置设置。 它们设置在事件中仅用于演示目的。

编辑: ShowBalloonTip() 会触发附加的级联 MouseMove 事件,因此有必要禁用此事件,直到隐藏气球工具提示为止。 此外,BalloonTipClosed 是(根据 文档)仅在用户主动单击“X”时触发,尽管我观察到它是在工具提示超时后关闭时触发的。 因此,我添加了一个辅助计时器来重置状态,而不是依赖 BalloonTipClosed 事件。 修改和测试的代码如下:

    private bool balloonTipShown;
    private Timer balloonTimer;
    private void trayIcon_MouseMove(object sender, MouseEventArgs e)
    {
        if (balloonTipShown)
        {
            return;
        }
        balloonTipShown = true;
        trayIcon.MouseMove -= trayIcon_MouseMove;
        balloonTimer = new Timer();
        balloonTimer.Tick += balloonTimer_Tick;
        balloonTimer.Interval = 2005;
        balloonTimer.Start();
        trayIcon.ShowBalloonTip(2000);
    }

    void balloonTimer_Tick(object sender, EventArgs e)
    {
        balloonTipShown = false;
        balloonTimer.Stop();
        balloonTimer.Dispose();
        trayIcon.MouseMove += trayIcon_MouseMove;
    }

编辑 2:使用此解决方案的带有大量文本的气球工具提示的屏幕截图可以是 通过博客看到

I recently came across a similar problem. Rather than hacking the back-end, I implemented a work-around, which makes use of the BalloonTipText, which can accommodate quite a lot of characters.

The tooltip is shown on the first MouseMove event over the tray icon and the tooltip is displayed for 2 seconds. Atter the tooltip is closed, it can be re-opened again by a new MouseMove event.

The only downside with this solution is that is is not possible to close the balloon programatically, when a user, say, leaves the icon area, so it only disappears after a timeout or if the user clicks on the small X-button.

Note that the title and the text can be set at any time elsewhere in the program. They are set here in the event for demonstration purpose only.

EDIT: ShowBalloonTip() fires addition cascading MouseMove events, so it is necessary to disable this event until such time as the balloon tooltip is hidden. Additionally, BalloonTipClosed is (according to the documentation) only fired when the user actively clicks on 'X', though I observed it being fired when the tooltip closed after a timeout. I therefore added a helper timer to reset the sate, instead of relying on the BalloonTipClosed event. The revised and tested code is below:

    private bool balloonTipShown;
    private Timer balloonTimer;
    private void trayIcon_MouseMove(object sender, MouseEventArgs e)
    {
        if (balloonTipShown)
        {
            return;
        }
        balloonTipShown = true;
        trayIcon.MouseMove -= trayIcon_MouseMove;
        balloonTimer = new Timer();
        balloonTimer.Tick += balloonTimer_Tick;
        balloonTimer.Interval = 2005;
        balloonTimer.Start();
        trayIcon.ShowBalloonTip(2000);
    }

    void balloonTimer_Tick(object sender, EventArgs e)
    {
        balloonTipShown = false;
        balloonTimer.Stop();
        balloonTimer.Dispose();
        trayIcon.MouseMove += trayIcon_MouseMove;
    }

EDIT 2: A screenshot of a balloon tooltip with quite a lot of text, that utilises this solution can be seen in by blog.

音盲 2024-07-21 05:47:07

bk1e 这里说限制是 128 个字符,现在,如果您使用 UTF-16(Windows 中的本机 unicode 格式,尤其是 .NET),这意味着您只能使用 64 个字符,包括空。

我相信您使用的是 unicode API,它将工具提示限制为 64 个 16 位字符(包括 null),并且 VNC 服务器使用 ascii(或 ANSI)api,允许使用 128 个 8 位字符(包括空)。

编辑:这个答案是错误的,这是科迪·格雷的有用评论,解释了原因:

这个推理很有说服力,但实际上并不正确。 当 MSDN 文档谈论“字符”时,它实际上指的是数组中 char 或 wchar_t 项的数量(取决于您是否针对 Unicode)。 因此,在 Windows 2000+ 上运行时,您将获得承诺的完整 128 个字符。 Windows 9x 限制为 64 个字符。 – Cody Gray 6 月 19 日 4:11"

bk1e here says that the limit is 128 chars, now, if you use UTF-16, which is the native unicode format in windows and especially .NET, that means you are limited to 64 characters, including the NUL.

I would believe that you're using a unicode API which limits tooltips to 64 16-bit characters (including the null), and that VNC Server uses ascii (or ANSI) api's instead, allowing the use of 128 8-bit characters (including the null).

EDIT: This answer is wrong, here is a helpful comment by Cody Gray explaining why:

This reasoning is compelling, but is not actually correct. When the MSDN documentation talks about "characters", it actually means the number of char or wchar_t items in the array (depending on whether you're targeting Unicode). So you get the full 128 characters promised when running on Windows 2000+. Windows 9x was limited to 64 characters. – Cody Gray Jun 19 at 4:11"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文