• C#实现QQ靠边隐藏的功能


    C#实现QQ靠边隐藏的功能收藏

    你想过为自己的程序添加靠边隐藏的功能吗?还在为计算窗体的大小及位置而烦恼吗?想这么简单的轻松调用吗?

    DockWindow.FormDockTemplate m_oDockFormTemplate = new DockWindow.FormDockTemplate(this);

    不用吃惊,您只需要在你的窗体初始化的时候(也就是窗体构造函数里添加上述这一行代码)您的程序就可以轻松拥有靠边自动隐藏的功能。

    下面我就给各位共享一个我自己经常用的靠边停靠的窗体类,详细见如下代码:

    FormDockTemplate.cs文件:

    1.         using System;    

    2.         using System.Collections.Generic;    

    3.         using System.Text;    

    4.         using System.Drawing;    

    5.         using System.Windows.Forms;    

    6.           

    7.         namespace DockWindow   

    8.         {   

    9.             public class FormDockTemplate : NativeWindow   

    10.         {  

    11.             #region 私有字段   

    12.             /// <summary>    

    13.             /// 父级窗口实例   

    14.             /// </summary>    

    15.             private Form parentForm = null;   

    16.             /// <summary>    

    17.             /// 窗口实例的启动信息   

    18.             /// </summary>    

    19.             private FormStartInfo m_oFormStartInfo = null;   

    20.             /// <summary>    

    21.             /// 当前窗口可以停靠的方式   

    22.             /// </summary>    

    23.             private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None;   

    24.             /// <summary>    

    25.             /// 窗口停靠检测的定时器   

    26.             /// </summary>    

    27.             private Timer m_tmrHideWindow = null;   

    28.             /// <summary>    

    29.             /// 自动感知的矩形区域   

    30.             /// </summary>    

    31.             private Rectangle m_rcLeft = Rectangle.Empty;   

    32.             private Rectangle m_rcTop = Rectangle.Empty;   

    33.             private Rectangle m_rcRight = Rectangle.Empty;   

    34.             private Rectangle m_rcBottom = Rectangle.Empty;   

    35.             /// <summary>    

    36.             /// 感知区域的容差值,也就是当鼠标移动进入距边缘几个象素时进行自动捕获   

    37.             /// </summary>    

    38.             private int m_iSensitiveAreaTolerantPixel = 4;  

    39.             #endregion  

    40.      

    41.             #region 字段属性   

    42.             /// <summary>    

    43.             /// 当前窗口的鼠标位置   

    44.             /// </summary>    

    45.             Point CurrentMousePos   

    46.             {   

    47.                 get  

    48.                 {   

    49.                     //获取当前鼠标的屏幕坐标               

    50.                     User32.POINT ptMousePos = new User32.POINT();   

    51.                     User32.GetCursorPos(ref ptMousePos);   

    52.                     return new Point(ptMousePos.X, ptMousePos.Y);   

    53.                 }   

    54.             }   

    55.       

    56.             Rectangle FormTitleRect   

    57.             {   

    58.                 get { return new Rectangle(parentForm.Location, new Size(parentForm.Width, parentForm.Height - parentForm.ClientRectangle.Height)); }   

    59.             }   

    60.       

    61.             /// <summary>    

    62.             /// 感应区域的容差设置,距离屏幕边缘多少象素时,开始自动感知   

    63.             /// </summary>    

    64.             public int TolerantPixel   

    65.             {   

    66.                 get { return m_iSensitiveAreaTolerantPixel; }   

    67.                 set { m_iSensitiveAreaTolerantPixel = value; }   

    68.             }  

    69.             #endregion  

    70.      

    71.             #region 构造函数   

    72.             /// <summary>    

    73.             /// 构造函数   

    74.             /// </summary>    

    75.             /// <param name="frmParent">父窗口对象</param>    

    76.             public FormDockTemplate(Form frmParent)   

    77.                 : this(frmParent, 4)   

    78.             {   

    79.             }   

    80.       

    81.             /// <summary>    

    82.             /// 构造函数   

    83.             /// </summary>    

    84.             /// <param name="frmParent">父窗口对象</param>    

    85.             /// <param name="iTolerantPixel">自动感知容差象素(当Mouse距离屏幕边缘多少象素时自动感知)</param>    

    86.             public FormDockTemplate(Form frmParent, int iTolerantPixel)   

    87.             {   

    88.                 m_iSensitiveAreaTolerantPixel = iTolerantPixel;   

    89.                 parentForm = frmParent;   

    90.                 parentForm.HandleCreated += new EventHandler(parentForm_HandleCreated);   

    91.                 parentForm.HandleDestroyed += new EventHandler(parentForm_HandleDestroyed);   

    92.                 parentForm.Load += new EventHandler(parentForm_Load);   

    93.                 parentForm.Move += new EventHandler(parentForm_Move);               

    94.                 parentForm.Resize += new EventHandler(parentForm_Resize);   

    95.       

    96.                 //初始化窗体的启动信息:如上次关闭时窗体的大小及位置   

    97.                 InitialFormStartInfo();   

    98.             }   

    99.       

    100.         /// <summary>   

    101.         /// 初始化窗体启动信息,通过反序列化完成   

    102.         /// </summary>   

    103.         void InitialFormStartInfo()   

    104.         {   

    105.             try  

    106.             {   

    107.                 m_oFormStartInfo = new FormStartInfo(parentForm);   

    108.                 FormStartInfo.Deserialize(ref m_oFormStartInfo);                   

    109.             }   

    110.             catch  

    111.             {   

    112.                 m_oFormStartInfo.FormLocation = parentForm.Location;   

    113.                 m_oFormStartInfo.FormSize = new Size(parentForm.Width, parentForm.Height);   

    114.             }   

    115.         }  

    116.         #endregion  

    117.  

    118.         #region 窗体事件处理   

    119.         void parentForm_Load(object sender, EventArgs e)   

    120.         {   

    121.             //初始化感知区域   

    122.             InitialDockArea();   

    123.   

    124.             //初始化时设置窗口大小及位置   

    125.             parentForm.Location = m_oFormStartInfo.FormLocation;   

    126.             parentForm.Size = m_oFormStartInfo.FormSize;   

    127.   

    128.             //定时器初始化   

    129.             m_tmrHideWindow = new Timer();   

    130.             m_tmrHideWindow.Interval = 100;   

    131.             m_tmrHideWindow.Enabled = true;   

    132.             m_tmrHideWindow.Tick += new EventHandler(m_tmrHideWindow_Tick);   

    133.         }   

    134.   

    135.         void parentForm_Resize(object sender, EventArgs e)   

    136.         {   

    137.             m_oFormStartInfo.FormSize = parentForm.Size;   

    138.         }   

    139.   

    140.         void parentForm_Move(object sender, EventArgs e)   

    141.         {   

    142.             //当左键按下时并且当前鼠标位置处于窗口标题栏区域内,则认为是合法窗口移动,启用自动感知功能   

    143.             if (Control.MouseButtons == MouseButtons.Left && FormTitleRect.Contains(CurrentMousePos))   

    144.             {   

    145.                 SetFormDockPos();                   

    146.             }   

    147.         }   

    148.           

    149.         void parentForm_HandleDestroyed(object sender, EventArgs e)   

    150.         {   

    151.             //销毁定时器   

    152.             m_tmrHideWindow.Enabled = false;   

    153.             m_tmrHideWindow.Stop();   

    154.             m_tmrHideWindow.Dispose();   

    155.   

    156.             //窗口关闭时,保存窗口的大小位置及停靠信息   

    157.             if (m_iDockStyle == Enu_FormDockStyle.None)   

    158.             {   

    159.                 m_oFormStartInfo.FormLocation = parentForm.Location;   

    160.                 m_oFormStartInfo.FormSize = parentForm.Size;   

    161.             }   

    162.             FormStartInfo.Serialize(m_oFormStartInfo);   

    163.   

    164.             //释放本类关联的窗口句柄   

    165.             ReleaseHandle();   

    166.         }   

    167.   

    168.         void parentForm_HandleCreated(object sender, EventArgs e)   

    169.         {   

    170.             AssignHandle(((Form)sender).Handle);   

    171.         }   

    172.   

    173.         void m_tmrHideWindow_Tick(object sender, EventArgs e)   

    174.         {   

    175.             if (m_oFormStartInfo.DockStyle != Enu_FormDockStyle.None)   

    176.             {   

    177.                 //为了提升显示效率,只有处于如下两种情况时,才需要重新显示窗体   

    178.                 //1、窗体可见但鼠标已经移出窗体外   

    179.                 //2、窗体不可见但鼠标已经移入窗体内   

    180.                 bool bNeedReshow = (m_oFormStartInfo.FormVisible && IsMouseOutForm()) ||   

    181.                     (!m_oFormStartInfo.FormVisible && !IsMouseOutForm());   

    182.                 if (bNeedReshow)   

    183.                     m_oFormStartInfo.ShowDockWindow(parentForm.Handle, !IsMouseOutForm());   

    184.             }   

    185.         }  

    186.         #endregion  

    187.  

    188.         #region 私有函数   

    189.         private void InitialDockArea()   

    190.         {   

    191.             //获取屏幕可用区域                

    192.             User32.RECT rectWorkArea = new User32.RECT();   

    193.             User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0);   

    194.             Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top);   

    195.             Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds;   

    196.   

    197.             //容差值,表示鼠标移动到边界若干象素里即可以自动感知停靠位置                

    198.             m_rcLeft = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);   

    199.             m_rcTop = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, rcWorkArea.Width, m_iSensitiveAreaTolerantPixel);   

    200.             m_rcRight = new Rectangle(rcWorkArea.Width - rcWorkArea.Left - m_iSensitiveAreaTolerantPixel, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);   

    201.             m_rcBottom = new Rectangle(rcScreenArea.Left, rcScreenArea.Bottom - rcScreenArea.Top - m_iSensitiveAreaTolerantPixel, rcScreenArea.Width, m_iSensitiveAreaTolerantPixel);   

    202.         }   

    203.            

    204.         /// <summary>    

    205.         /// 鼠标按下时未放开的时候,设置窗体停靠时的位置   

    206.         /// </summary>    

    207.         void SetFormDockPos()   

    208.         {   

    209.             m_iDockStyle = Enu_FormDockStyle.None;   

    210.   

    211.             //根据不同的停靠方式来重置窗体位置   

    212.             if (m_rcLeft.Contains(CurrentMousePos))   

    213.             {   

    214.                 parentForm.Location = m_rcLeft.Location;   

    215.                 parentForm.Height = m_rcLeft.Height;   

    216.   

    217.                 m_iDockStyle = Enu_FormDockStyle.Left;   

    218.             }   

    219.             else if (m_rcTop.Contains(CurrentMousePos))   

    220.             {   

    221.                 parentForm.Location = new Point(parentForm.Location.X, m_rcTop.Top);   

    222.   

    223.                 m_iDockStyle = Enu_FormDockStyle.Top;   

    224.             }   

    225.             else if (m_rcRight.Contains(CurrentMousePos))   

    226.             {   

    227.                 parentForm.Location = new Point(m_rcRight.Right - parentForm.Width, m_rcRight.Top);   

    228.                 parentForm.Height = m_rcRight.Height;   

    229.   

    230.                 m_iDockStyle = Enu_FormDockStyle.Right;   

    231.             }   

    232.             else if (m_rcBottom.Contains(CurrentMousePos))   

    233.             {   

    234.                 parentForm.Location = new Point(parentForm.Location.X, m_rcBottom.Bottom - parentForm.Height);   

    235.   

    236.                 m_iDockStyle = Enu_FormDockStyle.Bottom;   

    237.             }   

    238.   

    239.             m_oFormStartInfo.DockStyle = m_iDockStyle;   

    240.             m_oFormStartInfo.FormLocation = parentForm.Location;               

    241.         }   

    242.   

    243.         /// <summary>    

    244.         /// 表明当前鼠标位置是否已经移出窗体外   

    245.         /// </summary>    

    246.         /// <returns></returns>    

    247.         private bool IsMouseOutForm()   

    248.         {   

    249.             //获取当前鼠标的屏幕坐标               

    250.             User32.POINT ptMousePos = new User32.POINT();   

    251.             User32.GetCursorPos(ref ptMousePos);   

    252.             Point ptClientCursor = new Point(ptMousePos.X, ptMousePos.Y);   

    253.   

    254.             User32.RECT rcFormClient = new User32.RECT();   

    255.             User32.GetWindowRect(this.Handle, ref rcFormClient);   

    256.             Rectangle rcFormBound = new Rectangle(rcFormClient.left, rcFormClient.top, rcFormClient.right - rcFormClient.left, rcFormClient.bottom - rcFormClient.top);   

    257.             return !rcFormBound.Contains(ptClientCursor);   

    258.         }  

    259.         #endregion   

    260.     }   

    261. }  

    下面这个类是负责隐藏或显示窗体,并计算其位置和保存窗体的大小及位置

    FormStartInfo.cs 文件:

    1.         using System;    

    2.         using System.Collections.Generic;    

    3.         using System.Text;    

    4.         using System.IO;    

    5.         using System.Drawing;    

    6.         using System.Runtime.Serialization;    

    7.         using System.Runtime.Serialization.Formatters.Binary;    

    8.         using System.Windows.Forms;    

    9.           

    10.     namespace DockWindow   

    11.     {   

    12.         public enum Enu_FormDockStyle   

    13.         {   

    14.             None = 0,   

    15.             Left = 1,   

    16.             Top = 2,   

    17.             Right = 3,   

    18.             Bottom = 4,   

    19.         }   

    20.       

    21.         [Serializable]   

    22.         public class FormStartInfo   

    23.         {   

    24.             [NonSerialized]   

    25.             private Form m_frmDockWindow = null;   

    26.             private string m_strSerialFileName = string.Empty;   

    27.             private Size m_szFormSize = Size.Empty;   

    28.             private Point m_ptFormLocation = Point.Empty;   

    29.             private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None;   

    30.             private bool m_bFormVisible = false;   

    31.       

    32.       

    33.             /// <summary>    

    34.             /// 构造函数   

    35.             /// </summary>    

    36.             /// <param name="frmItem">停靠的窗体对象</param>    

    37.             public FormStartInfo(Form frmItem)   

    38.             {   

    39.                 try  

    40.                 {   

    41.                     m_frmDockWindow = frmItem;   

    42.       

    43.                     if (null == frmItem) m_strSerialFileName = "StartInfo.dat";   

    44.                     else m_strSerialFileName = frmItem.Name + frmItem.Text + "_StartInfo.dat";   

    45.                 }   

    46.                 catch { }   

    47.             }   

    48.       

    49.             /// <summary>    

    50.             /// 窗体大小   

    51.             /// </summary>    

    52.             public Size FormSize   

    53.             {   

    54.                 get { return m_szFormSize; }   

    55.                 internal set { m_szFormSize = value; }   

    56.             }   

    57.       

    58.             /// <summary>    

    59.             /// 窗体位置坐标   

    60.             /// </summary>    

    61.             public Point FormLocation   

    62.             {   

    63.                 get { return m_ptFormLocation; }   

    64.                 internal set { m_ptFormLocation = value; }   

    65.             }   

    66.       

    67.             /// <summary>    

    68.             /// 停靠方式   

    69.             /// </summary>    

    70.             public Enu_FormDockStyle DockStyle   

    71.             {   

    72.                 get { return m_iDockStyle; }   

    73.                 internal set { m_iDockStyle = value; }   

    74.             }   

    75.       

    76.             /// <summary>    

    77.             /// 表示窗体是否自动隐藏   

    78.             /// </summary>    

    79.             public bool FormVisible   

    80.             {   

    81.                 get { return m_bFormVisible; }   

    82.             }   

    83.             /// <summary>    

    84.             /// 序列化此类的实例信息   

    85.             /// </summary>    

    86.             /// <param name="frmStartInfo"></param>    

    87.             public static void Serialize(FormStartInfo frmStartInfo)   

    88.             {   

    89.                 using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.OpenOrCreate))   

    90.                 {   

    91.                     BinaryFormatter bf = new BinaryFormatter();   

    92.                     bf.Serialize(fs, frmStartInfo);   

    93.                 }   

    94.             }   

    95.       

    96.             /// <summary>    

    97.             /// 反序列化此类的实例信息   

    98.             /// </summary>    

    99.             /// <param name="frmStartInfo"></param>    

    100.         public static void Deserialize(ref FormStartInfo frmStartInfo)   

    101.         {   

    102.             FormStartInfo frmTemp = null;   

    103.   

    104.             if (null == frmStartInfo) return;   

    105.             using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.Open))   

    106.             {   

    107.                 BinaryFormatter bf = new BinaryFormatter();   

    108.                 frmTemp = (FormStartInfo)bf.Deserialize(fs);   

    109.                 if (null != frmTemp) frmStartInfo = frmTemp;   

    110.             }   

    111.         }   

    112.         /// <summary>    

    113.         /// 显示或隐藏停靠窗口   

    114.         /// </summary>    

    115.         public void ShowDockWindow(IntPtr hwnd, bool bVisible)   

    116.         {   

    117.             Point ptLocation = Point.Empty;   

    118.             Size szFormSize = Size.Empty;   

    119.   

    120.             m_bFormVisible = bVisible;   

    121.   

    122.             if (m_frmDockWindow == null) m_frmDockWindow = (Form)Control.FromHandle(hwnd);   

    123.             if (m_frmDockWindow == nullreturn;   

    124.   

    125.   

    126.   

    127.             GetDockWindowClientRect(ref ptLocation, ref szFormSize, bVisible);   

    128.   

    129.             m_frmDockWindow.TopMost = (m_iDockStyle != Enu_FormDockStyle.None);   

    130.             m_frmDockWindow.Location = ptLocation;   

    131.             m_frmDockWindow.Width = szFormSize.Width;   

    132.             m_frmDockWindow.Height = szFormSize.Height;   

    133.         }   

    134.         /// <summary>    

    135.         /// 根据当前窗体的停靠方式来计算出当前窗体的大小及位置   

    136.         /// </summary>    

    137.         /// <param name="ptLocation">窗体位置</param>    

    138.         /// <param name="szFormSize">窗体大小</param>    

    139.         /// <param name="bDockWindowVisible">显示还是隐藏</param>    

    140.         private void GetDockWindowClientRect(ref Point ptLocation, ref Size szFormSize, bool bDockWindowVisible)   

    141.         {   

    142.             int iTorrentPixel = 0;   

    143.             int iWindowTitleHeight = SystemInformation.CaptionHeight;   

    144.   

    145.   

    146.             //获取屏幕可用区域                

    147.             User32.RECT rectWorkArea = new User32.RECT();   

    148.             User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0);   

    149.             Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top);   

    150.             Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds;   

    151.   

    152.             if (m_ptFormLocation.X < 0) m_ptFormLocation.X = 0;   

    153.             if (m_ptFormLocation.Y < 0) m_ptFormLocation.Y = 0;   

    154.   

    155.             if (!bDockWindowVisible)   

    156.             {   

    157.                 switch (m_iDockStyle)   

    158.                 {   

    159.                     case Enu_FormDockStyle.None:   

    160.                         ptLocation = m_ptFormLocation;   

    161.                         szFormSize = m_szFormSize;   

    162.                         break;   

    163.                     case Enu_FormDockStyle.Left:   

    164.                         ptLocation = new Point(m_ptFormLocation.X - m_szFormSize.Width + SystemInformation.FrameBorderSize.Width + iTorrentPixel, rcWorkArea.Top);   

    165.                         szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height);   

    166.                         break;   

    167.                     case Enu_FormDockStyle.Top:   

    168.                         ptLocation = new Point(m_ptFormLocation.X, rcWorkArea.Top - m_szFormSize.Height +SystemInformation.FrameBorderSize.Width + iTorrentPixel);   

    169.                         szFormSize = m_szFormSize;   

    170.                         break;   

    171.                     case Enu_FormDockStyle.Right:   

    172.                         ptLocation = new Point(rcWorkArea.Width - rcWorkArea.Left - SystemInformation.FrameBorderSize.Width - iTorrentPixel, rcWorkArea.Top);   

    173.                         szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height);   

    174.                         break;   

    175.                     case Enu_FormDockStyle.Bottom:   

    176.                         ptLocation = new Point(m_ptFormLocation.X, rcScreenArea.Bottom - rcScreenArea.Top - SystemInformation.FrameBorderSize.Width - iTorrentPixel);   

    177.                         szFormSize = m_szFormSize;   

    178.                         break;   

    179.                     default:   

    180.                         ptLocation = m_ptFormLocation;   

    181.                         szFormSize = m_szFormSize;   

    182.                         break;   

    183.                 }   

    184.             }   

    185.             else  

    186.             {   

    187.                 ptLocation = m_ptFormLocation;   

    188.                 szFormSize = m_szFormSize;   

    189.             }   

    190.         }   

    191.     }   

    192. }  

    下面在贴上在此过程中引用的一些API函数:

    User32.cs文件:

    1.         using System;   

    2.         using System.Collections.Generic;   

    3.         using System.Linq;   

    4.         using System.Text;   

    5.         using System.Runtime.InteropServices;   

    6.           

    7.         namespace DockWindow   

    8.         {   

    9.             class User32   

    10.         {   

    11.             [StructLayout(LayoutKind.Sequential)]   

    12.             public struct POINT   

    13.             {   

    14.                 public int X;   

    15.                 public int Y;   

    16.             }   

    17.       

    18.             [StructLayout(LayoutKind.Sequential)]   

    19.             public struct RECT   

    20.             {   

    21.                 public int left;   

    22.                 public int top;   

    23.                 public int right;   

    24.                 public int bottom;    

    25.             }   

    26.       

    27.             public enum Enu_SystemParametersInfo_Action   

    28.             {   

    29.                 SPI_GETWORKAREA = 0x0030   

    30.             }   

    31.       

    32.             [DllImport("User32.dll")]   

    33.             public static extern bool GetCursorPos(ref POINT lpPoint);   

    34.       

    35.             [DllImport("User32.dll")]   

    36.             public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref RECT lpRect, uint fWinIni);   

    37.       

    38.             [DllImport("User32.dll")]   

    39.             public static extern bool GetWindowRect(IntPtr hwnd, ref RECT lpRect);   

    40.         }   

    41.     }  

    详细可以下载工程后自行研究

  • 相关阅读:
    头插法链表的基本操作:创建空链表,插入结点,遍历链表,求链表长度,查找结点,删除结点
    尾插法链表拆分
    头插法链表拆分
    尾插法创建链表
    头插法创建链表
    二维数组45度反斜线扫描分析。
    [LeetCode] Binary Search Tree Iterator | 二叉查找树迭代器
    只用递归翻转栈
    [LeetCode] Wiggle Sort II | 摆动排序
    今天回归刷题的日子
  • 原文地址:https://www.cnblogs.com/xianyin05/p/1509336.html
Copyright © 2020-2023  润新知