C#如何实现类似QQ那样靠边隐藏的功能

http://www.cnblogs.com/yechensi/archive/2009/08/02/1537145.html

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. namespace DockWindow
  7. {
  8. public class FormDockTemplate : NativeWindow
  9. {
  10. #region 私有字段
  11. /// <summary>
  12. /// 父级窗口实例
  13. /// </summary>
  14. private Form parentForm = null;
  15. /// <summary>
  16. /// 窗口实例的启动信息
  17. /// </summary>
  18. private FormStartInfo m_oFormStartInfo = null;
  19. /// <summary>
  20. /// 当前窗口可以停靠的方式
  21. /// </summary>
  22. private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None;
  23. /// <summary>
  24. /// 窗口停靠检测的定时器
  25. /// </summary>
  26. private Timer m_tmrHideWindow = null;
  27. /// <summary>
  28. /// 自动感知的矩形区域
  29. /// </summary>
  30. private Rectangle m_rcLeft = Rectangle.Empty;
  31. private Rectangle m_rcTop = Rectangle.Empty;
  32. private Rectangle m_rcRight = Rectangle.Empty;
  33. private Rectangle m_rcBottom = Rectangle.Empty;
  34. /// <summary>
  35. /// 感知区域的容差值,也就是当鼠标移动进入距边缘几个象素时进行自动捕获
  36. /// </summary>
  37. private int m_iSensitiveAreaTolerantPixel = 4;
  38. #endregion
  39. #region 字段属性
  40. /// <summary>
  41. /// 当前窗口的鼠标位置
  42. /// </summary>
  43. Point CurrentMousePos
  44. {
  45. get
  46. {
  47. //获取当前鼠标的屏幕坐标
  48. User32.POINT ptMousePos = new User32.POINT();
  49. User32.GetCursorPos(ref ptMousePos);
  50. return new Point(ptMousePos.X, ptMousePos.Y);
  51. }
  52. }
  53. Rectangle FormTitleRect
  54. {
  55. get { return new Rectangle(parentForm.Location, new Size(parentForm.Width, parentForm.Height - parentForm.ClientRectangle.Height)); }
  56. }
  57. /// <summary>
  58. /// 感应区域的容差设置,距离屏幕边缘多少象素时,开始自动感知
  59. /// </summary>
  60. public int TolerantPixel
  61. {
  62. get { return m_iSensitiveAreaTolerantPixel; }
  63. set { m_iSensitiveAreaTolerantPixel = value; }
  64. }
  65. #endregion
  66. #region 构造函数
  67. /// <summary>
  68. /// 构造函数
  69. /// </summary>
  70. /// <param name="frmParent">父窗口对象</param>
  71. public FormDockTemplate(Form frmParent)
  72. : this(frmParent, 4)
  73. {
  74. }
  75. /// <summary>
  76. /// 构造函数
  77. /// </summary>
  78. /// <param name="frmParent">父窗口对象</param>
  79. /// <param name="iTolerantPixel">自动感知容差象素(当Mouse距离屏幕边缘多少象素时自动感知)</param>
  80. public FormDockTemplate(Form frmParent, int iTolerantPixel)
  81. {
  82. m_iSensitiveAreaTolerantPixel = iTolerantPixel;
  83. parentForm = frmParent;
  84. parentForm.HandleCreated += new EventHandler(parentForm_HandleCreated);
  85. parentForm.HandleDestroyed += new EventHandler(parentForm_HandleDestroyed);
  86. parentForm.Load += new EventHandler(parentForm_Load);
  87. parentForm.Move += new EventHandler(parentForm_Move);
  88. parentForm.Resize += new EventHandler(parentForm_Resize);
  89. //初始化窗体的启动信息:如上次关闭时窗体的大小及位置
  90. InitialFormStartInfo();
  91. }
  92. /// <summary>
  93. /// 初始化窗体启动信息,通过反序列化完成
  94. /// </summary>
  95. void InitialFormStartInfo()
  96. {
  97. try
  98. {
  99. m_oFormStartInfo = new FormStartInfo(parentForm);
  100. FormStartInfo.Deserialize(ref m_oFormStartInfo);
  101. }
  102. catch
  103. {
  104. m_oFormStartInfo.FormLocation = parentForm.Location;
  105. m_oFormStartInfo.FormSize = new Size(parentForm.Width, parentForm.Height);
  106. }
  107. }
  108. #endregion
  109. #region 窗体事件处理
  110. void parentForm_Load(object sender, EventArgs e)
  111. {
  112. //初始化感知区域
  113. InitialDockArea();
  114. //初始化时设置窗口大小及位置
  115. parentForm.Location = m_oFormStartInfo.FormLocation;
  116. parentForm.Size = m_oFormStartInfo.FormSize;
  117. //定时器初始化
  118. m_tmrHideWindow = new Timer();
  119. m_tmrHideWindow.Interval = 100;
  120. m_tmrHideWindow.Enabled = true;
  121. m_tmrHideWindow.Tick += new EventHandler(m_tmrHideWindow_Tick);
  122. }
  123. void parentForm_Resize(object sender, EventArgs e)
  124. {
  125. m_oFormStartInfo.FormSize = parentForm.Size;
  126. }
  127. void parentForm_Move(object sender, EventArgs e)
  128. {
  129. //当左键按下时并且当前鼠标位置处于窗口标题栏区域内,则认为是合法窗口移动,启用自动感知功能
  130. if (Control.MouseButtons == MouseButtons.Left && FormTitleRect.Contains(CurrentMousePos))
  131. {
  132. SetFormDockPos();
  133. }
  134. }
  135. void parentForm_HandleDestroyed(object sender, EventArgs e)
  136. {
  137. //销毁定时器
  138. m_tmrHideWindow.Enabled = false;
  139. m_tmrHideWindow.Stop();
  140. m_tmrHideWindow.Dispose();
  141. //窗口关闭时,保存窗口的大小位置及停靠信息
  142. if (m_iDockStyle == Enu_FormDockStyle.None)
  143. {
  144. m_oFormStartInfo.FormLocation = parentForm.Location;
  145. m_oFormStartInfo.FormSize = parentForm.Size;
  146. }
  147. FormStartInfo.Serialize(m_oFormStartInfo);
  148. //释放本类关联的窗口句柄
  149. ReleaseHandle();
  150. }
  151. void parentForm_HandleCreated(object sender, EventArgs e)
  152. {
  153. AssignHandle(((Form)sender).Handle);
  154. }
  155. void m_tmrHideWindow_Tick(object sender, EventArgs e)
  156. {
  157. if (m_oFormStartInfo.DockStyle != Enu_FormDockStyle.None)
  158. {
  159. //为了提升显示效率,只有处于如下两种情况时,才需要重新显示窗体
  160. //1、窗体可见但鼠标已经移出窗体外
  161. //2、窗体不可见但鼠标已经移入窗体内
  162. bool bNeedReshow = (m_oFormStartInfo.FormVisible && IsMouseOutForm()) ||
  163. (!m_oFormStartInfo.FormVisible && !IsMouseOutForm());
  164. if (bNeedReshow)
  165. m_oFormStartInfo.ShowDockWindow(parentForm.Handle, !IsMouseOutForm());
  166. }
  167. }
  168. #endregion
  169. #region 私有函数
  170. private void InitialDockArea()
  171. {
  172. //获取屏幕可用区域
  173. User32.RECT rectWorkArea = new User32.RECT();
  174. User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0);
  175. Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top);
  176. Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds;
  177. //容差值,表示鼠标移动到边界若干象素里即可以自动感知停靠位置
  178. m_rcLeft = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);
  179. m_rcTop = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, rcWorkArea.Width, m_iSensitiveAreaTolerantPixel);
  180. m_rcRight = new Rectangle(rcWorkArea.Width - rcWorkArea.Left - m_iSensitiveAreaTolerantPixel, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);
  181. m_rcBottom = new Rectangle(rcScreenArea.Left, rcScreenArea.Bottom - rcScreenArea.Top - m_iSensitiveAreaTolerantPixel, rcScreenArea.Width, m_iSensitiveAreaTolerantPixel);
  182. }
  183. /// <summary>
  184. /// 鼠标按下时未放开的时候,设置窗体停靠时的位置
  185. /// </summary>
  186. void SetFormDockPos()
  187. {
  188. m_iDockStyle = Enu_FormDockStyle.None;
  189. //根据不同的停靠方式来重置窗体位置
  190. if (m_rcLeft.Contains(CurrentMousePos))
  191. {
  192. parentForm.Location = m_rcLeft.Location;
  193. parentForm.Height = m_rcLeft.Height;
  194. m_iDockStyle = Enu_FormDockStyle.Left;
  195. }
  196. else if (m_rcTop.Contains(CurrentMousePos))
  197. {
  198. parentForm.Location = new Point(parentForm.Location.X, m_rcTop.Top);
  199. m_iDockStyle = Enu_FormDockStyle.Top;
  200. }
  201. else if (m_rcRight.Contains(CurrentMousePos))
  202. {
  203. parentForm.Location = new Point(m_rcRight.Right - parentForm.Width, m_rcRight.Top);
  204. parentForm.Height = m_rcRight.Height;
  205. m_iDockStyle = Enu_FormDockStyle.Right;
  206. }
  207. else if (m_rcBottom.Contains(CurrentMousePos))
  208. {
  209. parentForm.Location = new Point(parentForm.Location.X, m_rcBottom.Bottom - parentForm.Height);
  210. m_iDockStyle = Enu_FormDockStyle.Bottom;
  211. }
  212. m_oFormStartInfo.DockStyle = m_iDockStyle;
  213. m_oFormStartInfo.FormLocation = parentForm.Location;
  214. }
  215. /// <summary>
  216. /// 表明当前鼠标位置是否已经移出窗体外
  217. /// </summary>
  218. /// <returns></returns>
  219. private bool IsMouseOutForm()
  220. {
  221. //获取当前鼠标的屏幕坐标
  222. User32.POINT ptMousePos = new User32.POINT();
  223. User32.GetCursorPos(ref ptMousePos);
  224. Point ptClientCursor = new Point(ptMousePos.X, ptMousePos.Y);
  225. User32.RECT rcFormClient = new User32.RECT();
  226. User32.GetWindowRect(this.Handle, ref rcFormClient);
  227. Rectangle rcFormBound = new Rectangle(rcFormClient.left, rcFormClient.top, rcFormClient.right - rcFormClient.left, rcFormClient.bottom - rcFormClient.top);
  228. return !rcFormBound.Contains(ptClientCursor);
  229. }
  230. #endregion
  231. }
  232. }

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace DockWindow
{
public class FormDockTemplate : NativeWindow
{
#region 私有字段
/// <summary>
/// 父级窗口实例
/// </summary>
private Form parentForm = null;
/// <summary>
/// 窗口实例的启动信息
/// </summary>
private FormStartInfo m_oFormStartInfo = null;
/// <summary>
/// 当前窗口可以停靠的方式
/// </summary>
private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None;
/// <summary>
/// 窗口停靠检测的定时器
/// </summary>
private Timer m_tmrHideWindow = null;
/// <summary>
/// 自动感知的矩形区域
/// </summary>
private Rectangle m_rcLeft = Rectangle.Empty;
private Rectangle m_rcTop = Rectangle.Empty;
private Rectangle m_rcRight = Rectangle.Empty;
private Rectangle m_rcBottom = Rectangle.Empty;
/// <summary>
/// 感知区域的容差值,也就是当鼠标移动进入距边缘几个象素时进行自动捕获
/// </summary>
private int m_iSensitiveAreaTolerantPixel = 4;
#endregion

#region 字段属性
/// <summary>
/// 当前窗口的鼠标位置
/// </summary>
Point CurrentMousePos
{
get
{
//获取当前鼠标的屏幕坐标
User32.POINT ptMousePos = new User32.POINT();
User32.GetCursorPos(ref ptMousePos);
return new Point(ptMousePos.X, ptMousePos.Y);
}
}

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

/// <summary>
/// 感应区域的容差设置,距离屏幕边缘多少象素时,开始自动感知
/// </summary>
public int TolerantPixel
{
get { return m_iSensitiveAreaTolerantPixel; }
set { m_iSensitiveAreaTolerantPixel = value; }
}
#endregion

#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
/// <param name="frmParent">父窗口对象</param>
public FormDockTemplate(Form frmParent)
: this(frmParent, 4)
{
}

/// <summary>
/// 构造函数
/// </summary>
/// <param name="frmParent">父窗口对象</param>
/// <param name="iTolerantPixel">自动感知容差象素(当Mouse距离屏幕边缘多少象素时自动感知)</param>
public FormDockTemplate(Form frmParent, int iTolerantPixel)
{
m_iSensitiveAreaTolerantPixel = iTolerantPixel;
parentForm = frmParent;
parentForm.HandleCreated += new EventHandler(parentForm_HandleCreated);
parentForm.HandleDestroyed += new EventHandler(parentForm_HandleDestroyed);
parentForm.Load += new EventHandler(parentForm_Load);
parentForm.Move += new EventHandler(parentForm_Move);
parentForm.Resize += new EventHandler(parentForm_Resize);

//初始化窗体的启动信息:如上次关闭时窗体的大小及位置
InitialFormStartInfo();
}

/// <summary>
/// 初始化窗体启动信息,通过反序列化完成
/// </summary>
void InitialFormStartInfo()
{
try
{
m_oFormStartInfo = new FormStartInfo(parentForm);
FormStartInfo.Deserialize(ref m_oFormStartInfo);
}
catch
{
m_oFormStartInfo.FormLocation = parentForm.Location;
m_oFormStartInfo.FormSize = new Size(parentForm.Width, parentForm.Height);
}
}
#endregion

#region 窗体事件处理
void parentForm_Load(object sender, EventArgs e)
{
//初始化感知区域
InitialDockArea();

//初始化时设置窗口大小及位置
parentForm.Location = m_oFormStartInfo.FormLocation;
parentForm.Size = m_oFormStartInfo.FormSize;

//定时器初始化
m_tmrHideWindow = new Timer();
m_tmrHideWindow.Interval = 100;
m_tmrHideWindow.Enabled = true;
m_tmrHideWindow.Tick += new EventHandler(m_tmrHideWindow_Tick);
}

void parentForm_Resize(object sender, EventArgs e)
{
m_oFormStartInfo.FormSize = parentForm.Size;
}

void parentForm_Move(object sender, EventArgs e)
{
//当左键按下时并且当前鼠标位置处于窗口标题栏区域内,则认为是合法窗口移动,启用自动感知功能
if (Control.MouseButtons == MouseButtons.Left && FormTitleRect.Contains(CurrentMousePos))
{
SetFormDockPos();
}
}

void parentForm_HandleDestroyed(object sender, EventArgs e)
{
//销毁定时器
m_tmrHideWindow.Enabled = false;
m_tmrHideWindow.Stop();
m_tmrHideWindow.Dispose();

//窗口关闭时,保存窗口的大小位置及停靠信息
if (m_iDockStyle == Enu_FormDockStyle.None)
{
m_oFormStartInfo.FormLocation = parentForm.Location;
m_oFormStartInfo.FormSize = parentForm.Size;
}
FormStartInfo.Serialize(m_oFormStartInfo);

//释放本类关联的窗口句柄
ReleaseHandle();
}

void parentForm_HandleCreated(object sender, EventArgs e)
{
AssignHandle(((Form)sender).Handle);
}

void m_tmrHideWindow_Tick(object sender, EventArgs e)
{
if (m_oFormStartInfo.DockStyle != Enu_FormDockStyle.None)
{
//为了提升显示效率,只有处于如下两种情况时,才需要重新显示窗体
//1、窗体可见但鼠标已经移出窗体外
//2、窗体不可见但鼠标已经移入窗体内
bool bNeedReshow = (m_oFormStartInfo.FormVisible && IsMouseOutForm()) ||
(!m_oFormStartInfo.FormVisible && !IsMouseOutForm());
if (bNeedReshow)
m_oFormStartInfo.ShowDockWindow(parentForm.Handle, !IsMouseOutForm());
}
}
#endregion

#region 私有函数
private void InitialDockArea()
{
//获取屏幕可用区域
User32.RECT rectWorkArea = new User32.RECT();
User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0);
Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top);
Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds;

//容差值,表示鼠标移动到边界若干象素里即可以自动感知停靠位置
m_rcLeft = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);
m_rcTop = new Rectangle(rcWorkArea.Left, rcWorkArea.Top, rcWorkArea.Width, m_iSensitiveAreaTolerantPixel);
m_rcRight = new Rectangle(rcWorkArea.Width - rcWorkArea.Left - m_iSensitiveAreaTolerantPixel, rcWorkArea.Top, m_iSensitiveAreaTolerantPixel, rcWorkArea.Height);
m_rcBottom = new Rectangle(rcScreenArea.Left, rcScreenArea.Bottom - rcScreenArea.Top - m_iSensitiveAreaTolerantPixel, rcScreenArea.Width, m_iSensitiveAreaTolerantPixel);
}

