C#仿QQ皮肤-基窗体FunctionFormBase的实现

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

 

        一周要过去了,本来打算多写点的,还是时间不够啊,费话不多说,开始写代码,今天 我们要做的是一个窗体,这个窗体是基于窗体FormBase,就是我们上一节所说到的FormBase与基用户控件FormBase1的实现 里面的FormBase窗体, 有关 FormBase的实现还请大家去看相应文章,这里不再做过多的说明。

        我们先看一下实现的效果吧,第一张图是 实现,第二张是正常使用时的样子

        

 

   下面看一下怎么实现吧,

   第一步,创建窗体

            我们右键单击文件夹选择添加窗体就行了,名称当时是“ FunctionFormBase”,然后单击确定,我们的窗体的大小不需要做任何的修改,那是因为那是继承自窗体FormBase而来的,上节我们讲过了, 他的大小是固定的,所以在这里不用再做设置;

            只要这样一行继承的语句就OK了

  

  ///   <summary>
    
///  FunctionFormBase基窗体
    
///  是构造EntryForm和SkinForm窗体的基础
    
///   </summary>
     public   partial   class  FunctionFormBase : FormBase
    

 

    第二步,窗体的UI布局实现

            我们可以看到第一张图,就是窗体的UI布局,相信大家一看就能明白是怎么实现 的,我还是大致的说一下是怎么会事吧。窗体一共是三个Panel

     代码实现为:

代码
             //  
            
//  ptbTopMiddle
            
//  
             this .ptbTopMiddle.Dock  =  System.Windows.Forms.DockStyle.Fill;
            
this .ptbTopMiddle.Location  =   new  System.Drawing.Point( 10 0 );
            
this .ptbTopMiddle.Name  =   " ptbTopMiddle " ;
            
this .ptbTopMiddle.Size  =   new  System.Drawing.Size( 669 31 );
            
this .ptbTopMiddle.TabIndex  =   2 ;
            
this .ptbTopMiddle.TabStop  =   false ;

            
//  pnlBackGroup
            
//  
             this .pnlBackGroup.BackgroundImageLayout  =  System.Windows.Forms.ImageLayout.Stretch;
            
this .pnlBackGroup.Dock  =  System.Windows.Forms.DockStyle.Fill;
            
this .pnlBackGroup.Location  =   new  System.Drawing.Point( 0 31 );
            
this .pnlBackGroup.Name  =   " pnlBackGroup " ;
            
this .pnlBackGroup.Size  =   new  System.Drawing.Size( 689 444 );
            
this .pnlBackGroup.TabIndex  =   9 ;

            
//  
            
//  ptbBottomMiddle
            
//  
             this .ptbBottomMiddle.Dock  =  System.Windows.Forms.DockStyle.Fill;
            
this .ptbBottomMiddle.Location  =   new  System.Drawing.Point( 10 0 );
            
this .ptbBottomMiddle.Name  =   " ptbBottomMiddle " ;
            
this .ptbBottomMiddle.Size  =   new  System.Drawing.Size( 669 37 );
            
this .ptbBottomMiddle.TabIndex  =   3 ;

 

 

 在ptbTopMiddle左面是一个lblText  右面是两个CommandButton,这个控件是 我自己写的实现方法后面会提到这里不做详细说明,在ptbTopMiddle的两端分别是两个Panel,用来实现窗体的边角,和低部的ptbBottomMiddle 形式是一样的,下面我给出这些控件的初始代码

 

 ,我是通过Controls.Remove方法来实现 的,具体的代码如下所示

 

代码
  // 移除FormBase现有控件
             this .Controls.Remove( this .pnlRight);
            
this .Controls.Remove( this .pnlLeft);
            
this .Controls.Remove( this .pnlBackGroup);
            
this .Controls.Remove( this .pnlCaption);
            
this .Controls.Remove( this .pnlBottom);

 

 

 好了我们的布局就到这里吧

