zoukankan      html  css  js  c++  java
  • C#窗体贴边自动隐藏组件 By Red_angelX

        靠边隐藏效果:当程序移动到显示的边界时,程序自动隐藏起来,留一条小边在外面,很酷的效果吧.
        先介绍下实现原理,靠边隐藏无非就是判断窗体的位置和屏幕的四边的关系,当上左右三个方向超出的时候,就把窗体自动往上移,问题是...怎么判断窗体的位置 呢?.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(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;
                }
            }
        }
    }
        编译用csc去编译,vs2005里没找到组件工程-_-#,如果不会编译的直接下载我编译好的dll 点击下载
       

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

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

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

         

  • 相关阅读:
    更快的datetime string to python datetime转换模块 ciso8601
    华为新员工入职培训计划曝光!你留不住员工的原因就在这! zz
    在vmware中安装macos系统 vm12 osx10.11 or higher
    vmware for linux (centos65) 卸载相关
    第八章多态
    第七章 复用类
    第六章 访问权限控制
    Think in Java 第四 五 章
    Think in Java 第三章操作符
    Thank in Java
  • 原文地址:https://www.cnblogs.com/Red_angelX/p/747417.html
Copyright © 2011-2022 走看看