苏飞—Perky Su

签名: 软件开发,功能定制,全国各种接口开发,网页抓取程序,请联系我给我留言      Q Q:                    

posts - 184, comments - 1664, trackbacks - 3, articles - 5
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

C#仿QQ皮肤系列之-引言

Posted on 2010-03-13 21:11 苏飞 阅读(6423) 评论(28) 编辑 收藏

                                              C#仿QQ皮肤-实现原理系列文章导航 
                        http://www.cnblogs.com/sufei/archive/2010/03/10/1682847.html                

        

                                                             C#仿QQ皮肤系列之-引言

 

       开篇大喜吧,有朋友很早就提出让我写文章说明这块的原理,一直没有时间来写,今天是这块的第一篇文章,我不打算说什么实际的实现上的问题,跟大家聊聊天

不知道 有没有朋友研究过这一块,其实只有三个点上的技术要我们去研究的,第一个就是GDI+   ,基本上每一个控件都 用的上,当然这套皮肤主要也是从这块入手的,建议如果对这块不太理解的朋友可以先学习一下,第二个就是 windows的API,像显示方面的,呵呵 ,当然还有别的,这些我会在之后的具体实现上一一说明,第三块其实就是,程序的实现原理了,也就是作文里的中心思想。

       先告诉大家一个好的消息吧,就是在最新的皮肤里我又增加了一个右键菜单的功能, 方便大家的使用,只在在调用的界面里加上一行就可以了, 跟使用正常的控件没有什么分别,当然也是有不同肤色让大家选择的。具体功能 可以看最新版本的皮肤。

     接下来先做个小例子吧,实现一个最简单点的控件就是Button,原理今天先不讲,就讲讲怎么实现效果的先来看一下效果

 

效果就是这样的  接下来看看怎么样实现 的,在开始写代码之前,我们得先用PS,P几张图片出来

一共是三张,是这样的

 

   在不同的事件时显示

我们应该首先添加一个用户控件

他的InitializeComponent()方法代码如下

 

代码
this.lblText = new Label();
            
this.SuspendLayout();
            
// 
            
// lblText
            
// 
            this.lblText.BackColor = System.Drawing.Color.Transparent;
            
this.lblText.Dock = System.Windows.Forms.DockStyle.Fill;
            
this.lblText.Font = new System.Drawing.Font("宋体"10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            
this.lblText.Location = new System.Drawing.Point(00);
            
this.lblText.Name = "lblText";
            
this.lblText.Size = new System.Drawing.Size(7830);
            
this.lblText.TabIndex = 0;
            
this.lblText.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            
this.lblText.TextChanged += new System.EventHandler(this.lblText_TextChanged);
            
this.lblText.MouseLeave += new System.EventHandler(this.lblText_MouseLeave);
            
this.lblText.Click += new System.EventHandler(this.lblText_Click);
            
this.lblText.MouseUp += new System.Windows.Forms.MouseEventHandler(this.lblText_MouseUp);
            
this.lblText.MouseEnter += new System.EventHandler(this.lblText_MouseEnter);
            
this.lblText.ForeColor = Shared.FontColor;
            
// 
            
// Button
            
// 
            this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
            
this.Controls.Add(this.lblText);
            
this.Name = "Button";
            
this.Size = new System.Drawing.Size(7830);
            
this.ResumeLayout(false);

 

 

下面我们来处理一下怎么样让他在不同的事件时显示 不同的图片吧,这个很简单,我就不多说了,代码在这里

 

 

代码
protected override void OnCreateControl()
        {
            
base.OnCreateControl();

            
this.NormalImage = Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream("CRD.WinUI.Resources.Common.button.btnnomal.bmp"), truefalse);
            
this.MouseDownImage = Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream("CRD.WinUI.Resources.Common.button.btndown.bmp"), truefalse);
            
this.MouseMoveImage = Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream("CRD.WinUI.Resources.Common.button.btnfore.bmp"), truefalse);
            
        }

        
public void ResetBackGroundImage()
        {
            
this.NormalImage = Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream("CRD.WinUI.Resources.Common.button.btnnomal.bmp"), truefalse);
            
this.MouseDownImage = Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream("CRD.WinUI.Resources.Common.button.btndown.bmp"), truefalse);
            
this.MouseMoveImage = Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream("CRD.WinUI.Resources.Common.button.btnfore.bmp"), truefalse);
        }

        
private string _text = string.Empty;

        [Browsable(
true)]
        
