Winform的窗体美化心酸路

来源:互联网 发布:小田切让 知乎 编辑:程序博客网 时间:2024/05/17 01:14

我想做一位狂热的程序猿粪子!

其实一直都很想做点什么,工作原因林林种种导致停止了前进的脚步。

有时会为自己的一个目标狂热,但经常发觉激情过后更多的总是为自己找借口!

最近感觉奔三将近。逐有感而发,不能再这样下去了。

即拿出以前自己为那狂热好一阵的东西继续下去。

一直想为自己开发一套控件库,但感觉精力确实有限,也没那么多时间,逐渐浇灭了这样的织热。

 

这是套窗体皮肤,断断续续所花费的时间也不少。

下面我介绍下我的这套皮肤,其实也算不上一套,只算是个开始吧。

有人可能会想这不就是边框隐藏再绘制客户区么,这是目前大部人会选择的方案。但我这是连同客户区和边框一同绘的效果。

这种实现方式难度大些,更关键的是比较耗时,加之当时对有些消息的不了解,在一些问题上花费了大量的时间。

 废话不多说帖代码

复制代码
protected virtual void OnNcPaint(PaintEventArgs e)        {            Graphics dc = e.Graphics;            dc.PageUnit = GraphicsUnit.Pixel;            Rectangle iconArea = new Rectangle(10, 4, this.Icon.Width, this.Icon.Height);            if (this.ShowIcon && iconArea.IntersectsWith(e.ClipRectangle))                dc.DrawIcon(this.Icon, new Rectangle(0, 0, this.IconSize.Width, this.IconSize.Height));            Rectangle textArea = this.CaptionArea;            if (textArea.IntersectsWith(e.ClipRectangle))            {                StringFormat strFmt = new StringFormat();                switch (this.CaptionAlign)                {                    case ContentAlignment.TopLeft:                        strFmt.Alignment = StringAlignment.Near;                        strFmt.LineAlignment = StringAlignment.Near;                        if (this.ShowIcon) textArea.X += this.IconSize.Width;                        textArea.X += this.CaptionOffset.X;                        textArea.Y += this.captionOffset.Y;                        break;                    case ContentAlignment.TopCenter:                        strFmt.Alignment = StringAlignment.Center;                        strFmt.LineAlignment = StringAlignment.Near;                        break;                    case ContentAlignment.TopRight:                        strFmt.Alignment = StringAlignment.Far;                        strFmt.LineAlignment = StringAlignment.Near;                        textArea.Width = this.CaptionButtonOffset;                        textArea.Width -= this.CaptionOffset.X;                        textArea.Height -= this.CaptionOffset.Y;                        break;                    case ContentAlignment.MiddleLeft:                        strFmt.Alignment = StringAlignment.Near;                        strFmt.LineAlignment = StringAlignment.Center;                        if (this.ShowIcon) textArea.X += this.IconSize.Width;                        textArea.X += this.CaptionOffset.X;                        textArea.Y += this.captionOffset.Y;                        break;                    case ContentAlignment.MiddleCenter:                        strFmt.Alignment = StringAlignment.Center;                        strFmt.LineAlignment = StringAlignment.Center;                        break;                    case ContentAlignment.MiddleRight:                        strFmt.Alignment = StringAlignment.Far;                        strFmt.LineAlignment = StringAlignment.Center;                        textArea.Width = this.CaptionButtonOffset;                        break;                    case ContentAlignment.BottomLeft:                        strFmt.Alignment = StringAlignment.Near;                        strFmt.LineAlignment = StringAlignment.Far;                        if (this.ShowIcon) textArea.X += this.IconSize.Width;                        textArea.X += this.CaptionOffset.X;                        textArea.Y += this.captionOffset.Y;                        break;                    case ContentAlignment.BottomCenter:                        strFmt.Alignment = StringAlignment.Center;                        strFmt.LineAlignment = StringAlignment.Far;                        break;                    case ContentAlignment.BottomRight:                        strFmt.Alignment = StringAlignment.Far;                        strFmt.LineAlignment = StringAlignment.Far;                        textArea.Width = this.CaptionButtonOffset;                        textArea.Width -= this.CaptionOffset.X;                        textArea.Height -= this.CaptionOffset.Y;                        break;                }                using (SolidBrush brush = new SolidBrush(this.ForeColor))                {                    //dc.DrawString(this.Text, this.Font, brush, textArea, strFmt);                    TextDraw.DrawWordArtEffect(dc, this.Text, this.Font, this.ForeColor, Color.Black, textArea, strFmt, WordArtEffectStyle.shadow);                }            }        }protected override void OnPaintBackground(PaintEventArgs e)        {            //透明画刷填充            if (this.backgroundPattern == null)            {                this.backgroundPattern = DrawWinBackgroundPattern();            }            e.Graphics.DrawImage(this.backgroundPattern, e.ClipRectangle,                new Rectangle(e.ClipRectangle.X, this.CaptionHeight + e.ClipRectangle.Y,                    e.ClipRectangle.Width, e.ClipRectangle.Height), GraphicsUnit.Pixel);        }protected override void WndProc(ref Message m)        {            switch ((WindowsMessages)m.Msg)            {                case WindowsMessages.WM_NCCALCSIZE:                    this.WmNcCalcSize(ref m);                    return;                case WindowsMessages.WM_NCACTIVATE:                    this.WmNcActivate(ref m);                    return;                case WindowsMessages.WM_NCUAHDRAWCAPTION:                    return;                case WindowsMessages.WM_NCUAHDRAWFRAME:                    return;                case WindowsMessages.WM_NCPAINT:                    this.WmNcPaint(ref m);                    return;                case WindowsMessages.WM_NCHITTEST:                    this.WmNcHitTest(ref m);                    return;                case WindowsMessages.WM_NCLBUTTONDBLCLK:                    if (this.MaximizeBox && this.MaximumSize.IsEmpty)                        base.WndProc(ref m);                    return;                case WindowsMessages.WM_NCLBUTTONDOWN:                    this.WmNcLButtonDown(ref m);                    return;                case WindowsMessages.WM_NCLBUTTONUP:                    this.WmNcLButtonUP(ref m);                    return;                case WindowsMessages.WM_NCMOUSEMOVE:                    this.WmNcMouseMove(ref m);                    return;                case WindowsMessages.WM_NCMOUSELEAVE:                    this.WmNcMouseLeave(ref m);                    return;                case WindowsMessages.WM_LBUTTONDOWN:                    this.WmLButtonDown(ref m);                    return;                case WindowsMessages.WM_GETMINMAXINFO:                    this.WmGetMinMaxInfo(ref m);                    return;                default:                    base.WndProc(ref m);                    return;            }        }
复制代码
复制代码
protected virtual Image DrawWinBackgroundPattern()        {            Bitmap img = new Bitmap(this.Width, this.Height);            using (Graphics gp = Graphics.FromImage(img))            {                gp.SmoothingMode = SmoothingMode.AntiAlias;                gp.PageUnit = GraphicsUnit.Pixel;                gp.Clear(this.BackColor);                if (this.BackgroundImage == null)                {                    using (LinearGradientBrush brush = new LinearGradientBrush(this.CaptionArea, ColorDraw.ColorOffset(this.BackColor, 30),                        Color.FromArgb(0, 255, 255, 255), LinearGradientMode.Vertical))                    {                        gp.FillRectangle(brush, this.CaptionArea);                    }                }                else                {                    switch (this.BackgroundImageLayout)                    {                        case ImageLayout.None:                            {                                #region None                                int gradientX = Math.Min(this.BackgroundImage.Width, 300);                                int gradientY = Math.Min(this.BackgroundImage.Height, 100);                                gp.DrawImage(this.BackgroundImage, new Point());                                Rectangle rightGradientReg = new Rectangle(this.BackgroundImage.Width - gradientX, 0, gradientX, this.BackgroundImage.Height);                                Rectangle bottomGradientReg = new Rectangle(0, this.BackgroundImage.Height - gradientY, this.BackgroundImage.Width, gradientY);                                using (LinearGradientBrush hbrush = new LinearGradientBrush(rightGradientReg, Color.FromArgb(0, this.BackColor), Color.FromArgb(255, this.BackColor), 0F))                                {                                    rightGradientReg.X += 1;                                    gp.FillRectangle(hbrush, rightGradientReg);                                }                                using (LinearGradientBrush vbrush = new LinearGradientBrush(bottomGradientReg, Color.FromArgb(0, this.BackColor), Color.FromArgb(255, this.BackColor), 90F))                                {                                    gp.FillRectangle(vbrush, bottomGradientReg);                                }                                #endregion                            }                            break;                        case ImageLayout.Stretch:                            {                                #region Stretch                                int gradientX = Math.Min(this.Width, 300);                                int gradientY = Math.Min(this.Height, 100);                                gp.DrawImage(this.BackgroundImage, new Rectangle(Point.Empty, this.Size),                                    new Rectangle(0, 0, Math.Min(this.BackgroundImage.Width, this.Width), Math.Min(this.BackgroundImage.Height, this.Height)), GraphicsUnit.Pixel);                                Rectangle rightGradientReg = new Rectangle(this.Width - gradientX, 0, gradientX, this.Height);                                Rectangle bottomGradientReg = new Rectangle(0, this.Height - gradientY, this.Width, gradientY);                                Color rightside = BitmapDraw.GetBitmapEdgeColor(this.BackgroundImage, BorderSide.Right);                                Color bottomside = BitmapDraw.GetBitmapEdgeColor(this.BackgroundImage, BorderSide.Bottom);                                using (LinearGradientBrush hbrush = new LinearGradientBrush(rightGradientReg, Color.FromArgb(0, rightside), Color.FromArgb(255, rightside), 0F))                                {                                    rightGradientReg.X += 1;                                    gp.FillRectangle(hbrush, rightGradientReg);                                }                                using (LinearGradientBrush vbrush = new LinearGradientBrush(bottomGradientReg, Color.FromArgb(0, bottomside), Color.FromArgb(255, bottomside), 90F))                                {                                    gp.FillRectangle(vbrush, bottomGradientReg);                                }                                #endregion                            }                            break;                        case ImageLayout.Tile:                            {                                #region Tile                                gp.DrawImage(this.BackgroundImage, new Rectangle(Point.Empty, this.Size),                                    new Rectangle(Point.Empty, this.BackgroundImage.Size), GraphicsUnit.Pixel);                                #endregion                            }                            break;                        case ImageLayout.Center:                            {                                #region Center                                Rectangle targetRect = new Rectangle(Point.Empty, this.Size);                                Rectangle desRect = new Rectangle(Point.Empty, this.BackgroundImage.Size);                                if (this.Width > this.BackgroundImage.Width)                                {                                    targetRect.X = (this.Width - this.BackgroundImage.Width) / 2;                                    targetRect.Width = this.BackgroundImage.Width;                                }                                else if (this.Width < this.BackgroundImage.Width)                                {                                    desRect.X = (this.BackgroundImage.Width - this.Width) / 2;                                    desRect.Width = this.Width;                                }                                if (this.Height > this.BackgroundImage.Height)                                {                                    targetRect.Y = (this.Height - this.BackgroundImage.Height) / 2;                                    targetRect.Height = this.BackgroundImage.Height;                                }                                else if (this.Height < this.BackgroundImage.Height)                                {                                    desRect.Y = (this.BackgroundImage.Height - this.Height) / 2;                                    desRect.Height = this.Height;                                }                                gp.DrawImage(this.BackgroundImage, targetRect, desRect, GraphicsUnit.Pixel);                                int gradientW = Math.Min(this.BackgroundImage.Width, 300);                                int gradientH = Math.Min(this.BackgroundImage.Height, 100);                                Rectangle leftGradientReg = new Rectangle(targetRect.X - 1, targetRect.Y, gradientW, targetRect.Height);                                Rectangle topGradientReg = new Rectangle(targetRect.X, targetRect.Y, targetRect.Width, gradientH);                                Rectangle rightGradientReg = new Rectangle(targetRect.Width - gradientW + targetRect.X, targetRect.Y, gradientW, targetRect.Height);                                Rectangle bottomGradientReg = new Rectangle(targetRect.X, targetRect.Height - gradientH + targetRect.Y, targetRect.Width, gradientH);                                using (LinearGradientBrush lhbrush = new LinearGradientBrush(leftGradientReg, Color.FromArgb(255, this.BackColor), Color.FromArgb(0, this.BackColor), 0F))                                {                                    gp.FillRectangle(lhbrush, leftGradientReg);                                }                                using (LinearGradientBrush rhbrush = new LinearGradientBrush(rightGradientReg, Color.FromArgb(0, this.BackColor), Color.FromArgb(255, this.BackColor), 0F))                                {                                    rightGradientReg.X++;                                    gp.FillRectangle(rhbrush, rightGradientReg);                                }                                using (LinearGradientBrush tvbrush = new LinearGradientBrush(topGradientReg, Color.FromArgb(255, this.BackColor), Color.FromArgb(0, this.BackColor), 90F))                                {                                    topGradientReg.Y--;                                    gp.FillRectangle(tvbrush, topGradientReg);                                }                                using (LinearGradientBrush bvbrush = new LinearGradientBrush(bottomGradientReg, Color.FromArgb(0, this.BackColor), Color.FromArgb(255, this.BackColor), 90F))                                {                                    gp.FillRectangle(bvbrush, bottomGradientReg);                                }                                #endregion                            }                            break;                        case ImageLayout.Zoom:                            {                                #region Zoom                                gp.DrawImage(this.BackgroundImage, Point.Empty);                                Rectangle winRound = new Rectangle(Point.Empty, this.Size);                                using (LinearGradientBrush brush = new LinearGradientBrush(winRound, Color.FromArgb(60, this.BackColor),                                    Color.FromArgb(200, this.BackColor), LinearGradientMode.Vertical))                                {                                    gp.FillRectangle(brush, winRound);                                }                                #endregion                            }                            break;                        default:                            {                                gp.DrawImage(this.BackgroundImage,                                    new Rectangle(0, 0, this.Size.Width, this.Size.Height),                                    new Rectangle(0, 0, this.BackgroundImage.Width, this.BackgroundImage.Height), GraphicsUnit.Pixel);                            }                            break;                    }                }                //绘制设计器时标题栏分界线                if (this.DesignMode && this.CaptionHeight > 0)                {                    using (Pen pen = new Pen(Color.FromArgb(127, 0, 127)))                        gp.DrawLine(pen, 0, this.CaptionHeight - 1, this.Width - 1, this.CaptionHeight - 1);                }                //绘制边框                if (this.BorderWidth > 0)                {                    using (Pen pen = new Pen(Color.FromArgb(50, Color.Black), this.BorderWidth))                    {                        Rectangle outborderline = Rectangle.FromLTRB(0, 0, this.Size.Width - 1, this.Size.Height - 1);                        gp.DrawPath(pen, VectorDraw.CreateRoundRect(outborderline, this.CircularBeadRadius, BorderSide.None));                    }                }                if (this.BorderLightWidth > 0)                {                    using (Pen pen = new Pen(Color.FromArgb(50, Color.White), this.BorderLightWidth))                    {                        Rectangle inborderline = Rectangle.FromLTRB(this.BorderWidth, this.BorderWidth, this.Size.Width - this.BorderWidth * 2, this.Size.Height - this.BorderWidth * 2);                        gp.DrawPath(pen, VectorDraw.CreateRoundRect(inborderline, this.CircularBeadRadius, BorderSide.None));                    }                }                if (this.NCPaint != null)                    this.NCPaint.Invoke(new PaintEventArgs(gp, this.ClipNcRectangle));            }            return img;        }
复制代码

 重绘非客户区,大家可能注意到上面的代码

case WindowsMessages.WM_NCUAHDRAWCAPTION:return;case WindowsMessages.WM_NCUAHDRAWFRAME:return;

此处消息什么也不处理,也许是历史年代原因,上述消息是响应win98的机制,窗体非客户区的重绘会导致头部出现黑色块,我们将之屏蔽即可。

PS:当时的我可在这坑了很长时间。

 

大家都知道,其实winform最大的瓶颈就是性能!

但是导致重绘的原因很多,如,鼠标移动,窗体移动,大小改变等以及还有我们的主观控制。

所以我们应当尽可能的减少重绘次,以及增加局部重绘的条件。

原创粉丝点击