摘自:http://www.cnblogs.com/risen/archive/2008/01/15/1039751.html

public partial class AlertForm : Form
    {
        /*
         * 在类AlertForm定义的下方,
         * 我们创建用于显示的字符串和其颜色的变量,
         * 再定义几个Rectangle对象的变量用于放置标题、
         * 提示内容以及可以拖动窗体的区域和关闭按钮的区域。
         * 然后,我们需要保存窗体在浮动时的高度以便计算移动后的新高度,
         * intervalValue变量用来确定窗体显示和隐藏的速度。
         * 进行平台调用时我们需要提前定义好常量的值用来传递给函数,
         * WM_NCLBUTTONDOWN和HT_CAPTION常量用于拖动窗体,
         * 他们的值都保存在WinUser.h头文件中,
         * 所对应的动态链接库名为:user32.dll。
         * 我们用到的Win32API为:SendMessage、ReleaseCapture和ShowWindow,
         * 通过使用DllImportAttribute可以导入相应的函数并在程序中重新进行定义,如下:
         */
        public Bitmap BackgroundBitmap = null;

private string titleText;
        private string contentText;
        private Color normalTitleColor = Color.FromArgb(0, 0, 0);
        private Font normalTitleFont = new Font("宋体", 12, FontStyle.Regular, GraphicsUnit.Pixel);
        private Color normalContentColor = Color.FromArgb(0, 0, 0);
        private Font normalContentFont = new Font("宋体", 12, FontStyle.Regular, GraphicsUnit.Pixel);

public Rectangle TitleRectangle;
        public Rectangle TitlebarRectangle;
        public Rectangle ContentRectangle;
        public Rectangle CloseBtnRectangle;

private Rectangle WorkAreaRectangle;

private int SavedTop;
        private int currentTop = 1;
        private int intervalValue = 2;

public const int WM_NCLBUTTONDOWN = 0x00A1; //消息:左键点击 winuser.h
        public const int HT_CAPTION = 0x0002; //标题栏

[DllImportAttribute("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); //发送消息 //winuser.h 中有函数原型定义
        [DllImportAttribute("user32.dll")]
        public static extern bool ReleaseCapture(); //释放鼠标捕捉 winuser.h
        /*
         * SendMessage向消息循环发送标题栏被按下的消息来模拟窗体的拖动,
         * ShowWindow用来将特定句柄的窗体显示出来,
         * 注意第二个参数nCmdShow,它表示窗体应该怎样显示出来,
         * 而我们需要窗体不获得焦点显示出来,
         * SW_SHOWNOACTIVATE可以满足我们要求,
         * 继续在WinUser.h文件中搜索找到该常量对应的值为4,
         * 于是我们就可以这样调用来显示窗体了:
         */
        [DllImportAttribute("user32.dll")] //winuser.h
        private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);

public int CurrentState=0; //0=hide 1=uptoshow 2=showing 3=downtohide

private AlertForm()
        {
            InitializeComponent();
            SetBackgroundBitmap(snnu.ccs.Properties.Resources.popup2, Color.FromArgb(255, 0, 255));
        }
        public static void Show(string ftitletext, string fcontenttext)
        {
            AlertForm alert = new AlertForm();
            alert.ShowForm(ftitletext, fcontenttext);
        }
        /*
         * 当窗体需要升起时将窗体的Top属性值不断减少,
         * 而窗体回落时将Top属性值增加并超过屏幕的高度窗体就消失了,
         * 虽然原理很简单但仍需精确控制。
         * SetBackgroundBitmap函数首先将窗体背景图像保存到BackgroundBitmap变量中,
         * 然后根据该位图图像轮廓和透明色创建Region,BitmapToRegion就用于完成Bitmap到Region的转换,
         * 程序再将这个Region付值给窗体的Region属性以完成不规则窗体的创建。
         */
        protected void SetBackgroundBitmap(Image image, Color transparencyColor)
        {
            BackgroundBitmap = new Bitmap(image);
            Width = BackgroundBitmap.Width;
            Height = BackgroundBitmap.Height;
            TitleRectangle = new Rectangle(2, 1, 70, 25);
            TitlebarRectangle = new Rectangle(1, 1, Width, 25);
            ContentRectangle = new Rectangle(1, 25, Width, Height - 25);
            CloseBtnRectangle = new Rectangle(Width - 25, 1, 25, 25);
            Region = BitmapToRegion(BackgroundBitmap, transparencyColor);
        }

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

protected void DrawText(Graphics grfx)
        {
            if (titleText != null && titleText.Length != 0)
            {
                StringFormat sf = new StringFormat();
                sf.Alignment = StringAlignment.Near;
                sf.LineAlignment = StringAlignment.Center;
                sf.FormatFlags = StringFormatFlags.NoWrap;
                sf.Trimming = StringTrimming.EllipsisCharacter;
                grfx.DrawString(titleText, normalTitleFont, new SolidBrush(normalTitleColor), TitleRectangle, sf);
            }

if (contentText != null && contentText.Length != 0)
            {
                StringFormat sf = new StringFormat();
                sf.Alignment = StringAlignment.Center;
                sf.LineAlignment = StringAlignment.Center;
                sf.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
                sf.Trimming = StringTrimming.Word;    
                grfx.DrawString(contentText, normalContentFont, new SolidBrush(normalContentColor), ContentRectangle, sf);
            }
        }
        /*
         * 通知窗体背景以及文字的绘制在重载的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);
        }
        /*
         * CurrentState变量表示窗体的状态是显示中、停留中还是隐藏中,
         * 两个计时器根据窗体不同状态对窗体的位置进行更改,
         * 我们会使用SetBounds来执行该操作:
         * this.SetBounds(WorkAreaRectangle.Width - this.Width, WorkAreaRectangle.Height - currentTop, this.Width, this.Height);
         */
        protected void ShowForm(string ftitletext, string fcontenttext)
        {
            titleText = ftitletext;
            contentText = fcontenttext;
            WorkAreaRectangle = Screen.GetWorkingArea(WorkAreaRectangle);
            this.Top = WorkAreaRectangle.Height + this.Height;
            FormBorderStyle = FormBorderStyle.None;
            WindowState = FormWindowState.Normal;
            this.SetBounds(WorkAreaRectangle.Width - this.Width, WorkAreaRectangle.Height - currentTop, this.Width, this.Height);
            CurrentState = 1;
            timer1.Enabled = true;

ShowWindow(this.Handle, 4); //#define SW_SHOWNOACTIVATE   4
        }

private void timer1_Tick(object sender, EventArgs e)
        {
            if (CurrentState == 1)
            {
                this.SetBounds(WorkAreaRectangle.Width - this.Width, WorkAreaRectangle.Height - currentTop, this.Width, this.Height);
                currentTop = currentTop + intervalValue;
                if (this.Top <= WorkAreaRectangle.Height - this.Height)
                {
                    timer1.Enabled = false;
                    CurrentState = 2;
                    timer2.Enabled = true; //显示停留计时
                    currentTop = 1;
                }
            }
            else if (CurrentState==3)
            {
                this.SetBounds(WorkAreaRectangle.Width - this.Width, SavedTop + currentTop, this.Width, this.Height);
                currentTop = currentTop + intervalValue;
                if (this.Top >= WorkAreaRectangle.Height)
                {
                    timer1.Enabled = false;

this.Close();
                    CurrentState = 0;
                    currentTop = 1;
                }
            }
        }
        /*
         上述代码首先返回窗体绘制表面的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.Close();
                    currentTop = 1;
                }
            }
        }

private void timer2_Tick(object sender, EventArgs e)
        {
            timer2.Enabled = false;
            CurrentState = 1;
            currentTop = 1;
            SavedTop = this.Top;
            CurrentState = 3;
            timer1.Enabled = true;
        }

private void TaskbarForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (ContentRectangle.Contains(e.Location))
            {
                Cursor = Cursors.Hand;
            }
            else
                Cursor = Cursors.Default;
        }
    }

winform消息提示框的更多相关文章

  1. 自定义iOS 中推送消息 提示框

    看到标题你可能会觉得奇怪 推送消息提示框不是系统自己弹出来的吗? 为什么还要自己自定义呢? 因为项目需求是这样的:最近需要做 远程推送通知 和一个客服系统 包括店铺客服和官方客服两个模块 如果有新的消 ...

  2. Android第三方开源对话消息提示框:SweetAlertDialog(sweet-alert-dialog)

    Android第三方开源对话消息提示框:SweetAlertDialog(sweet-alert-dialog) Android第三方开源对话消息提示框:SweetAlertDialog(sweet- ...

  3. 精美舒适的对话消息提示框--第三方开源--SweetAlertDialog

    SweetAlertDialog(sweet-alert-dialog)是一个套制作精美.动画效果出色生动的Android对话.消息提示框 SweetAlertDialog(sweet-alert-d ...

  4. Android:Toast简单消息提示框

    Toast是简单的消息提示框,一定时间后自动消失,没有焦点. 1.简单文本提示的方法: Toast.makeText(this, "默认的toast", Toast.LENGTH_ ...

  5. Android应用开发学习之Toast消息提示框

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 本文我们来看Toast消息提示框的用法.使用Toast消息提示框一般有三个步骤: 1.  创建一个Toast对象.可 ...

  6. JS~Boxy和JS模版实现一个标准的消息提示框

    面向对象的封装 面向对象一个入最重要的特性就是“封装”,将一些没有必要公开的方法和属性以特定的方式进行组装,使它对外只公开一个接口,外界在调用它时,不需要关注它实现的细节,而只要关注它的方法签名即可, ...

  7. MFC上下浮动与渐入渐出消息提示框实现

    类似QQ与360软件,消息提示有两种.上下浮动.渐入渐出. 1.上下浮动提示框实现 机制,定时器响应上下浮动消息. 主要API:MoveWindow. 源码如下UpDownTipDlg.h.UpDow ...

  8. Android消息提示框Toast

    Android消息提示框Toast Toast是Android中一种简易的消息提示框.和Dialog不一样的是,Toast是没有焦点的,toast提示框不能被用户点击,而且Toast显示的时间有限,t ...

  9. 微信小程序之----消息提示框toast

    toast toast为消息提示框,无按钮,如需关闭弹框可以添加事件设置hidden为true,在弹框显示后经过duration指定的时间后触发bindchange绑定的函数. 官方文档 .wxml ...

随机推荐

  1. bzoj 1007: [HNOI2008]水平可见直线【半平面交】

    其实并不算标准半平面交?但是思路差不多 先按照斜率排序,然后用栈维护凸壳,每遇到重斜率或a[i],s[top-1]交点的x轴在s[top],s[top-1]交点左侧,则说明s[top]被a[i],s[ ...

  2. 洛谷 P2761 软件补丁问题 【spfa】

    -为什么最短路的题会出现在网络流24里?? 因为范围是15所以直接把每个状态作为一个点,向它能转移到的点连有向边即可.可以不用建图(据说建图存不下?),直接枚举m个转移方案.位运算比较麻烦注意不要写错 ...

  3. P4357 [CQOI2016]K远点对(KDTree)

    传送门 又一次产生了KDTree本质就是爆搜的感觉-- 大概就类似于p4169,只不过是从最近点对变成了第\(k\)远点对 我们开一个小根堆,里面放\(k\)个元素,起初全为\(0\),然后每一次都把 ...

  4. Java标准输入流system.in报错: java.util.NoSuchElementException解决方法

    我的程序大概是这样的: main()主函数里面,调用两个自定义的方法,这里我们称之为方法a和方法b: 主函数main()里有一个:Scanner scanner = new Scanner(Syste ...

  5. Tree CodeForces -932D

    错误记录:如下注释语句 #include<cstdio> #include<algorithm> using namespace std; typedef long long ...

  6. Access OLE对象和附件的区别

    OLE 对象 来自 Office 和基于 Windows 的程序的图像.文档.图形和其他对象 最多可存储 2GB 数据(此大小限制适用于所有 Access 数据库).请记住,添加 2GB 数据会导致数 ...

  7. jQuery相关知识总结

    1 encodeURIComponent(city)处理js传值乱码问题 2 总体概述 以后项目如果没有特殊情况,一般采用jQuery作为最基础的公共底层库. 另外对于前端的javascript相关的 ...

  8. Win10 UWP开发:摄像头扫描二维码/一维码功能

    这个示例演示整合了Aran和微软的示例,无需修改即可运行. 支持识别,二维码/一维码,需要在包清单管理器勾选摄像头权限. 首先右键项目引用,打开Nuget包管理器搜索安装:ZXing.Net.Mobi ...

  9. 死磕 java集合之终结篇

    概览 我们先来看一看java中所有集合的类关系图. 这里面的类太多了,请放大看,如果放大还看不清,请再放大看,如果还是看不清,请放弃. 我们下面主要分成五个部分来逐个击破. List List中的元素 ...

  10. CentOS安装使用vnc进行远程桌面登录

    以下介绍在CentOS 7下安装vncserver并使用vnc-viewer进行登录(使用root权限): 1.运行命令yum install tigervnc-server安装vncserver: ...