public new string Caption
        {
            
get { return _text; }
            
set
            {
                _text 
= value;

                
if (lblText.Text != value)
                {
                    lblText.Text 
= value;
                }
            }
        }

        
private void lblText_TextChanged(object sender, EventArgs e)
        {
            
this.Text = lblText.Text;
        }

        
private void lblText_MouseEnter(object sender, EventArgs e)
        {
            
this.OnMouseEnter(e);
        }

        
private void lblText_MouseLeave(object sender, EventArgs e)
        {
            
this.OnMouseLeave(e);
        }

        
private void lblText_MouseUp(object sender, MouseEventArgs e)
        {
            
this.OnMouseUp(e);
        }

        
private void lblText_Click(object sender, EventArgs e)
        {
            
this.PerformClick();
        }

 

 

     有了这些,我们只要生成一下,然后就可以在工具箱里找到Button这个控件 了,和使用系统 的控件没有什么差别,直接 拉过来就可以使用了,

属性也和系统 控件一样,呵呵,里面还用到了一些具体皮肤上的东西,在这里我先不多说,后面的文章会详细 的说明,这里只是想让大家看一下,普通的控件效果是怎么实现 的,如果您对基本的用户控件的实现还不理解的话,建议先去学习一下,要不然,不敢保证能明白 和我思路。

     在这个控件 里我把原有的Text属性给取消了,大这可以用这个属性来代替一下定义的方法如下

代码
 
  [Browsable(true)]
        
public new string Caption
        {
            get { 
return _text; }
            
set
            {
                _
text = value;

                
if (lblText.Text != value)
                {
                    lblText.
Text = value;
                }
            }
        }

 

那原有的Text属性呢,呵呵 其实也不是没有了,在这里lblText.Text;这个就是原有的Text属性,只不过不会显示在控件上,用上面的方法可以显示出来,这个lblText.Text;可 以在Load事件里调用lblText.Text=“确定”;这样在执行的时候是可以的,当然也可以直接使用Caption属性

      [Browsable(true)]是指定这个属性是否出现在工具箱里,当然这里是True了  

我这个控件单独使用是不行的,还借助一下基类,

CommandButton 这也是一个UserControl

这个类我暂时不提共,说到[Browsable(true)]我还想多提一点点,大家看这个 [DefaultEvent("Click")] 就是在自己的控件里定义一个默认的事件,是什么意思 呢

意思 就是在你双击控件时默认的事件

还是提一些吧,要不然应该会有朋友说了,

简单点先说四个

 

代码
 private Image _mouseMoveImage = null;
        private 
Image _mouseDownImage = null;
        private 
Image _normalImage = null;
        private ToolTip toolTip;
        private System.ComponentModel.IContainer components;

 

 

定义方法

 

 

代码
  public Image MouseMoveImage
        {
            
get 
            { 
               
                
return _mouseMoveImage;
            }
            
set
            {
                _mouseMoveImage 
= value;
            }
        }

        
public Image MouseDownImage
        {
            
get 
            { 
               
                
return _mouseDownImage;
            }
            
set
            {
                _mouseDownImage 
= value;
            }
        }

        
public Image NormalImage
        {
            
get 
            {
              
                
return _normalImage;
            }
            
set
            {
                _normalImage 
= value;
                
this.BackgroundImage = _normalImage;
            }
        }

        
