65.9K
CodeProject 正在变化。 阅读更多。
Home

TaskbarNotifier,一个可自定义皮肤的类似 MSN Messenger 的弹出窗口,支持 C# 和 VB.NET

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (402投票s)

2002年12月2日

4分钟阅读

viewsIcon

2890207

downloadIcon

68483

TaskbarNotifier 类允许显示一个类似 MSN Messenger 的带自定义皮肤背景的动画弹出窗口

引言

由于我正在学习 C#,我认为将我之前用 C++ 编写的 CTaskbarNotifier 类移植过来会很有帮助(https://codeproject.org.cn/dialog/TaskbarNotifier.asp[^])。

因此,我编写了一个类似 MSN Messenger 的可自定义皮肤的弹出窗口,带有一个关闭按钮,外观几乎与微软的类似(带有相应的皮肤)。

TaskbarNotifier 类继承自 System.Windows.Forms.Form 并为其添加了一些方法。

特点

类似 MSN Messenger 的弹出窗口支持:

  • 自定义透明位图背景
  • 可自定义皮肤的 3 状态关闭按钮
  • 可点击的标题文本
  • 可点击的内容文本
  • 选择框
  • 文本不同状态(正常/悬停)下的自定义字体和颜色
  • 动画速度参数

兼容性

此类是独立的,除了 .NET 的默认库外,不需要任何特殊的库。它在托管代码中运行,因此应该是可移植的。

如何使用该类

  • 首先,将 TaskbarNotifier.cs 复制到您的项目目录中。
  • 在您的源代码顶部添加指令
    using CustomUIControls;
  • 在您的类中添加一个成员变量
    TaskbarNotifier taskbarNotifier;
  • 在您的构造函数中,添加以下几行
    taskbarNotifier=new TaskbarNotifier();
    taskbarNotifier.SetBackgroundBitmap("skin.bmp",
                        Color.FromArgb(255,0,255));
    taskbarNotifier.SetCloseBitmap("close.bmp",
            Color.FromArgb(255,0,255),new Point(127,8));
    taskbarNotifier.TitleRectangle=new Rectangle(40,9,70,25);
    taskbarNotifier.ContentRectangle=new Rectangle(8,41,133,68);
    taskbarNotifier.TitleClick+=new EventHandler(TitleClick);
    taskbarNotifier.ContentClick+=new EventHandler(ContentClick);
    taskbarNotifier.CloseClick+=new EventHandler(CloseClick);

详细说明

taskbarNotifier.SetBackgroundBitmap("skin.bmp",
                    Color.FromArgb(255,0,255));
taskbarNotifier.SetCloseBitmap("close.bmp",
    Color.FromArgb(255,0,255),new Point(127,8));

第一行设置背景位图皮肤和透明色(必须存在),第二行设置 3 状态关闭按钮及其透明色和在窗口上的位置(如果您不需要关闭按钮,此行是可选的)。

taskbarNotifier.TitleRectangle=new Rectangle(40,9,70,25);
taskbarNotifier.ContentRectangle=new Rectangle(8,41,133,68);

这两行允许我们定义标题和内容文本将显示的矩形区域。

taskbarNotifier.TitleClick+=new EventHandler(OnTitleClick);
taskbarNotifier.ContentClick+=new EventHandler(OnContentClick);
taskbarNotifier.CloseClick+=new EventHandler(OnCloseClick);

这三行允许我们捕获弹出窗口上的事件,例如标题/内容或关闭按钮被点击

  • 然后我们就完成了,只需要调用
    taskbarNotifier.Show("TitleText","ContentText",500,3000,500);

    这将以 500 毫秒/3000 毫秒/500 毫秒的显示/可见/隐藏动画时间显示弹出窗口动画。

您可以调整一些属性

  • 标题、内容字体和颜色
  • 标题/内容/关闭按钮的可点击性
  • 您可以禁用焦点矩形
  • ...(更多细节请参见下文)

类文档

方法

void Show(string strTitle, string strContent, int nTimeToShow, 
                                            int nTimeToStay, int nTimeToHide)

显示弹出窗口一段时间。