/// <summary>
/// 鼠标按下时未放开的时候,设置窗体停靠时的位置
/// </summary>
void SetFormDockPos()
{
m_iDockStyle = Enu_FormDockStyle.None;

//根据不同的停靠方式来重置窗体位置
if (m_rcLeft.Contains(CurrentMousePos))
{
parentForm.Location = m_rcLeft.Location;
parentForm.Height = m_rcLeft.Height;

m_iDockStyle = Enu_FormDockStyle.Left;
}
else if (m_rcTop.Contains(CurrentMousePos))
{
parentForm.Location = new Point(parentForm.Location.X, m_rcTop.Top);

m_iDockStyle = Enu_FormDockStyle.Top;
}
else if (m_rcRight.Contains(CurrentMousePos))
{
parentForm.Location = new Point(m_rcRight.Right - parentForm.Width, m_rcRight.Top);
parentForm.Height = m_rcRight.Height;

m_iDockStyle = Enu_FormDockStyle.Right;
}
else if (m_rcBottom.Contains(CurrentMousePos))
{
parentForm.Location = new Point(parentForm.Location.X, m_rcBottom.Bottom - parentForm.Height);

m_iDockStyle = Enu_FormDockStyle.Bottom;
}

m_oFormStartInfo.DockStyle = m_iDockStyle;
m_oFormStartInfo.FormLocation = parentForm.Location;
}

