谷歌谈话风格的Windows窗体

介绍 本文主要解释如何使用自定义绘制事件处理程序来绘制自己的Windows控件(在本例中为窗体控件)。GoogleTalkForm类继承和扩展System.Windows.Forms。表单控件(由Microsoft . net框架提供),用于提供谷歌Talk Windows窗体的外观和感觉。 类属性是windowsnappable, IsResizable, ResizableColor, TitleColor, TitleFont, TitleBackColor, TitleForeColor, TitleStyle, BodyBackColor, BodyStyle, OutlineColor, OutlineSize, IconsNormalColor, IconsHiLiteColor, MinimumHeight,和MinimumWidth可以用来改变表单的标准外观和感觉,以及行为。 GoogleTalkForm类提供: 绘制窗口窗体。 绘图使用双缓冲。 窗体快照到特定的客户端桌面区域。 鼠标事件处理。 绘制系统上下文菜单项。 它是如何工作的 首先,我们需要覆盖表单事件,如OnPaint, OnMouseDown, OnMouseUp, OnMouseMove, OnDoubleClick来处理表单绘制事件和鼠标事件。隐藏,复制Code

protected override void OnPaint(PaintEventArgs e)
{
   ...
}

protected override void OnMouseDown(MouseEventArgs e)
{
   ...
}

表单的样式必须使用GoogleTalkForm类构造函数中的SetStyle方法来设置,以反映所需的行为。隐藏,复制Code

this.SetStyle(ControlStyles.AllPaintingInWmPaint | 
              ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.StandardClick, true);
this.SetStyle(ControlStyles.StandardDoubleClick, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, false);
this.UpdateStyles();

isMousePointerInArea方法用于检查当前鼠标位置是否在特定的客户端矩形区域内。必须计算出鼠标相对于Windows窗体的位置,因为控件。鼠标位置返回鼠标相对于桌面的位置。隐藏,复制Code

private bool isMousePointerInArea(Point mousePosition, Rectangle area)
{
    Point relativePoint = new Point(0, 0);
    relativePoint.X = mousePosition.X - this.Location.X;
    relativePoint.Y = mousePosition.Y - this.Location.Y;

    return area.Contains(relativePoint);
}

自定义的窗体绘制都是通过方法OnFormPaint在一个新创建的具有窗体的精确宽度和高度的位图对象上完成的。从位图创建图形对象,并使用DrawString、DrawImage、DrawLine和DrawArc等方法。一旦所有的绘制完成,缓冲的位图就会被复制到窗体图形实例中,使用drawimageunscaling方法。隐藏,复制Code

// Create a new Pen object
p = new Pen(this.OutlineColor, this.OutlineSize);

// Draw the form outline
g.DrawArc(p, rectLeftCorner, 180, 90);
g.DrawArc(p, rectRightCorner, 270, 90);
g.DrawLine(p, edgeRadius, 0, this.Width - edgeRadius, 0);
g.DrawLine(p, 0, edgeRadius, 0, this.Height);
g.DrawLine(p, this.Width - 1, edgeRadius, 
           this.Width - 1, this.Height);
g.DrawLine(p, 0, this.Height - 1, 
           this.Width, this.Height - 1);

// Dispose the Pen object
p.Dispose();
p = null;

创建一个自定义区域并应用于窗体,以产生圆角边缘效果。要创建所需的区域,我们必须逐像素迭代,并在当前选择的像素与透明颜色不相同时向GraphicsPath对象(将用于创建区域对象)添加一个1x1的矩形。为了优化代码,只检查窗体的顶部角是否有透明的彩色像素。隐藏,收缩,复制Code

// Create GraphicsPath to be used to crop the region required
gpRegion = new GraphicsPath();

// Loop through every pixel in the top left corner.
// Create a 1 x 1 rectangle regions of pixels
// that do not match the transparent color
for (int x = rectLeftCorner.X; x < rectLeftCorner.Width; x++)
{
    for (int y = rectLeftCorner.Y; y < rectLeftCorner.Height / 2; y++) 
    {
        if (isSameColor(bmp.GetPixel(x, y), 
            this.transparentColor) == false) 
        {
            gpRegion.AddRectangle(new Rectangle(x, y, 1, 1));
        }
    }
}

// Loop through every pixel in the top right corner.
// Create a 1 x 1 rectangle regions of pixels
// that do not match the transparent color
for (int x = rectRightCorner.X + 1; x < 
             rectRightCorner.X + 
             rectRightCorner.Width + 1; x++)
{
    for (int y = rectRightCorner.Y; y < 
         rectRightCorner.Y + rectRightCorner.Height / 2; y++) 
    {
        if (isSameColor(bmp.GetPixel(x, y), 
            this.transparentColor) == false) 
        {
            gpRegion.AddRectangle(new Rectangle(x, y, 1, 1));
        }
    }
}

// Create the remaining rectangular regions
// to complete cover all the windows form area
gpRegion.AddRectangle(new Rectangle(rectLeftCorner.Width, 0, 
         this.Width - (edgeRadius * 4), rectLeftCorner.Height / 2));
gpRegion.AddRectangle(new Rectangle(0, 
         rectLeftCorner.Height / 2, this.Width, this.Height));

// Apply region
this.Region = new Region(gpRegion);

历史 第一个版本(2006年5月9日)。 1.1 -(二零零六年五月十一日) 创建窗体设计器以控制窗体(和子控件)行为。 修正了托管在MDI容器中的表单行为。 本文转载于:http://www.diyabc.com/frontweb/news6810.html

posted @ 2020-08-10 02:11  Dincat  阅读(148)  评论(0编辑  收藏  举报