利用 C# 实现任务栏通知窗口

来源:ChinaItLab  作者:佚名
利用 C# 实现任务栏通知窗口
摘要:想必大部分网友都使用过QQ、MSN等聊天程序,它们的界面都相当华丽,尤其是当网友上线以及消息提示时会有一个浮动的窗体从屏幕的右下方缓慢升起,既美观又人性化,作为程序员在享受的同时我们也不禁要问:这到底是怎么实现的呢?本文就利用VisualStudio.NetC…

  CurrentState变量表示窗体的状态是显示中、停留中还是隐藏中,两个计时器根据窗体不同状态对窗体的位置进行更改,我们会使用SetBounds来执行该操作:

this.SetBounds(WorkAreaRectangle.Width - this.Width, WorkAreaRectangle.Height - currentTop, this.Width, this.Height);

当窗体需要升起时将窗体的Top属性值不断减少,而窗体回落时将Top属性值增加并超过屏幕的高度窗体就消失了,虽然原理很简单但仍需精确控制。

SetBackgroundBitmap函数首先将窗体背景图像保存到BackgroundBitmap变量中,然后根据该位图图像轮廓和透明色创建Region,BitmapToRegion就用于完成Bitmap到Region的转换,程序再将这个Region付值给窗体的Region属性以完成不规则窗体的创建。

public void SetBackgroundBitmap(Image image, Color transparencyColor)
               {
               BackgroundBitmap = new Bitmap(image);
               Width = BackgroundBitmap.Width; 
   Height = BackgroundBitmap.Height;    Region = BitmapToRegion(BackgroundBitmap, transparencyColor);    }   
   public Region BitmapToRegion(Bitmap bitmap, Color transparencyColor)    {
   if (bitmap == null)    throw new ArgumentNullException("Bitmap", "Bitmap cannot be null!");    int height = bitmap.Height;    int width = bitmap.Width;    GraphicsPath path = new GraphicsPath();    for (int j = 0; j < height; j++)    for (int i = 0; i < width; i++)    {    if (bitmap.GetPixel(i, j) == transparencyColor)    continue;    int x0 = i;    while ((i < width) && (bitmap.GetPixel(i, j) != transparencyColor))    i++;    path.AddRectangle(new Rectangle(x0, j, i - x0, 1));
   }    Region region = new Region(path);    path.Dispose();    return region; }

通知窗体背景以及文字的绘制在重载的OnPaintBackground方法中完成,而且利用了双重缓冲区技术来进行绘制操作,代码如下:

protected override void OnPaintBackground(PaintEventArgs e)
               {
               Graphics grfx = e.Graphics;
               grfx.PageUnit = GraphicsUnit.Pixel;
               Graphics offScreenGraphics;
               Bitmap offscreenBitmap;
               offscreenBitmap = new Bitmap(BackgroundBitmap.Width,
            BackgroundBitmap.Height);
               offScreenGraphics = Graphics.FromImage(offscreenBitmap);
               if (BackgroundBitmap != null)
               {
               offScreenGraphics.DrawImage(BackgroundBitmap, 0, 0,
            BackgroundBitmap.Width,
BackgroundBitmap.Height);
   }
   DrawText(offScreenGraphics);    grfx.DrawImage(offscreenBitmap, 0, 0);    }

上述代码首先返回窗体绘制表面的Graphics并保存在变量grfx中,然后创建一个内存Graphics对象offScreenGraphics和内存位图对象offscreenBitmap,将内存位图对象的引用付值给offScreenGraphics,这样所有对offScreenGraphics的绘制操作也都同时作用于offscreenBitmap,这时就将需要绘制到通知窗体表面的背景图像BackgroundBitmap绘制到内存的Graphics对象上,DrawText函数根据需要显示文字的大小和范围调用Graphics.DrawString将文字显示在窗体的特定区域。最后,调用Graphics.DrawImage将内存中已经绘制完成的图像显示到通知窗体表面。

我们还需要捕获窗体的鼠标操作,有三个操作在这里进行,1、处理拖动窗体操作,2、处理通知窗体的关闭操作,3、内容区域的单击操作。三个操作都需要检测鼠标的当前位置与每个Rectangle区域的包含关系,只要单击落在特定区域我们就进行相应的处理,代码如下:

 private void TaskbarForm_MouseDown(object sender, MouseEventArgs e)
               { 
   if (e.Button == MouseButtons.Left)    {    if (TitlebarRectangle.Contains(e.Location)) //单击标题栏时拖动    {
   ReleaseCapture(); //释放鼠标捕捉    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0); //发送左键点击的消息至该窗体(标题栏)    }    if (CloseBtnRectangle.Contains(e.Location)) //单击Close按钮关闭    {
   this.Hide();    currentTop = 1;    }    if (ContentRectangle.Contains(e.Location )) //单击内容区域    {
   System.Diagnostics.Process.Start("http://www.Rithia.com");    }
   }   }

结论

该程序可以很好的进行通知窗体的显示、停留和隐藏操作,并且具备简单的换肤机制,在利用了双重缓冲区绘图技术后,可以保证窗体的绘制平滑且没有闪烁。

【相关文章】好搜一下
浅谈Visual Studio中如何选择本地项目与WEB项目

浅谈Visual Studio中如何选择本地

一般在软件开发中可以选择本地项目模型或者WEB项目模型。在Visual Stud…