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

             一直想实现类似QQ的贴边自动隐藏效果,在.Net下研究了半天,遇上不少困难,最终还是把它做出来了:)

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

          窗体里面实现了,我就想把它做成一个.Net组件,这样以后的项目如果需要这种效果只需要引用就OK了,不需要复制/粘贴代码,结果找了半天,VS2005里面没有组件项目-_-#!,用自定义控件项目改了之后编译之后不能使用-_-#!没办法,只好用csc命令行来编译组件代码!!

          本来不想贴代码的,直接给组件控件,不巧CSDN这几天不能传东西...,算了还是把代码贡献出来

 

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

namespace  Red_angelX.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(01);
                        
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 - 41);
                        
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机制的窗体大小改变事件必须在鼠标离开窗体后才能执行,所以想要完美的隐藏效果,最好是自己画个标题栏

         还一个就是IDE预执行的问题,由于timer默认是开着的我没加控制器,当加了控件的窗体大小使得IDE出现滚动条的时候,窗体就会自动缩起来.................,不知道怎么解决.

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

        使用的时候只要在工具面板里面把该dll里面的东西拖到界面上,把Form属性设置为当前窗口就行^-^

你可能感兴趣的:(C#贴边自动隐藏组件 By Red_angelX)