/// <summary>
/// 表明当前鼠标位置是否已经移出窗体外
/// </summary>
/// <returns></returns>
private bool IsMouseOutForm()
{
//获取当前鼠标的屏幕坐标
User32.POINT ptMousePos = new User32.POINT();
User32.GetCursorPos(ref ptMousePos);
Point ptClientCursor = new Point(ptMousePos.X, ptMousePos.Y);

User32.RECT rcFormClient = new User32.RECT();
User32.GetWindowRect(this.Handle, ref rcFormClient);
Rectangle rcFormBound = new Rectangle(rcFormClient.left, rcFormClient.top, rcFormClient.right - rcFormClient.left, rcFormClient.bottom - rcFormClient.top);
return !rcFormBound.Contains(ptClientCursor);
}
#endregion
}
}

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

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. namespace DockWindow
  10. {
  11. public enum Enu_FormDockStyle
  12. {
  13. None = 0,
  14. Left = 1,
  15. Top = 2,
  16. Right = 3,
  17. Bottom = 4,
  18. }
  19. [Serializable]
  20. public class FormStartInfo
  21. {
  22. [NonSerialized]
  23. private Form m_frmDockWindow = null;
  24. private string m_strSerialFileName = string.Empty;
  25. private Size m_szFormSize = Size.Empty;
  26. private Point m_ptFormLocation = Point.Empty;
  27. private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None;
  28. private bool m_bFormVisible = false;
  29. /// <summary>
  30. /// 构造函数
  31. /// </summary>
  32. /// <param name="frmItem">停靠的窗体对象</param>
  33. public FormStartInfo(Form frmItem)
  34. {
  35. try
  36. {
  37. m_frmDockWindow = frmItem;
  38. if (null == frmItem) m_strSerialFileName = "StartInfo.dat";
  39. else m_strSerialFileName = frmItem.Name + frmItem.Text + "_StartInfo.dat";
  40. }
  41. catch { }
  42. }
  43. /// <summary>
  44. /// 窗体大小
  45. /// </summary>
  46. public Size FormSize
  47. {
  48. get { return m_szFormSize; }
  49. internal set { m_szFormSize = value; }
  50. }
  51. /// <summary>
  52. /// 窗体位置坐标
  53. /// </summary>
  54. public Point FormLocation
  55. {
  56. get { return m_ptFormLocation; }
  57. internal set { m_ptFormLocation = value; }
  58. }
  59. /// <summary>
  60. /// 停靠方式
  61. /// </summary>
  62. public Enu_FormDockStyle DockStyle
  63. {
  64. get { return m_iDockStyle; }
  65. internal set { m_iDockStyle = value; }
  66. }
  67. /// <summary>
  68. /// 表示窗体是否自动隐藏
  69. /// </summary>
  70. public bool FormVisible
  71. {
  72. get { return m_bFormVisible; }
  73. }
  74. /// <summary>
  75. /// 序列化此类的实例信息
  76. /// </summary>
  77. /// <param name="frmStartInfo"></param>
  78. public static void Serialize(FormStartInfo frmStartInfo)
  79. {
  80. using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.OpenOrCreate))
  81. {
  82. BinaryFormatter bf = new BinaryFormatter();
  83. bf.Serialize(fs, frmStartInfo);
  84. }
  85. }
  86. /// <summary>
  87. /// 反序列化此类的实例信息
  88. /// </summary>
  89. /// <param name="frmStartInfo"></param>
  90. public static void Deserialize(ref FormStartInfo frmStartInfo)
  91. {
  92. FormStartInfo frmTemp = null;
  93. if (null == frmStartInfo) return;
  94. using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.Open))
  95. {
  96. BinaryFormatter bf = new BinaryFormatter();
  97. frmTemp = (FormStartInfo)bf.Deserialize(fs);
  98. if (null != frmTemp) frmStartInfo = frmTemp;
  99. }
  100. }
  101. /// <summary>
  102. /// 显示或隐藏停靠窗口
  103. /// </summary>
  104. public void ShowDockWindow(IntPtr hwnd, bool bVisible)
  105. {
  106. Point ptLocation = Point.Empty;
  107. Size szFormSize = Size.Empty;
  108. m_bFormVisible = bVisible;
  109. if (m_frmDockWindow == null) m_frmDockWindow = (Form)Control.FromHandle(hwnd);
  110. if (m_frmDockWindow == null) return;
  111. GetDockWindowClientRect(ref ptLocation, ref szFormSize, bVisible);
  112. m_frmDockWindow.TopMost = (m_iDockStyle != Enu_FormDockStyle.None);
  113. m_frmDockWindow.Location = ptLocation;
  114. m_frmDockWindow.Width = szFormSize.Width;
  115. m_frmDockWindow.Height = szFormSize.Height;
  116. }
  117. /// <summary>
  118. /// 根据当前窗体的停靠方式来计算出当前窗体的大小及位置
  119. /// </summary>
  120. /// <param name="ptLocation">窗体位置</param>
  121. /// <param name="szFormSize">窗体大小</param>
  122. /// <param name="bDockWindowVisible">显示还是隐藏</param>
  123. private void GetDockWindowClientRect(ref Point ptLocation, ref Size szFormSize, bool bDockWindowVisible)
  124. {
  125. int iTorrentPixel = 0;
  126. int iWindowTitleHeight = SystemInformation.CaptionHeight;
  127. //获取屏幕可用区域
  128. User32.RECT rectWorkArea = new User32.RECT();
  129. User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0);
  130. Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top);
  131. Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds;
  132. if (m_ptFormLocation.X < 0) m_ptFormLocation.X = 0;
  133. if (m_ptFormLocation.Y < 0) m_ptFormLocation.Y = 0;
  134. if (!bDockWindowVisible)
  135. {
  136. switch (m_iDockStyle)
  137. {
  138. case Enu_FormDockStyle.None:
  139. ptLocation = m_ptFormLocation;
  140. szFormSize = m_szFormSize;
  141. break;
  142. case Enu_FormDockStyle.Left:
  143. ptLocation = new Point(m_ptFormLocation.X - m_szFormSize.Width + SystemInformation.FrameBorderSize.Width + iTorrentPixel, rcWorkArea.Top);
  144. szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height);
  145. break;
  146. case Enu_FormDockStyle.Top:
  147. ptLocation = new Point(m_ptFormLocation.X, rcWorkArea.Top - m_szFormSize.Height +SystemInformation.FrameBorderSize.Width + iTorrentPixel);
  148. szFormSize = m_szFormSize;
  149. break;
  150. case Enu_FormDockStyle.Right:
  151. ptLocation = new Point(rcWorkArea.Width - rcWorkArea.Left - SystemInformation.FrameBorderSize.Width - iTorrentPixel, rcWorkArea.Top);
  152. szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height);
  153. break;
  154. case Enu_FormDockStyle.Bottom:
  155. ptLocation = new Point(m_ptFormLocation.X, rcScreenArea.Bottom - rcScreenArea.Top - SystemInformation.FrameBorderSize.Width - iTorrentPixel);
  156. szFormSize = m_szFormSize;
  157. break;
  158. default:
  159. ptLocation = m_ptFormLocation;
  160. szFormSize = m_szFormSize;
  161. break;
  162. }
  163. }
  164. else
  165. {
  166. ptLocation = m_ptFormLocation;
  167. szFormSize = m_szFormSize;
  168. }
  169. }
  170. }
  171. }

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

