星辰.Net技术社区论坛

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



附件: autodockmanage.rar
1
查看完整版本: C#窗体贴边自动隐藏组件