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文件:

view plaincopy to clipboardprint?

  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 文件:

view plaincopy to clipboardprint?

  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文件:

view plaincopy to clipboardprint?

  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. }
时间: 2024-10-13 01:40:09

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

实现类似QQ自拍头像的功能(demo源码)

在很多软件系统中,都允许用户设置自己的头像,甚至可以直接使用摄像头照相作为自己的头像,就像QQ的自拍头像功能一样. 这种功能是如何实现的了?最直接的,我们可以使用Windows提供的VFW技术或DirectX技术来捕获摄像头采集到的视频和图片.但是,无论使用这两种技术中的哪一个,要实现一个兼容所有摄像头而又运行稳定的拍照功能,都不是那么容易.幸运的是,OMCS已经内置集成了这种功能的一个WinForm控件PhotoPanel,我们可以直接拿来使用. PhotoPanel控件的主要接口如下图所示:

【C# WinForm】类似QQ靠近屏幕边缘缩放功能

当窗体离屏幕四周一定距离时,改变窗体位置,引导窗体靠边:靠边后,当鼠标离开窗体时,改变窗体位置,窗体隐藏,凸出一点在屏幕内:隐藏后,当鼠标移到窗体时,窗体显示. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.

C#实现类似QQ的隐藏浮动窗体、消息闪动

功能简介 当语音客服系统登录成功进入主界面时,本聊天工具将会自动隐藏在左下角位置,当鼠标移动到左下角时,自动弹出,当鼠标移开聊天窗体时,自动隐藏.如果想让聊天窗体固定在桌面,只要拖动一下聊天窗口,让它不停留在边界位置就可以了.隐藏和悬浮方式类型QQ. 1. 系统主界面 当点击最小化按钮时, 在电脑右下角会显示任务图标,点击任务图标,将会在左下角位置弹出. 主界面各部分介绍: a) 消息列表:该区域的功能主要是显示消息记录. b) 发送消息:输入要发送的消息进行发送,默认群聊,输入消息后,按回车键

winform-实现类似QQ停靠桌面上边缘隐藏的效果

//实现类似QQ停靠桌面上边缘隐藏的效果! private void timer1_Tick(object sender, EventArgs e) { System.Drawing.Point pp = new Point(Cursor.Position.X, Cursor.Position.Y);//获取鼠标在屏幕的坐标点 Rectangle Rects = new Rectangle(this.Left, this.Top, this.Left + this.Width, this.Top

WinForm实现类似QQ停靠,显示隐藏过程添加特效效果

原文:WinForm实现类似QQ停靠,显示隐藏过程添加特效效果 这可能是个老题长谈的问题了,只是在项目中会用到这个效果,所以今天做个记录.大家见了别喷我.在项目中的需求是这样的. 打开程序,在屏幕的右下角会显示一个窗体,一般情况下该窗体会隐藏停靠在右边,只露出很小部分,当鼠标移动到这个很小部分时,窗体全部显示,显示过程是从右边滑动到左边,当鼠标离开窗体时,窗体需要隐藏在右边,只露出很小部分,隐藏过程是从左边滑动到右边. 实现此类效果我碰到的连个难点是:1.如何判断鼠标离开了窗体?2.窗体显示隐藏

基于Qt的类似QQ好友列表抽屉效果的实现

前段时间在忙毕业设计,所以一直没有更新博客.今天答辩完以后,将对我的毕业设计进行模块展示,供Qt初学者进行参考. 毕业设计题目:Linux系统下基于Qt的局域网即时通信系统设计与实现 其中我有一个类似于QQ的好友列表,然后对好友可以进行分组管理,毕设中具体效果图如下: 网上查寻到的设计思路: 1.采用QToolBox的方式,虽然看起来有点样子,但是并不是我们所熟悉的好友列表,比如:http://blog.csdn.net/qianguozheng/article/details/6719074

使用plupload做一个类似qq邮箱附件上传的效果

公司项目中使用的框架是springmvc+hibernate+spring,目前需要做一个类似qq邮箱附件上传的功能,暂时只是上传小类型的附件 处理过程和解决方案都需要添加附件,处理过程和解决方案都可以添加多个附件,也可一个都不添加 以其中一个为例:(文件保存到了数据库中),有关plupload的内容可参考:http://www.360doc.com/content/14/0714/03/552866_394228686.shtml 首先是po package cn.com.plupload.p

qt实现类似QQ伸缩窗口--鼠标事件应用

上一章节讲了qt鼠标事件实现,获取鼠标参数的方法.这一讲主要讲怎么应用上讲的鼠标事件实现一个小功能. qq好友对话框右侧 未展开时如图: 鼠标移动到 “隐藏侧边”处单击可以隐藏侧边,隐藏后效果如图: 实现的范例效果如下 1.一般情况 2.鼠标移动到中间分割线中间区域时,效果 3.单击红色按钮后,效果 4.鼠标移动到边界,效果 下面讲解实现过程:一般情况在QT中,这种伸缩窗体的实现有两种方法:一种是是直接用QSplitter分割器实现:另一种直接用布局管理器自己实现.本节用的是第二种方法实现的.布

在类似qq或者微信聊天中。如何根据不同的手机发送图片

原文:在类似qq或者微信聊天中.如何根据不同的手机发送图片   前一段时间,公司自己要求做多客服开发,但是对于发送图片这一块,当时很苦恼,我用自己的手机(米2)测试,不管是本地,还是云相册,最新照片.都没有问题,但是测试那边一直说图片发不了,而且还会崩.很纳闷.      后来经过debug,发现4.4以上的手机,它的图片路径居然不一样,有file://开头的,也有content://开头的,还有/mnt/sdcard/开头的,坑爹啊,我自己的手机是4.1的,不一样.     4.4以前的路径都