namespace DockWindow
{
public enum Enu_FormDockStyle
{
None = 0,
Left = 1,
Top = 2,
Right = 3,
Bottom = 4,
}

[Serializable]
public class FormStartInfo
{
[NonSerialized]
private Form m_frmDockWindow = null;
private string m_strSerialFileName = string.Empty;
private Size m_szFormSize = Size.Empty;
private Point m_ptFormLocation = Point.Empty;
private Enu_FormDockStyle m_iDockStyle = Enu_FormDockStyle.None;
private bool m_bFormVisible = false;

/// <summary>
/// 构造函数
/// </summary>
/// <param name="frmItem">停靠的窗体对象</param>
public FormStartInfo(Form frmItem)
{
try
{
m_frmDockWindow = frmItem;

if (null == frmItem) m_strSerialFileName = "StartInfo.dat";
else m_strSerialFileName = frmItem.Name + frmItem.Text + "_StartInfo.dat";
}
catch { }
}

/// <summary>
/// 窗体大小
/// </summary>
public Size FormSize
{
get { return m_szFormSize; }
internal set { m_szFormSize = value; }
}

/// <summary>
/// 窗体位置坐标
/// </summary>
public Point FormLocation
{
get { return m_ptFormLocation; }
internal set { m_ptFormLocation = value; }
}

/// <summary>
/// 停靠方式
/// </summary>
public Enu_FormDockStyle DockStyle
{
get { return m_iDockStyle; }
internal set { m_iDockStyle = value; }
}

/// <summary>
/// 表示窗体是否自动隐藏
/// </summary>
public bool FormVisible
{
get { return m_bFormVisible; }
}
/// <summary>
/// 序列化此类的实例信息
/// </summary>
/// <param name="frmStartInfo"></param>
public static void Serialize(FormStartInfo frmStartInfo)
{
using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.OpenOrCreate))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, frmStartInfo);
}
}