public Color ImageTransparentColor
        {
            
get
            {
                
return this.imageTransparentColor;
            }
            
set
            {
                
this.imageTransparentColor = value;

                Bitmap image 
= this.BackgroundImage as Bitmap;

                
if (((image != null&& (value != Color.Empty)) && !ImageAnimator.CanAnimate(image))
                {
                    
try
                    {
                        image.MakeTransparent(
this.imageTransparentColor);
                    }
                    
catch
                    { }
                }
            }
        }

        
//重写一下创建控件的方法
        protected override void OnCreateControl()
        {
            
base.OnCreateControl();
            
if (this.NormalImage != null)
            {
                
this.BackgroundImage = NormalImage;
            }
        }

        
//重写进入事件
        protected override void OnMouseEnter(EventArgs e)
        {
            
base.OnMouseEnter(e);

            
if (this.MouseMoveImage != null)
            {
                
this.BackgroundImage = MouseMoveImage;
            }
            
this.Invalidate();
        }

        
//重写离开可见部分的事件
        protected override void OnMouseLeave(EventArgs e)
        {
            
base.OnMouseLeave(e);

            
if (this.NormalImage != null)
            {
                
this.BackgroundImage = NormalImage;
            }
            
this.Invalidate();
        }

        
//重写鼠标按下事件
        protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
        {
            
base.OnMouseDown(e);

            
if (this.MouseDownImage != null)
            {
                
this.BackgroundImage = this.MouseDownImage;
            }
        }

        
//重写鼠标离开事件
        protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
        {
            
base.OnMouseUp(e);

            
if (this.NormalImage != null)
            {
                
this.BackgroundImage = NormalImage;
            }
        }

        
//重写背景修改时的事件
        protected override void OnBackgroundImageChanged(EventArgs e)
        {
            
base.OnBackgroundImageChanged(e);

            
this.ImageTransparentColor = Color.FromArgb(2550255);
        }

        
public string ToolTip
        {
            
get { return _toolTip; }
            
set
            {
                _toolTip 
= value;
                
this.toolTip.SetToolTip(this, _toolTip);
            }
        }

 

 

其实我也不知道 要怎么开头说,不知道 这样行不行,如果大家有更好的方案可以告诉我, 我一定改正,呵呵

     。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

-------------------------------------------------------------签名部分------------------------------------------------------------------------

                          

         欢迎大家转载,如有转载请注明文章来自:   http://sufei.cnblogs.com/   

签名:做一番一生引以为豪的事业;在有生之年报答帮过我的人;并有能力帮助需要帮助的人;    

软件开发,功能定制,请联系我给我留言 QQ:361983679 Email:sufei.1013@163.com  MSN:sufei.1013@163.com 


-------------------------------------------------------------------推荐文章--------------------------------------------------------------
1.C#仿QQ皮肤 2.Sql2005学习笔记 3.httpHelper类

Feedback

#1楼  回复 引用 查看   

2010-03-13 21:16 by .tmp      
mark

#2楼  回复 引用 查看   

2010-03-13 21:30 by sheng.chao      
你为什么要用LABEL显示TEXT
另外用UserControl来实现,思路也不正确。

#3楼[楼主]  回复 引用 查看   

2010-03-13 21:36 by 苏飞      
@sheng.chao
原因是,第一我用的是UserControl,第二,你是说为什么用UserControl是因为方便使处理图片背景方便,更重要的是用UserControl可以有一个基类,这样我再处理其实按钮的时候就方便了,如果 使用Installer也就是安装程序类,我知道这样方便,只是如果控件里不只这一个是不是不很方便,这是我选择UserControl的原因,当然像TextBox,和Label,这样的简单控件是没有问题的使用Installer,不知道你有什么高见

#4楼  回复 引用 查看   

2010-03-13 21:39 by sheng.chao      
引用苏飞:
@sheng.chao
原因是,第一我用的是UserControl,第二,你是说为什么用UserControl是因为方便使处理图片背景方便,更重要的是用UserControl可以有一个基类,这样我再处理其实按钮的时候就方便了,如果 使用Installer也就是安装程序类,我知道这样方便,只是如果控件里不只这一个是不是不很方便,这是我选择UserControl的原因,当然像TextBox,和Label,这样的简单控件是没有问题的使用Installer,不知道你有什么高见

莫名奇妙,不懂你在说什么

#5楼[楼主]  回复 引用 查看   

2010-03-13 21:41 by 苏飞      
@sheng.chao
我是说,如果你有两到三个不同类型的Button,但有一些方法和属性是相同的,你怎么处理

#6楼  回复 引用 查看   

2010-03-14 09:59 by sohighthesky      
也许是水平太低,反正是没看懂
如果没看错的话,好像还要用几张图片,莫非tx的按钮还是用的图片?

#7楼  回复 引用 查看   

2010-03-14 12:53 by 不得闲      
完全采用API去绘制,显示文字不必要用一个Label
WinAPI的DrawText就是专门做这个的!
呵呵,我是用Delphi的,这些时候也在做皮肤控件!目前基本上实现了窗口皮肤化,以及一些皮肤控件!目前实现的例图:

我的地址在: www.cnblogs.com/dxsoft

#8楼  回复 引用 查看   

2010-03-14 14:21 by Nero.Pang      
你这东西在WIN7下有问题,WINFORM的边框是灰色的,难看

#9楼[楼主]  回复 引用 查看   

2010-03-14 16:48 by 苏飞      
@Nero.Pang
这个在最新的版本中已经解决了

#10楼[楼主]  回复 引用 查看   

2010-03-14 16:49 by 苏飞      
@不得闲
你去看看我的最新的http://www.cnblogs.com/sufei/archive/2010/01/14/1648041.html

#11楼  回复 引用 查看   

2010-03-14 19:11 by [Chris Wang]      
基类是不是应该用Button?

#12楼[楼主]  回复 引用 查看   

2010-03-14 20:10 by 苏飞      
@[Chris Wang]
你说的是控件的基类,我说的是可以派生其他类型Button的类

#13楼  回复 引用 查看   

2010-03-21 01:12 by 数据加载中...      
我想问http://www.cnblogs.com/sufei/archive/2010/01/14/1648041.html
这个是用.NET做的,那启动的时显示出来有么延迟吗或者说叫卡。
如果很流畅,那请教一下,您是如何实现的。

#14楼  回复 引用 查看   

2010-03-21 01:14 by 数据加载中...      
你是这样写的么:(大体描述一下)
class x : CommandButtom

我个人认为是用GDI来绘制控件的文本及背景应该快一点。当然啦,那样会很麻烦。。。。也许楼主就是怕麻烦,才用Label的吧

#15楼[楼主]  回复 引用 查看   

2010-03-21 01:14 by 苏飞      
@数据加载中...
你下载一下看看啊,我在慢慢改进,有一些但不是太明显

#16楼  回复 引用 查看   

2010-03-21 01:15 by 数据加载中...      
@不得闲
你那个菜单不是很好,我感觉子菜单缩进一点会好看些。

#17楼[楼主]  回复 引用 查看   

2010-03-21 01:19 by 苏飞      
@数据加载中...
现在版本的是绘的,呵呵 ,不是麻烦,是实现时有不同的方法,Gdi+也不一定快有时候,要根据不同的情况 ,毛主席说过有调查才有发言权,呵呵,你最拿到代码了也没有看出来我是绘的啊,这个就晕了

#18楼  回复 引用 查看   

2010-03-21 02:50 by 数据加载中...      
@苏飞
呵呵 我是刚接触的,加上代码量很大,看得我眼花。

#19楼[楼主]  回复 引用 查看   

2010-03-21 18:49 by 苏飞      
@数据加载中...
呵呵 有源码慢慢分析一下,呵呵

#20楼  回复 引用   

2010-04-07 19:02 by qq:357464419[未注册用户]
@sheng.chao
引用sheng.chao:
你为什么要用LABEL显示TEXT
另外用UserControl来实现,思路也不正确。

同感
使用处理起来你还要顾及Lable,否则会出问题
要显示文字直接使用TextRender.DrawText()方法画上就可以了

至于UserControl依个人习惯吧,如果真要做这种控件我更愿意使用CustomerControl

#21楼[楼主]  回复 引用 查看   

2010-04-07 19:12 by 苏飞      
@qq:357464419
大家可以看一下源文件是怎么绘制的再 发表呵呵

#22楼  回复 引用   

2010-09-13 15:13 by 这个确实[未注册用户]
继承UserControl确实有点多余了。继承Control就可以做到了。
使用Label来做文字也不好。直接DrawText或者 DrawString更合理。

也许你单个图片按钮的时候没感觉出有什么不同的。也许20来个也没感觉出有什么不同。
但是如果你有20个按钮,再加上窗体是去掉边框,使用图片贴上去的不规则窗体。
你就会发现打开的时候有明显的延迟。效果很差。
创建一个按钮还要再去创建一个Label对象,必然会拖累速度的。

#23楼[楼主]  回复 引用 查看   

2010-09-15 17:14 by 苏飞      
@这个确实
感谢你的建议啊

#24楼  回复 引用 查看   

2011-05-31 15:22 by 桦仔      
有源码可以看一下吗?

#25楼  回复 引用 查看   

2011-05-31 15:23 by 桦仔      
引用sohighthesky:
也许是水平太低,反正是没看懂
如果没看错的话,好像还要用几张图片,莫非tx的按钮还是用的图片?

我也看不懂

#26楼[楼主]  回复 引用 查看   

2011-05-31 15:37 by 苏飞      
@桦仔
http://www.cnblogs.com/sufei/archive/2010/03/10/1682847.html

#27楼[楼主]  回复 引用 查看   

2011-09-13 16:48 by 苏飞      
@噜噜咪
别发了,早晚都删除

#28楼  回复 引用 查看   

2011-12-08 20:41 by 心雨纷扬      
我用的win7 64bit,发现切换菜单的时候控件重绘时屏幕区域总是不停的闪烁
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1685236 +lo3kIlswcA=