Как я могу показать всплывающую подсказку длиной более 63 символов?
Как я могу показать всплывающую подсказку длиной более 63 символов? NotifyIcon.Text имеет ограничение в 63 символа, но я видел, что VNC Server имеет более длинную подсказку.
Как я могу сделать то, что делает VNC Server?
5 ответов
На самом деле, это ошибка в установщике свойства 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 });
}
}
Из документации MSDN по структуре Win32 NOTIFYICONDATA:
szTip
Строка с нулевым символом в конце, указывающая текст для стандартной всплывающей подсказки. Он может содержать не более 64 символов, включая завершающий нулевой символ.
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.
Расширение на правильный ответ bk1e.
Под капотом иконка в системном трее в WinForms реализована как иконка уведомлений Win32. Поэтому версия winforms имеет все ограничения как родная. Ограничение размера подсказки является лишь одним примером.
Недавно я столкнулся с похожей проблемой. Вместо того, чтобы взламывать серверную часть, я реализовал обходной путь, который использует 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: Скриншот всплывающей подсказки с довольно большим текстом, который использует это решение, можно увидеть в блоге.
Здесь 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"