/// <summary>
/// 反序列化此类的实例信息
/// </summary>
/// <param name="frmStartInfo"></param>
public static void Deserialize(ref FormStartInfo frmStartInfo)
{
FormStartInfo frmTemp = null;

if (null == frmStartInfo) return;
using (FileStream fs = new FileStream(frmStartInfo.m_strSerialFileName, FileMode.Open))
{
BinaryFormatter bf = new BinaryFormatter();
frmTemp = (FormStartInfo)bf.Deserialize(fs);
if (null != frmTemp) frmStartInfo = frmTemp;
}
}
/// <summary>
/// 显示或隐藏停靠窗口
/// </summary>
public void ShowDockWindow(IntPtr hwnd, bool bVisible)
{
Point ptLocation = Point.Empty;
Size szFormSize = Size.Empty;

m_bFormVisible = bVisible;

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

GetDockWindowClientRect(ref ptLocation, ref szFormSize, bVisible);

m_frmDockWindow.TopMost = (m_iDockStyle != Enu_FormDockStyle.None);
m_frmDockWindow.Location = ptLocation;
m_frmDockWindow.Width = szFormSize.Width;
m_frmDockWindow.Height = szFormSize.Height;
}
/// <summary>
/// 根据当前窗体的停靠方式来计算出当前窗体的大小及位置
/// </summary>
/// <param name="ptLocation">窗体位置</param>
/// <param name="szFormSize">窗体大小</param>
/// <param name="bDockWindowVisible">显示还是隐藏</param>
private void GetDockWindowClientRect(ref Point ptLocation, ref Size szFormSize, bool bDockWindowVisible)
{
int iTorrentPixel = 0;
int iWindowTitleHeight = SystemInformation.CaptionHeight;

//获取屏幕可用区域
User32.RECT rectWorkArea = new User32.RECT();
User32.SystemParametersInfo((uint)User32.Enu_SystemParametersInfo_Action.SPI_GETWORKAREA, 0, ref rectWorkArea, 0);
Rectangle rcWorkArea = new Rectangle(rectWorkArea.left, rectWorkArea.top, rectWorkArea.right - rectWorkArea.left, rectWorkArea.bottom - rectWorkArea.top);
Rectangle rcScreenArea = Screen.PrimaryScreen.Bounds;

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

if (!bDockWindowVisible)
{
switch (m_iDockStyle)
{
case Enu_FormDockStyle.None:
ptLocation = m_ptFormLocation;
szFormSize = m_szFormSize;
break;
case Enu_FormDockStyle.Left:
ptLocation = new Point(m_ptFormLocation.X - m_szFormSize.Width + SystemInformation.FrameBorderSize.Width + iTorrentPixel, rcWorkArea.Top);
szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height);
break;
case Enu_FormDockStyle.Top:
ptLocation = new Point(m_ptFormLocation.X, rcWorkArea.Top - m_szFormSize.Height +SystemInformation.FrameBorderSize.Width + iTorrentPixel);
szFormSize = m_szFormSize;
break;
case Enu_FormDockStyle.Right:
ptLocation = new Point(rcWorkArea.Width - rcWorkArea.Left - SystemInformation.FrameBorderSize.Width - iTorrentPixel, rcWorkArea.Top);
szFormSize = new Size(m_szFormSize.Width, rcWorkArea.Height);
break;
case Enu_FormDockStyle.Bottom:
ptLocation = new Point(m_ptFormLocation.X, rcScreenArea.Bottom - rcScreenArea.Top - SystemInformation.FrameBorderSize.Width - iTorrentPixel);
szFormSize = m_szFormSize;
break;
default:
ptLocation = m_ptFormLocation;
szFormSize = m_szFormSize;
break;
}
}
else
{
ptLocation = m_ptFormLocation;
szFormSize = m_szFormSize;
}
}
}
}

下面在贴上在此过程中引用的一些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. namespace DockWindow
  7. {
  8. class User32
  9. {
  10. [StructLayout(LayoutKind.Sequential)]
  11. public struct POINT
  12. {
  13. public int X;
  14. public int Y;
  15. }
  16. [StructLayout(LayoutKind.Sequential)]
  17. public struct RECT
  18. {
  19. public int left;
  20. public int top;
  21. public int right;
  22. public int bottom;
  23. }
  24. public enum Enu_SystemParametersInfo_Action
  25. {
  26. SPI_GETWORKAREA = 0x0030
  27. }
  28. [DllImport("User32.dll")]
  29. public static extern bool GetCursorPos(ref POINT lpPoint);
  30. [DllImport("User32.dll")]
  31. public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref RECT lpRect, uint fWinIni);
  32. [DllImport("User32.dll")]
  33. public static extern bool GetWindowRect(IntPtr hwnd, ref RECT lpRect);
  34. }
  35. }
上一篇:linux解压


下一篇:为SRS流媒体服务器添加HLS加密功能(附源码)