第三步,ptbTopMiddle功能实现

    因为我们的窗体是一个Panel,所以在移动和鼠标松开时的效果要处理一下,先说一下标题和最小化吧

     标题是个Label,我们需要重写定义一下,怎么样来实现呢,我们只要重写一下窗体的Text属性就行了。实现如下

 

 

 

 

代码

        
// 最小化
         public   new   bool  MinimizeBox
        {
            
get
            {
                
return   base .MinimizeBox;
            }
            
set
            {
                
base .MinimizeBox  =  value;
                
this .btnMin.Visible  =  value;
            }
        }

 

还有最后一个关闭按钮,这个更简单了,一个Close方法搞定

 

// 关闭按钮
         private   void  btnClose_Click( object  sender, EventArgs e)
        {
            
this .Close();
        }

 

 

  第四步,窗体移动效果

        我们的窗体是没有实际的标题的所以 在这里要处理一下移动时的效果

 在这里用到了一些Api,具体的说明 请大家参考代码中的类文章Win32类 ,一共有两个方法一个是鼠标移动时的方法

 

 

代码
  // 鼠标松开时
         private   void  caption_MouseUp( object  sender, MouseEventArgs e)
        {
            
if  (e.Button  ==  MouseButtons.Right  &&  ((Control)sender).Cursor  ==  Cursors.Default  &&  e.Y  <=  SystemInformation.CaptionHeight)
            {
                Win32.TrackPopupMenu(Win32.GetSystemMenu(Handle, 
0 ).ToInt32(),  2 , Cursor.Position.X, Cursor.Position.Y,  0 , Handle,  0 );
            }
        }

 

第五步,窗体样式 实现

        样式方面第一个重点就是Windows消息的处理,跟其实窗体的实现原理是一样的,不同 是WindowsApi和消息,因为消息在这里还要用的到所以我加了个ref,呵呵 ,ref(ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中)

  

代码
  ///   <summary>
        
///  Windows消息处理
        
///   </summary>
        
///   <param name="m"> Message </param>
         protected   override   void  WndProc( ref  Message m)
        {
            
switch  (m.Msg)
            {
                
case  Win32.WM_COMMAND:
                    Win32.SendMessage(Handle, Win32.WM_SYSCOMMAND, (
int )m.WParam, ( int )m.LParam);
                    
break ;
                
case  Win32.WM_SYSCOMMAND:
                    
base .WndProc( ref  m);

                    
if  (m.WParam.ToInt64()  ==  Win32.SC_RESTORE)
                    {
                        
this .Height  +=   6 ;
                        
this .Width  +=   6 ;
                    }
                    
else   if  (m.WParam.ToInt64()  ==  Win32.SC_MAXIMIZE)
                    {
                        Application.DoEvents();
                    }

                    
break ;
                
default :
                    
base .WndProc( ref  m);
                    
break ;
            }
        }

 

  这个窗体的样式 除了Windows消息还有一个ReSetFormBitmap方法,因为这个方法是FromBase窗体 里我们在这里需要重写一下,

跟原先的方法实现是一样的,只是我要改几张图片,呵呵

 

代码
  ///   <summary>
        
///  设置窗体样式
        
