您的位置:首页 > 编程语言 > C#

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

2009-02-18 08:49 429 查看
你想过为自己的程序添加靠边隐藏的功能吗?还在为计算窗体的大小及位置而烦恼吗?想这么简单的轻松调用吗?
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 == null) return;
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. }

详细可以下载工程后自行研究
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: