• C#贴边自动隐藏组件完美版


          直接贴代码,别让我再看到上次评论里的"怎么用啊?","能不能给我发份代码?"之类的屁话!
      1using System;
      2using System.ComponentModel;
      3using System.Collections.Generic;
      4using System.Diagnostics;
      5using System.Text;
      6using System.Drawing;
      7using System.Runtime.InteropServices;
      8using System.Windows.Forms;
      9
     10namespace autoDockWindow
     11{
     12    [Description("窗体自动靠边隐藏完美组件 @Author: Red_angelX")]
     13    public partial class autoDockManager : Component
     14    {
     15        private Form _form;
     16
     17        public autoDockManager()
     18        {
     19            InitializeComponent();
     20        }

     21
     22        public autoDockManager(IContainer container)
     23        {
     24            container.Add(this);
     25            InitializeComponent();
     26        }

     27
     28        [Description("用于控制要自动Dock的窗体")]
     29        public Form dockForm
     30        {
     31            get
     32            {
     33                return _form;
     34            }

     35            set
     36            {
     37                _form = value;
     38                if (_form != null)
     39                {
     40                    if (_form.TopMost == false)
     41                        _form.TopMost = true;
     42
     43                    if (DesignMode)
     44                        return;
     45
     46                    nativeDockWindow dockWindow = new nativeDockWindow();
     47                    dockWindow.AssignHandle(_form.Handle);
     48                }

     49            }

     50        }

     51    }

     52
     53    public class nativeDockWindow : NativeWindow
     54    {
     55        IntPtr handle = IntPtr.Zero;
     56        Form baseForm = null;
     57
     58        const int HM_NONE = 0;   //不收缩
     59        const int HM_TOP = 1;   //向上收缩
     60        const int HM_BOTTOM = 2;   //向下收缩
     61        const int HM_LEFT = 3;   //向左收缩
     62        const int HM_RIGHT = 4;   //向右收缩
     63
     64        const int INTERVAL = 20;  //触发粘附的最小间隔,单位为象素
     65        const int INFALTE = 4;  //触发收缩的小间隔,单位为象素
     66
     67
     68        bool m_isWndHide = false;       //窗口是否隐藏
     69        bool m_isSizeChanged = false;   //窗口大小是否改变了 
     70        bool m_isSetTimer = false;      //窗口大小是否改变了
     71        int m_oldWndHeight;    //旧的窗口宽度
     72        int m_hideMode = HM_NONE;         //隐藏模式
     73
     74        Timer checkTimer = new Timer();    //定时器
     75
     76        protected override void OnHandleChange()
     77        {
     78            handle = this.Handle;
     79            if (handle != IntPtr.Zero)
     80            {
     81                baseForm = (Form)Form.FromHandle(handle);
     82                checkTimer.Interval = 200;
     83                checkTimer.Tick +=new EventHandler(checkTimer_Tick);
     84            }

     85            base.OnHandleChange();
     86        }

     87
     88        //修正移动时窗口的大小
     89        void FixMoving(ref Message m)
     90        {
     91            //已经隐藏了的情况
     92            if (m_hideMode != HM_NONE && m_isWndHide == true)
     93            {
     94                return;
     95            }

     96
     97            if (Control.MousePosition.Y <= INTERVAL)
     98            {   //粘附在上边
     99                m_hideMode = HM_TOP;
    100            }

    101            else if (Control.MousePosition.Y >= (Screen.PrimaryScreen.Bounds.Width - INTERVAL))
    102            {   //粘附在下边
    103                m_hideMode = HM_BOTTOM;
    104            }

    105            else if (Control.MousePosition.X < INTERVAL)
    106            {    //粘附在左边    
    107                if (!m_isSizeChanged)
    108                {
    109                    m_oldWndHeight = baseForm.Height;
    110                }

    111                m_isSizeChanged = true;
    112                m_hideMode = HM_LEFT;
    113            }

    114            else if (Control.MousePosition.X >= (Screen.PrimaryScreen.Bounds.Width - INTERVAL))
    115            {   //粘附在右边
    116                if (!m_isSizeChanged)
    117                {
    118                    m_oldWndHeight = baseForm.Height;
    119                }

    120                m_isSizeChanged = true;
    121                m_hideMode = HM_RIGHT;
    122            }

    123            else
    124            {   //不粘附
    125
    126                if (m_isSizeChanged)
    127                {   //如果收缩到两边,则拖出来后会变回原来大小
    128                    //在"拖动不显示窗口内容下"只有光栅变回原来大小
    129                    int left = Marshal.ReadInt32(m.LParam, sizeof(int* 0);
    130                    int top = Marshal.ReadInt32(m.LParam, sizeof(int* 1);
    131                    int right = Marshal.ReadInt32(m.LParam, sizeof(int* 2);
    132                    Marshal.WriteInt32(m.LParam, sizeof(int* 0, left); // left
    133                    Marshal.WriteInt32(m.LParam, sizeof(int* 1, top); // top
    134                    Marshal.WriteInt32(m.LParam, sizeof(int* 2, right); // right
    135                    Marshal.WriteInt32(m.LParam, sizeof(int* 3, top + m_oldWndHeight); // bottom
    136                    m_isSizeChanged = false;
    137                }

    138                if (m_isSetTimer)
    139                {   //如果Timer开启了,则关闭之
    140                    checkTimer.Stop();
    141                    m_isSetTimer = false;
    142                }

    143                m_isWndHide = false;
    144                m_hideMode = HM_NONE;
    145            }

    146        }

    147
    148        //从收缩状态显示窗口
    149        void DoShow()
    150        {
    151            if (m_hideMode == HM_NONE || !m_isWndHide)
    152                return;
    153
    154            switch (m_hideMode)
    155            {
    156                case HM_TOP:
    157                    baseForm.Location = new Point(baseForm.Location.X, 0);
    158                    m_isWndHide = false;
    159                    break;
    160                case HM_BOTTOM:
    161                    //不处理
    162                    //m_isWndHide = false;
    163                    break;
    164                case HM_LEFT:
    165                    baseForm.Location = new Point(01);
    166                    m_isWndHide = false;
    167                    break;
    168                case HM_RIGHT:
    169                    baseForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width - baseForm.Width, 1);
    170                    m_isWndHide = false;
    171                    break;
    172                default:
    173                    break;
    174            }

    175        }

    176
    177        //从显示状态收缩窗口
    178        void DoHide()
    179        {
    180            if (m_hideMode == HM_NONE || m_isWndHide)
    181                return;
    182
    183            switch (m_hideMode)
    184            {
    185                case HM_TOP:
    186                    //此句必须放在MoveWindow之上,否则大小变成m_wndRect,其他case同样        
    187                    m_isWndHide = true;
    188                    baseForm.Location = new Point(baseForm.Location.X, (baseForm.Height - INFALTE) * (-1));
    189                    break;
    190                case HM_BOTTOM:
    191                    //m_isWndHide = true;
    192                    break;
    193                case HM_LEFT:
    194                    m_isWndHide = true;
    195                    baseForm.Size = new Size(baseForm.Width, Screen.PrimaryScreen.WorkingArea.Height);
    196                    baseForm.Location = new Point((-1* (baseForm.Width - INFALTE), 1);
    197                    break;
    198                case HM_RIGHT:
    199                    m_isWndHide = true;
    200                    baseForm.Size = new Size(baseForm.Width, Screen.PrimaryScreen.WorkingArea.Height);
    201                    baseForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width - INFALTE, 1);
    202                    break;
    203                default:
    204                    break;
    205            }

    206        }

    207
    208
    209        const UInt32 SWP_NOSIZE = 0x0001;
    210        const UInt32 SWP_NOMOVE = 0x0002;
    211        const UInt32 SWP_NOZORDER = 0x0004;
    212        const UInt32 SWP_NOREDRAW = 0x0008;
    213        const UInt32 SWP_NOACTIVATE = 0x0010;
    214        const UInt32 SWP_FRAMECHANGED = 0x0020;  // The frame changed: send WM_NCCALCSIZE 
    215        const UInt32 SWP_SHOWWINDOW = 0x0040;
    216        const UInt32 SWP_HIDEWINDOW = 0x0080;
    217        const UInt32 SWP_NOCOPYBITS = 0x0100;
    218        const UInt32 SWP_NOOWNERZORDER = 0x0200;  // Don't do owner Z ordering 
    219        const UInt32 SWP_NOSENDCHANGING = 0x0400// Don't send WM_WINDOWPOSCHANGING 
    220
    221        [DllImport("user32.dll")]
    222        static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
    223           int Y, int cx, int cy, uint uFlags);
    224
    225        [DllImport("user32.dll")]
    226        [return: MarshalAs(UnmanagedType.Bool)]
    227        static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
    228
    229        //这个结构在改lparam时要用到
    230        [StructLayout(LayoutKind.Sequential)]
    231        public struct RECT
    232        {
    233            public int Left;
    234            public int Top;
    235            public int Right;
    236            public int Bottom;
    237        }

    238
    239        [DllImport("user32.dll")]
    240        [return: MarshalAs(UnmanagedType.Bool)]
    241        static extern bool GetCursorPos(out Point lpPoint);
    242
    243        [DllImport("user32.dll")]
    244        static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth,
    245           int nHeight, bool bRepaint);
    246
    247        [DllImport("user32.dll")]
    248        static extern bool InflateRect(ref RECT lprc, int dx, int dy);
    249
    250        [DllImport("user32.dll")]
    251        static extern bool PtInRect([In] ref RECT lprc, Point pt);
    252
    253
    254        private void checkTimer_Tick(object sender, EventArgs e)
    255        {
    256            RECT tRect;
    257            //获取此时窗口大小
    258            GetWindowRect(this.Handle, out tRect);
    259            //膨胀tRect,以达到鼠标离开窗口边沿一定距离才触发事件
    260            InflateRect(ref tRect, INFALTE, INFALTE);
    261
    262            if (!PtInRect(ref tRect, Control.MousePosition))   //如果鼠标离开了这个区域
    263            {
    264                checkTimer.Stop();
    265                m_isSetTimer = false;
    266                DoHide();  //隐藏
    267            }

    268        }

    269
    270        const int WM_NCHITTEST = 0x84;
    271        const int WM_MOVING = 0x216;
    272        const int WM_MOVE = 0x3;
    273        const int WM_SIZING = 0x214;
    274        const int HTCAPTION = 0x0002;
    275        const int WM_EXITSIZEMOVE = 0x232;
    276        const int WM_ENTERSIZEMOVE = 0x231;
    277        const int WM_SYSCOMMAND = 0x112;
    278        const int SC_SIZE = 0xF000;
    279        const int WM_SETTINGCHANGE = 0x1A;
    280
    281        protected override void WndProc(ref Message m)
    282        {
    283            if (m.Msg == WM_NCHITTEST)
    284            {
    285                if (m_hideMode != HM_NONE && !m_isSetTimer)
    286                {   //鼠标进入时,如果是从收缩状态到显示状态则开启Timer
    287                    checkTimer.Start();
    288                    m_isSetTimer = true;
    289                    DoShow();
    290                }

    291            }

    292            else if (m.Msg == WM_MOVING)
    293            {                
    294                FixMoving(ref m);
    295            }

    296            else if(m.Msg == WM_ENTERSIZEMOVE)
    297            {
    298                baseForm.SuspendLayout();
    299            }

    300            else if (m.Msg == WM_EXITSIZEMOVE)
    301            {
    302                baseForm.ResumeLayout();
    303            }

    304            base.WndProc(ref m);
    305        }

    306    }

    307}

    308
  • 相关阅读:
    二分、冒泡、选择、插入排序
    15行python代码,帮你理解令牌桶算法
    mybatis 的排序方式用参数传入 但是无法正常排序
    js事件篇
    ajax详解
    kafka概要设计
    HttpClient简述
    双十一问题:在洪峰数据来临的瞬间,redis出现连接超时异常
    双十一问题:kafka消费能力低下原因思考
    Timer类注意事项
  • 原文地址:https://www.cnblogs.com/Red_angelX/p/1235377.html
Copyright © 2020-2023  润新知