///   </summary>
         public   override   void  ReSetFormBitmap()
        {
            
this .pnlCaption.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertm.bmp " ));
            
this .ptbTopLeft.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertl.bmp " ));
            
this .ptbTopMiddle.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertm.bmp " ));
            
this .ptbTopRight.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertr.bmp " ));

            
this .ptbLeft.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderml.bmp " ));
            
this .ptbRight.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordermr.bmp " ));

            
this .ptbBottomLeft.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbl.bmp " ));
            
this .ptbBottomMiddle.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbm.bmp " ));
            
this .ptbBottomRight.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbr.bmp " ));

            
this .pnlBackGroup.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bg.bmp " ));

            Bitmap closeBitmap 
=   new  Bitmap(Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.MainWin.Button.CloseBtn.bmp " )));
            
this .btnClose.NormalImage  =  closeBitmap.Clone( new  Rectangle( 0 0 37 22 ), PixelFormat.Format64bppPArgb);
            
this .btnClose.MouseMoveImage  =  closeBitmap.Clone( new  Rectangle( 37 0 37 22 ), PixelFormat.Format64bppPArgb);
            
this .btnClose.MouseDownImage  =  closeBitmap.Clone( new  Rectangle( 74 0 37 22 ), PixelFormat.Format64bppPArgb);

            Bitmap minBitmap 
=   new  Bitmap(Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.MainWin.Button.MinBtn.bmp " )));
            
this .btnMin.NormalImage  =  minBitmap.Clone( new  Rectangle( 0 0 31 22 ), PixelFormat.Format64bppPArgb);
            
this .btnMin.MouseMoveImage  =  minBitmap.Clone( new  Rectangle( 31 0 31 22 ), PixelFormat.Format64bppPArgb);
            
this .btnMin.MouseDownImage  =  minBitmap.Clone( new  Rectangle( 62 0 31 22 ), PixelFormat.Format64bppPArgb);

            
this .CurrentSkinColor  =  SkinColor.Default;
        }

 

  文章中用到的所有素材请大家到源文件中去查找这里不再做过多的说明

到这里基本全部实现了,更具体的还请大家参考 源代码

老规矩这里附上窗体的所有实现 代码

 

代码
using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;

using  System.Text;
using  System.Windows.Forms;
using  CRD.Common;
using  System.Drawing.Imaging;

namespace  CRD.WinUI.Forms
{
    
///   <summary>
    
///  FunctionFormBase基窗体
    
///  是构造EntryForm和SkinForm窗体的基础
    
///   </summary>
     public   partial   class  FunctionFormBase : FormBase
    {
        
// 构造器
         public  FunctionFormBase()
        {
            
// 设置默认的皮肤
             this .SetStyle(ControlStyles.DoubleBuffer  |  ControlStyles.AllPaintingInWmPaint,  true );

            InitializeComponent();

            
// 移除FormBase现有控件
             this .Controls.Remove( this .pnlRight);
            
this .Controls.Remove( this .pnlLeft);
            
this .Controls.Remove( this .pnlBackGroup);
            
this .Controls.Remove( this .pnlCaption);
            
this .Controls.Remove( this .pnlBottom);
        }

        
///   <summary>
        
///  Windows消息处理
        
///   </summary>
        
///   <param name="m"> Message </param>
         protected   override   void  WndProc( ref  Message m)
        {
            
switch  (m.Msg)
            {
                
case  Win32.WM_COMMAND:
                    Win32.SendMessage(Handle, Win32.WM_SYSCOMMAND, (
int )m.WParam, ( int )m.LParam);
                    
break ;
                
case  Win32.WM_SYSCOMMAND:
                    
base .WndProc( ref  m);

                    
if  (m.WParam.ToInt64()  ==  Win32.SC_RESTORE)
                    {
                        
this .Height  +=   6 ;
                        
this .Width  +=   6 ;
                    }
                    
else   if  (m.WParam.ToInt64()  ==  Win32.SC_MAXIMIZE)
                    {
                        Application.DoEvents();
                    }

                    
break ;
                
default :
                    
base .WndProc( ref  m);
                    
break ;
            }
        }

        
///   <summary>
        
///  设置窗体样式
        
///   </summary>
         public   override   void  ReSetFormBitmap()
        {
            
this .pnlCaption.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertm.bmp " ));
            
this .ptbTopLeft.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertl.bmp " ));
            
this .ptbTopMiddle.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertm.bmp " ));
            
this .ptbTopRight.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordertr.bmp " ));

            
this .ptbLeft.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderml.bmp " ));
            
this .ptbRight.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bordermr.bmp " ));

            
this .ptbBottomLeft.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbl.bmp " ));
            
this .ptbBottomMiddle.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbm.bmp " ));
            
this .ptbBottomRight.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.borderbr.bmp " ));

            
this .pnlBackGroup.BackgroundImage  =  Image.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.Common.dialog2009.bg.bmp " ));

            Bitmap closeBitmap 
=   new  Bitmap(Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.MainWin.Button.CloseBtn.bmp " )));
            
this .btnClose.NormalImage  =  closeBitmap.Clone( new  Rectangle( 0 0 37 22 ), PixelFormat.Format64bppPArgb);
            
this .btnClose.MouseMoveImage  =  closeBitmap.Clone( new  Rectangle( 37 0 37 22 ), PixelFormat.Format64bppPArgb);
            
this .btnClose.MouseDownImage  =  closeBitmap.Clone( new  Rectangle( 74 0 37 22 ), PixelFormat.Format64bppPArgb);

            Bitmap minBitmap 
=   new  Bitmap(Bitmap.FromStream(Shared.AssemblyWinUI.GetManifestResourceStream( " CRD.WinUI.Resources.MainWin.Button.MinBtn.bmp " )));
            
this .btnMin.NormalImage  =  minBitmap.Clone( new  Rectangle( 0 0 31 22 ), PixelFormat.Format64bppPArgb);
            
this .btnMin.MouseMoveImage  =  minBitmap.Clone( new  Rectangle( 31 0 31 22 ), PixelFormat.Format64bppPArgb);
            
this .btnMin.MouseDownImage  =  minBitmap.Clone( new  Rectangle( 62 0 31 22 ), PixelFormat.Format64bppPArgb);

            
this .CurrentSkinColor  =  SkinColor.Default;
        }

        
///   <summary>
        
///  重写的OnLoad
        
///   </summary>
         protected   override   void  OnLoad(EventArgs e)
        {
            
this .Controls.Add( this .pnlRight);
            
this .Controls.Add( this .pnlLeft);
            
this .Controls.Add( this .pnlBackGroup);
            
this .Controls.Add( this .pnlCaption);
            
this .Controls.Add( this .pnlBottom);

            
if  ( ! DesignMode)
            {
                
this .Hide();
            }

            
base .OnLoad(e);

            Win32.SetWindowLong(
this .Handle,  - 16 ,Win32.GetWindowLong( this .Handle, - 16 - Win32.WS_MAXIMIZEBOX );

            
this .Show();
        }

        
// 关闭按钮
         private   void  btnClose_Click( object  sender, EventArgs e)
        {
            
this .Close();
        }

        
// 最小化
         private   void  btnMin_Click( object  sender, EventArgs e)
        {
            
this .WindowState  =  FormWindowState.Minimized;
        }

        
// 移动标题时
         private   void  Caption_MouseMove( object  sender, MouseEventArgs e)
        {
            ((Control)sender).Cursor 
=  Cursors.Default;
            
if  (e.Button  ==  MouseButtons.Left)
            {
                Win32.ReleaseCapture();
                Win32.SendMessage(Handle, 
274 61440   +   9 0 );
            }
        }

        
// 标题
         public   override   string  Text
        {
            
get
            {
                
return   base .Text;
            }
            
set
            {
                
base .Text  =  value;
                
if  ( this .lblText != null )
                
this .lblText.Text  =   this .Text;
            }
        }

        
// 最小化
         public   new   bool  MinimizeBox
        {
            
get
            {
                
return   base .MinimizeBox;
            }
            
set
            {
                
base .MinimizeBox  =  value;
                
this .btnMin.Visible  =  value;
            }
        }

        
// 鼠标松开时
         private   void  caption_MouseUp( object  sender, MouseEventArgs e)
        {
            
if  (e.Button  ==  MouseButtons.Right  &&  ((Control)sender).Cursor  ==  Cursors.Default  &&  e.Y  <=  SystemInformation.CaptionHeight)
            {
                Win32.TrackPopupMenu(Win32.GetSystemMenu(Handle, 
0 ).ToInt32(),  2 , Cursor.Position.X, Cursor.Position.Y,  0 , Handle,  0 );
            }
        }

    }
}

 

 

       

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值