C#窗体贴边自动隐藏组件 By Red_angelX

 

    靠边隐藏效果:当程序移动到显示的边界时,程序自动隐藏起来,留一条小边在外面,很酷的效果吧.
    先介绍下实现原理,靠边隐藏无非就是判断窗体的位置和屏幕的四边的关系,当上左右三个方向超出的时候,就把窗体自动往上移,问题是...怎么判断窗体的位置呢?.Net里面有很方便的事件:LocationChanged,来判断窗体位置的变化,那又如何判断鼠标和窗体的关系呢?最简单的办法是用个 timer不停的去判断...,我最不想用这种方法实现,结果苦苦探寻了两个小时最终还是以这种最笨的方法来实现效果-_-#,如果不用timer,还有其他什么方法呢?我第一想到的是钩子,于是我拦截系统消息WM_MOVE,WM_MOVING,0x00a0................发现都无法满足要求,翻遍winnt.h也没发现有什么是进入窗体离开窗体时发出的消息,只有一个0x00a0是经过窗体边框时发的消息,不过呢如果鼠标移动太快,系统就收不到这个消息.... 此路不通,于是想看看.Net里面封装了什么事件, 很遗憾MouveEnter和MouseLeave会被上层的控件遮蔽,我总不能窗体上有多少控件都给设置Mouse事件吧.............,最后还是用timer来实现比较现实-_-#
    我把它封装成一个.Net组件,这样以后的项目如果需要这种效果只需像引用Timer一样拖拽到窗体上,然后设置DockForm为需要效果的窗体就可以了
    具体代码如下:

建一个自定义控件,然后记得建一个Timer,并设置Tick事件

using  System;
using  System.ComponentModel;
using  System.Diagnostics;
using  System.Text;
using  System.Windows.Forms;
using  System.Drawing;

namespace  QQClient.QQ.QQBuddy.Components
{
    [Description(
" 窗体自动靠边隐藏组件 @Author: Red_angelX " )]
    
public  partial  class  AutoDockManage : Component
    {
        
private  Form _form;

        
public  AutoDockManage()
        {
            InitializeComponent();
        }

        
public  AutoDockManage(IContainer container)
        {
            container.Add(
this );

            InitializeComponent();
        }

        [Description(
" 用于控制要自动Dock的窗体 " )]
        
public  Form DockForm
        {
            
get
            {
                
return  _form;
            }
            
set
            {
                _form 
=  value;
                
if  (_form  !=   null )
                {
                    _form.LocationChanged 
+=   new  EventHandler(_form_LocationChanged);                    
                    _form.SizeChanged 
+=   new  EventHandler(_form_SizeChanged);
                    _form.TopMost 
=   true ;
                }
            }
        }

        
private   bool  IsOrg  =   false ;
        
private  Rectangle lastBoard;
        
private   const   int  DOCKING  =   0 ;
        
private   const   int  PRE_DOCKING  =   1 ;
        
private   const   int  OFF  =   2 ;

        
private   int  status  =   2 ;

        
private   void  CheckPosTimer_Tick( object  sender, EventArgs e)
        {
            
if  (DesignMode)
            {
                
return ;
            }

            
if  (_form  ==   null   ||  IsOrg  ==   false  )
            {
                
return ;
            }

            
if  (_form.Bounds.Contains(Cursor.Position))
            {
                
/*
                 * 该死的.Net在移动时候不会发生该代码,必须在鼠标离开后才会执行
                if (dockSide == AnchorStyles.None && status == OFF && IsOrg == true)
                {
                    if (_form.Bounds.Width == lastBoard.Width && _form.Bounds.Height == lastBoard.Height)
                    {
                        return;
                    }
                    _form.Size = new Size(lastBoard.Width, lastBoard.Height);
                    return;
                } 
                 
*/
                
switch  (dockSide)
                {
                    
case  AnchorStyles.Top:
                        
if  (status  ==  DOCKING)
                        _form.Location 
=   new  Point(_form.Location.X,  0 );
                        
break ;
                    
case  AnchorStyles.Right:
                        
if  (status  ==  DOCKING)
                        _form.Location 
=   new  Point(Screen.PrimaryScreen.Bounds.Width  -  _form.Width,  1 );
                        
break ;
                    
case  AnchorStyles.Left:
                        
if  (status  ==  DOCKING)
                        _form.Location 
=   new  Point( 0 1 );
                        
break ;
                }
            }
            
else
            {
                
switch  (dockSide)
                {
                    
case  AnchorStyles.Top:
                        _form.Location 
=   new  Point(_form.Location.X, (_form.Height  -   4 *  ( - 1 ));
                        
break ;
                    
case  AnchorStyles.Right:
                        _form.Size 
=   new  Size(_form.Width, Screen.PrimaryScreen.WorkingArea.Height);
                        _form.Location 
=   new  Point(Screen.PrimaryScreen.Bounds.Width  -   4 1 );
                        
break ;
                    
case  AnchorStyles.Left:
                        _form.Size 
=   new  Size(_form.Width, Screen.PrimaryScreen.WorkingArea.Height);
                        _form.Location 
=   new  Point(( - 1 *  (_form.Width  -   4 ),  1 );
                        
break ;
                    
case  AnchorStyles.None:
                        
if  (IsOrg  ==   true   &&  status  ==  OFF)
                        {
                            
if  (_form.Bounds.Width  !=  lastBoard.Width  ||  _form.Bounds.Height  !=  lastBoard.Height)
                            {
                                _form.Size 
=   new  Size(lastBoard.Width, lastBoard.Height);
                            }
                        }
                        
break ;
                }
            }
        }

        
internal  AnchorStyles dockSide  =  AnchorStyles.None;

        
private   void  GetDockSide()
        {
            
if  (_form.Top  <=   0 )
            {
                dockSide 
=  AnchorStyles.Top;
                
if  (_form.Bounds.Contains(Cursor.Position))
                    status 
=  PRE_DOCKING;
                
else
                    status 
=  DOCKING;
            }
            
else   if  (_form.Left  <=   0 )
            {
                dockSide 
=  AnchorStyles.Left;
                
if  (_form.Bounds.Contains(Cursor.Position))
                    status 
=  PRE_DOCKING;
                
else
                    status 
=  DOCKING;
            }
            
else   if  (_form.Left  >=  Screen.PrimaryScreen.Bounds.Width  -  _form.Width)
            {
                dockSide 
=  AnchorStyles.Right;
                
if  (_form.Bounds.Contains(Cursor.Position))
                    status 
=  PRE_DOCKING;
                
else
                    status 
=  DOCKING;
            }
            
else
            {
                dockSide 
=  AnchorStyles.None;
                status 
=  OFF;
            }
        }

        
private   void  _form_LocationChanged( object  sender, EventArgs e)
        {
            GetDockSide();
            
if  (IsOrg  ==   false )
            {
                lastBoard 
=  _form.Bounds;
                IsOrg 
=   true ;
            }
        }

        
private   void  _form_SizeChanged( object  sender, EventArgs e)
        {
            
if  (IsOrg  ==   true   &&  status  ==  OFF)
            {
                lastBoard 
=  _form.Bounds;
            }
        }
    }
}

  
   

    转载请写上出处就行,代码可以随意改动,但要保持版权完整性,现在已知还有个小问题,

    .Net机制中的窗体大小改变事件必须在鼠标离开窗体后才能执行,所以想要完美的隐藏效果,最好是自己画个标题栏

    不过总体来说还算另我满意,VS 2005 编译没问题,2003似乎命名空间不能和类名相同?可能需要改少许代码 

你可能感兴趣的:(timer,.net,C#,null)