Как я могу показать всплывающую подсказку длиной более 63 символов? - PullRequest
17 голосов
/ 24 февраля 2009

Как я могу показать всплывающую подсказку длиной более 63 символов? NotifyIcon.Text имеет ограничение в 63 символа, но я видел, что VNC Server имеет более длинную подсказку.

Как я могу делать то, что делает VNC Server?

Ответы [ 5 ]

28 голосов
/ 24 февраля 2009

На самом деле, это ошибка в установщике свойства Text. В объявлении P / Invoke для NOTIFYICONDATA в Windows Forms используется ограничение в 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 });
      }
    }
8 голосов
/ 24 февраля 2009

Из документации MSDN по структуре Win32 NOTIFYICONDATA :

szTip

Строка с нулевым символом в конце, указывающая текст для стандарта ToolTip. Может иметь максимум 64 символы, включая завершающие нулевой символ.

Для Windows 2000 (Shell32.dll версия 5.0) и более поздних версий szTip может иметь максимум 128 символов, в том числе завершающий нулевой символ.

Похоже, библиотека Windows Forms поддерживает здесь самый низкий общий знаменатель.

1 голос
/ 12 марта 2013

Недавно я столкнулся с подобной проблемой. Вместо того, чтобы взламывать серверную часть, я реализовал обходной путь, который использует 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: Скриншот всплывающей подсказки с довольно большим текстом, который использует это решение, можно увидеть в блоге .

1 голос
/ 24 февраля 2009

Расширение на правильный ответ bk1e.

Под капотом значок в системном трее в WinForms реализован как значок уведомления Win32. Поэтому версия winforms имеет все ограничения как родная. Ограничение размера всплывающей подсказки - только один пример.

0 голосов
/ 24 февраля 2009

bk1e здесь говорит, что ограничение составляет 128 символов, теперь, если вы используете UTF-16, который является родным форматом Unicode в Windows и особенно .NET, это означает, что вы ограничены 64 символами , в том числе NUL.

Я полагаю, что вы используете API-интерфейс Unicode, который ограничивает всплывающие подсказки до 64 16-битных символов (включая ноль), и что вместо этого VNC Server использует API-интерфейсы ascii (или ANSI), что позволяет использовать 128 8-битных символы (включая ноль).

РЕДАКТИРОВАТЬ: Этот ответ неправильный, вот полезный комментарий Коди Грей, объясняющий, почему:

Это рассуждение убедительно, но на самом деле не правильно. Когда в документации MSDN говорится о «символах», это на самом деле означает количество символов char или wchar_t в массиве (в зависимости от того, нацеливаетесь ли вы на Unicode). Таким образом, вы получите обещанные полные 128 символов при работе в Windows 2000+. Windows 9x была ограничена до 64 символов. - Коди Грей 19 июня в 4:11 "

...