关于 .NET ToolTip/BalloonTip 的不同实现方式






1.22/5 (9投票s)
如何使用标准的 .NET Form 实现 .NET ToolTip/BalloonTip。
引言
标准的 NotificationIcon ToolTip 宽度仅为 64 个字符,而 BalloonTip
使用起来过于突兀且不够灵活。 我编写了自己的工具提示版本,它能显示更多文本,并且易于使用且不显眼。
背景
这段代码使用了标准的 WinForms 控件和技术。 我查阅了一些资料,发现了一些使用 PInvoke 等方法实现的复杂版本。 因此,我创建了这种更简单(至少对我来说)的方式来实现我想要的功能。
以下是在鼠标悬停在图标上时显示的位图
Using the Code
这段代码只是一个方法(InfoTip
)和一些事件处理程序。 您会注意到它使用起来很简单,希望它能给您一些进一步开发的思路。 它可以肯定地扩展为包含其他控件和功能。 我还应该提到,这是我的第一篇文章,请原谅我可能遗漏了任何文章规范。
//the InfoTip method takes in a whole seconds int value
private void InfoTip(int theTimeOut)
{
//we want the current position so we can calculate where the
//info tip will be displayed relative to the NotificationIcon
Point aXY = Cursor.Position;
//create a new form for housing the text label
_InfoTipForm = new Form();
//register load and formclosing event so that
//we can control interaction with context menu
_InfoTipForm.FormClosing +=
new FormClosingEventHandler(_InfoTipForm_FormClosing);
_InfoTipForm.Load += new EventHandler(_InfoTipForm_Load);
//set up the form's attributes to mimic standard ToolTip look and feel
_InfoTipForm.FormBorderStyle = FormBorderStyle.None;
_InfoTipForm.BackColor = Color.Cornsilk;
_InfoTipForm.ControlBox = false;
_InfoTipForm.MaximizeBox = false;
_InfoTipForm.MinimizeBox = false;
_InfoTipForm.Width = 0; //these two prop settings prevent flashing
_InfoTipForm.Height = 0; //when the form draws itself
_InfoTipForm.TopMost = true;
_InfoTipForm.ShowInTaskbar = false;
_InfoTipForm.Visible = true;
//this is the label that will display the Tip's text
//this is what allows us to go beyond
//the 64 char limit of the standard tooltip
//but you can also make this be any container type
//of control to hold an image, rich text, etc...
Label aInfoTip = new Label();
//format to mimic ToolTip look and feel
aInfoTip.BackColor = Color.Cornsilk;
aInfoTip.ForeColor = Color.Black;
aInfoTip.Font = new Font("Arial", 9, FontStyle.Regular);
aInfoTip.AutoSize = true;
aInfoTip.Location = new Point(0, 0);
aInfoTip.TextAlign = ContentAlignment.MiddleLeft;
aInfoTip.Visible = true;
//for my application I assign the text
//on a global but you can pass it in.
aInfoTip.Text = _NotifyText;
aInfoTip.Refresh();//forces control to redraw
//now we add the label to the form and
//set the form size to the label size
_InfoTipForm.Controls.Add(aInfoTip);
_InfoTipForm.Width = aInfoTip.Width;
_InfoTipForm.Height = aInfoTip.Height;
//keep the form within the screen viewing area and above the icon
if(Screen.PrimaryScreen.Bounds.Width - aXY.X < _InfoTipForm.Width)
_InfoTipForm.DesktopLocation =
new Point(aXY.X - _InfoTipForm.Width, aXY.Y - 34);
else
_InfoTipForm.DesktopLocation = new Point(aXY.X, aXY.Y - 34);
//force form to refresh
_InfoTipForm.Refresh();
_InfoTipForm.Show();
//global manualresetevent that waits the timeout period,
//used to close the tip before timeout ends
_TipWait.WaitOne(theTimeOut * 1000, false);
//close the form when done waiting
_InfoTipForm.Close();
//reset the signaller so it's ready the next time our tip shows
_TipWait.Reset();
}
///////////////////////////////////////////////////////////////////////////
//the info tip form global
Form _InfoTipForm;
//control the showing of the tip
bool _isCanShowInfoTip=true;
//wait signaller
ManualResetEvent _TipWait=new ManualResetEvent();
//when the infottip form loads set the show controller boolean to false
private void _InfoTipForm_Load(object sender, EventArgs e)
{
_isCanShowInfoTip = false;
}//_InfoTipForm_Load
//when the tip form closes then we can show the tip again
private void _InfoTipForm_FormClosing(object sender, FormClosingEventArgs e)
{
_isCanShowInfoTip = true;
}//_InfoTipForm_FormClosing
//contextmenu and infotip are mutually exclusive,
//so when context menu shows, infotip closes
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
_isCanShowInfoTip = false;
//tell the signaller to stop blocking and continue
//so the tip can close before the timeout period
_TipWait.Set();
}//contextMenuStrip1_Opening
//show the infotip on mousemove (simulates hover)
//this is the InfoTip's entry point
private void notifyIcon1_MouseMove(object sender, MouseEventArgs e)
{
//if we can show the tip and there's
//no contextmenu showing then create the infotip
if(_isCanShowInfoTip && !contextMenuStrip1.Visible)
InfoTip(3);//timeout of three seconds
}//notifyIcon1_MouseMove
关注点
这只是一个简单的实现,满足我自己的需求,但您可以肯定地以此为基础进行扩展,并使其更加健壮以满足您的需求。