参数

  • strTitle:将显示为弹出窗口标题的 string
  • strContent:将显示为弹出窗口内容的 string
  • nTimeToShow:显示动画的持续时间(以毫秒为单位)
  • nTimeToStay:可见状态的持续时间(在折叠之前)(以毫秒为单位)
  • nTimeToHide:隐藏动画的持续时间(以毫秒为单位)
void Hide()

强制弹出窗口隐藏。

void SetBackgroundBitmap(string strFilename, Color transparencyColor)

设置背景位图及其透明色。

参数

  • strFilename:磁盘上背景位图的路径
  • transparencyColor:位图中不可见的颜色
void SetBackgroundBitmap(Image image, Color transparencyColor)

设置背景位图及其透明色。

参数

  • image:背景位图
  • transparencyColor:位图中不可见的 Color
void SetCloseBitmap(string strFilename, 
            Color transparencyColor, Point position)

设置 3 状态关闭按钮位图、其透明色和坐标。

参数

  • strFilename:磁盘上 3 状态关闭按钮位图的路径(宽度必须是 3 的倍数)
  • transparencyColor:位图中不可见的颜色
  • position:关闭按钮在弹出窗口上的位置
void SetCloseBitmap(Image image, Color transparencyColor, Point position)

设置 3 状态关闭按钮位图、其透明色和坐标。

参数

  • image:表示 3 状态关闭按钮位图的 Image/Bitmap 对象(宽度必须是 3 的倍数)
  • transparencyColor:位图中不可见的 Color
  • position:关闭按钮在弹出窗口上的位置

属性

string TitleText (get/set)
string ContentText (get/set)
TaskbarStates TaskbarState (get)
Color NormalTitleColor (get/set)
Color HoverTitleColor (get/set)
Color NormalContentColor (get/set)
Color HoverContentColor (get/set)
Font NormalTitleFont (get/set)
Font HoverTitleFont (get/set)
Font NormalContentFont (get/set)
Font HoverContentFont (get/set)
Rectangle TitleRectangle (get/set) //must be defined before calling show())
Rectangle ContentRectangle (get/set) //must be defined before calling show())
bool TitleClickable (get/set) (default = false);
bool ContentClickable (get/set) (default = true);
bool CloseClickable (get/set) (default = true);
bool EnableSelectionRectangle (get/set) (default = true);

事件

event EventHandler CloseClick
event EventHandler TitleClick
event EventHandler ContentClick

技术问题

弹出窗口使用从位图和透明色动态生成的区域进行皮肤定制

protected 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;
}

弹出窗口的 refresh() 使用双缓冲技术实现,以避免闪烁

protected override void OnPaintBackground(PaintEventArgs pea)
{
    Graphics grfx = pea.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);
    }

    DrawCloseButton(offScreenGraphics);
    DrawText(offScreenGraphics);

    grfx.DrawImage(offscreenBitmap, 0, 0);
}

Bug/局限性

由于我想只保留托管代码,我使用了 Screen.GetWorkingArea(WorkAreaRectangle) 函数,而不是使用非托管代码来获取任务栏位置。因此,我将弹出窗口始终显示在 WorkAreaRectangle 的底部,而不管任务栏位于何处。

我没有找到任何 C# 托管等效的 Win32 函数 ShowWindow(SW_SHOWNOACTIVATE) 来使弹出窗口不抢占活动窗口的焦点。

更新

  • 2003 年 4 月 1 日:OnMouseUp 处理程序中的一个小 bug 修复
  • 2003 年 1 月 11 日:Patrick Vanden Driessche 更新了 C# 和 VB.NET 版本
    • 当鼠标仍在上方时,弹出窗口现在不会自动关闭
    • 当弹出窗口正在消失且鼠标移到它上面时,它会重新显示
    • 其他一些 bug 已得到纠正
  • 2003 年 1 月 10 日:Patrick Vanden Driessche 将 TaskbarNotifier 移植到了 VB.NET
  • 2002 年 12 月 5 日:现在使用 Win32 函数 ShowWindow(SW_SHOWNOACTIVATE) 显示弹出窗口,以防止弹出窗口抢占焦点。

结论

希望这段代码对您有所帮助。如果您有关于增强此类功能的建议,请发表评论。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.