1using System;
2using System.ComponentModel;
3using System.Collections.Generic;
4using System.Diagnostics;
5using System.Text;
6using System.Drawing;
7using System.Runtime.InteropServices;
8using System.Windows.Forms;
9
10namespace autoDockWindow
11{
12 [Description("窗体自动靠边隐藏完美组件 @Author: Red_angelX")]
13 public partial class autoDockManager : Component
14 {
15 private Form _form;
16
17 public autoDockManager()
18 {
19 InitializeComponent();
20 }
21
22 public autoDockManager(IContainer container)
23 {
24 container.Add(this);
25 InitializeComponent();
26 }
27
28 [Description("用于控制要自动Dock的窗体")]
29 public Form dockForm
30 {
31 get
32 {
33 return _form;
34 }
35 set
36 {
37 _form = value;
38 if (_form != null)
39 {
40 if (_form.TopMost == false)
41 _form.TopMost = true;
42
43 if (DesignMode)
44 return;
45
46 nativeDockWindow dockWindow = new nativeDockWindow();
47 dockWindow.AssignHandle(_form.Handle);
48 }
49 }
50 }
51 }
52
53 public class nativeDockWindow : NativeWindow
54 {
55 IntPtr handle = IntPtr.Zero;
56 Form baseForm = null;
57
58 const int HM_NONE = 0; //不收缩
59 const int HM_TOP = 1; //向上收缩
60 const int HM_BOTTOM = 2; //向下收缩
61 const int HM_LEFT = 3; //向左收缩
62 const int HM_RIGHT = 4; //向右收缩
63
64 const int INTERVAL = 20; //触发粘附的最小间隔,单位为象素
65 const int INFALTE = 4; //触发收缩的小间隔,单位为象素
66
67
68 bool m_isWndHide = false; //窗口是否隐藏
69 bool m_isSizeChanged = false; //窗口大小是否改变了
70 bool m_isSetTimer = false; //窗口大小是否改变了
71 int m_oldWndHeight; //旧的窗口宽度
72 int m_hideMode = HM_NONE; //隐藏模式
73
74 Timer checkTimer = new Timer(); //定时器
75
76 protected override void OnHandleChange()
77 {
78 handle = this.Handle;
79 if (handle != IntPtr.Zero)
80 {
81 baseForm = (Form)Form.FromHandle(handle);
82 checkTimer.Interval = 200;
83 checkTimer.Tick +=new EventHandler(checkTimer_Tick);
84 }
85 base.OnHandleChange();
86 }
87
88 //修正移动时窗口的大小
89 void FixMoving(ref Message m)
90 {
91 //已经隐藏了的情况
92 if (m_hideMode != HM_NONE && m_isWndHide == true)
93 {
94 return;
95 }
96
97 if (Control.MousePosition.Y <= INTERVAL)
98 { //粘附在上边
99 m_hideMode = HM_TOP;
100 }
101 else if (Control.MousePosition.Y >= (Screen.PrimaryScreen.Bounds.Width - INTERVAL))
102 { //粘附在下边
103 m_hideMode = HM_BOTTOM;
104 }
105 else if (Control.MousePosition.X < INTERVAL)
106 { //粘附在左边
107 if (!m_isSizeChanged)
108 {
109 m_oldWndHeight = baseForm.Height;
110 }
111 m_isSizeChanged = true;
112 m_hideMode = HM_LEFT;
113 }
114 else if (Control.MousePosition.X >= (Screen.PrimaryScreen.Bounds.Width - INTERVAL))
115 { //粘附在右边
116 if (!m_isSizeChanged)
117 {
118 m_oldWndHeight = baseForm.Height;
119 }
120 m_isSizeChanged = true;
121 m_hideMode = HM_RIGHT;
122 }
123 else
124 { //不粘附
125
126 if (m_isSizeChanged)
127 { //如果收缩到两边,则拖出来后会变回原来大小
128 //在"拖动不显示窗口内容下"只有光栅变回原来大小
129 int left = Marshal.ReadInt32(m.LParam, sizeof(int) * 0);
130 int top = Marshal.ReadInt32(m.LParam, sizeof(int) * 1);
131 int right = Marshal.ReadInt32(m.LParam, sizeof(int) * 2);
132 Marshal.WriteInt32(m.LParam, sizeof(int) * 0, left); // left
133 Marshal.WriteInt32(m.LParam, sizeof(int) * 1, top); // top
134 Marshal.WriteInt32(m.LParam, sizeof(int) * 2, right); // right
135 Marshal.WriteInt32(m.LParam, sizeof(int) * 3, top + m_oldWndHeight); // bottom
136 m_isSizeChanged = false;
137 }
138 if (m_isSetTimer)
139 { //如果Timer开启了,则关闭之
140 checkTimer.Stop();
141 m_isSetTimer = false;
142 }
143 m_isWndHide = false;
144 m_hideMode = HM_NONE;
145 }
146 }
147
148 //从收缩状态显示窗口
149 void DoShow()
150 {
151 if (m_hideMode == HM_NONE || !m_isWndHide)
152 return;
153
154 switch (m_hideMode)
155 {
156 case HM_TOP:
157 baseForm.Location = new Point(baseForm.Location.X, 0);
158 m_isWndHide = false;
159 break;
160 case HM_BOTTOM:
161 //不处理
162 //m_isWndHide = false;
163 break;
164 case HM_LEFT:
165 baseForm.Location = new Point(0, 1);
166 m_isWndHide = false;
167 break;
168 case HM_RIGHT:
169 baseForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width - baseForm.Width, 1);
170 m_isWndHide = false;
171 break;
172 default:
173 break;
174 }
175 }
176
177 //从显示状态收缩窗口
178 void DoHide()
179 {
180 if (m_hideMode == HM_NONE || m_isWndHide)
181 return;
182
183 switch (m_hideMode)
184 {
185 case HM_TOP:
186 //此句必须放在MoveWindow之上,否则大小变成m_wndRect,其他case同样
187 m_isWndHide = true;
188 baseForm.Location = new Point(baseForm.Location.X, (baseForm.Height - INFALTE) * (-1));
189 break;
190 case HM_BOTTOM:
191 //m_isWndHide = true;
192 break;
193 case HM_LEFT:
194 m_isWndHide = true;
195 baseForm.Size = new Size(baseForm.Width, Screen.PrimaryScreen.WorkingArea.Height);
196 baseForm.Location = new Point((-1) * (baseForm.Width - INFALTE), 1);
197 break;
198 case HM_RIGHT:
199 m_isWndHide = true;
200 baseForm.Size = new Size(baseForm.Width, Screen.PrimaryScreen.WorkingArea.Height);
201 baseForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width - INFALTE, 1);
202 break;
203 default:
204 break;
205 }
206 }
207
208
209 const UInt32 SWP_NOSIZE = 0x0001;
210 const UInt32 SWP_NOMOVE = 0x0002;
211 const UInt32 SWP_NOZORDER = 0x0004;
212 const UInt32 SWP_NOREDRAW = 0x0008;
213 const UInt32 SWP_NOACTIVATE = 0x0010;
214 const UInt32 SWP_FRAMECHANGED = 0x0020; // The frame changed: send WM_NCCALCSIZE
215 const UInt32 SWP_SHOWWINDOW = 0x0040;
216 const UInt32 SWP_HIDEWINDOW = 0x0080;
217 const UInt32 SWP_NOCOPYBITS = 0x0100;
218 const UInt32 SWP_NOOWNERZORDER = 0x0200; // Don't do owner Z ordering
219 const UInt32 SWP_NOSENDCHANGING = 0x0400; // Don't send WM_WINDOWPOSCHANGING
220
221 [DllImport("user32.dll")]
222 static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
223 int Y, int cx, int cy, uint uFlags);
224
225 [DllImport("user32.dll")]
226 [return: MarshalAs(UnmanagedType.Bool)]
227 static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
228
229 //这个结构在改lparam时要用到
230 [StructLayout(LayoutKind.Sequential)]
231 public struct RECT
232 {
233 public int Left;
234 public int Top;
235 public int Right;
236 public int Bottom;
237 }
238
239 [DllImport("user32.dll")]
240 [return: MarshalAs(UnmanagedType.Bool)]
241 static extern bool GetCursorPos(out Point lpPoint);
242
243 [DllImport("user32.dll")]
244 static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth,
245 int nHeight, bool bRepaint);
246
247 [DllImport("user32.dll")]
248 static extern bool InflateRect(ref RECT lprc, int dx, int dy);
249
250 [DllImport("user32.dll")]
251 static extern bool PtInRect([In] ref RECT lprc, Point pt);
252
253
254 private void checkTimer_Tick(object sender, EventArgs e)
255 {
256 RECT tRect;
257 //获取此时窗口大小
258 GetWindowRect(this.Handle, out tRect);
259 //膨胀tRect,以达到鼠标离开窗口边沿一定距离才触发事件
260 InflateRect(ref tRect, INFALTE, INFALTE);
261
262 if (!PtInRect(ref tRect, Control.MousePosition)) //如果鼠标离开了这个区域
263 {
264 checkTimer.Stop();
265 m_isSetTimer = false;
266 DoHide(); //隐藏
267 }
268 }
269
270 const int WM_NCHITTEST = 0x84;
271 const int WM_MOVING = 0x216;
272 const int WM_MOVE = 0x3;
273 const int WM_SIZING = 0x214;
274 const int HTCAPTION = 0x0002;
275 const int WM_EXITSIZEMOVE = 0x232;
276 const int WM_ENTERSIZEMOVE = 0x231;
277 const int WM_SYSCOMMAND = 0x112;
278 const int SC_SIZE = 0xF000;
279 const int WM_SETTINGCHANGE = 0x1A;
280
281 protected override void WndProc(ref Message m)
282 {
283 if (m.Msg == WM_NCHITTEST)
284 {
285 if (m_hideMode != HM_NONE && !m_isSetTimer)
286 { //鼠标进入时,如果是从收缩状态到显示状态则开启Timer
287 checkTimer.Start();
288 m_isSetTimer = true;
289 DoShow();
290 }
291 }
292 else if (m.Msg == WM_MOVING)
293 {
294 FixMoving(ref m);
295 }
296 else if(m.Msg == WM_ENTERSIZEMOVE)
297 {
298 baseForm.SuspendLayout();
299 }
300 else if (m.Msg == WM_EXITSIZEMOVE)
301 {
302 baseForm.ResumeLayout();
303 }
304 base.WndProc(ref m);
305 }
306 }
307}
308
2using System.ComponentModel;
3using System.Collections.Generic;
4using System.Diagnostics;
5using System.Text;
6using System.Drawing;
7using System.Runtime.InteropServices;
8using System.Windows.Forms;
9
10namespace autoDockWindow
11{
12 [Description("窗体自动靠边隐藏完美组件 @Author: Red_angelX")]
13 public partial class autoDockManager : Component
14 {
15 private Form _form;
16
17 public autoDockManager()
18 {
19 InitializeComponent();
20 }
21
22 public autoDockManager(IContainer container)
23 {
24 container.Add(this);
25 InitializeComponent();
26 }
27
28 [Description("用于控制要自动Dock的窗体")]
29 public Form dockForm
30 {
31 get
32 {
33 return _form;
34 }
35 set
36 {
37 _form = value;
38 if (_form != null)
39 {
40 if (_form.TopMost == false)
41 _form.TopMost = true;
42
43 if (DesignMode)
44 return;
45
46 nativeDockWindow dockWindow = new nativeDockWindow();
47 dockWindow.AssignHandle(_form.Handle);
48 }
49 }
50 }
51 }
52
53 public class nativeDockWindow : NativeWindow
54 {
55 IntPtr handle = IntPtr.Zero;
56 Form baseForm = null;
57
58 const int HM_NONE = 0; //不收缩
59 const int HM_TOP = 1; //向上收缩
60 const int HM_BOTTOM = 2; //向下收缩
61 const int HM_LEFT = 3; //向左收缩
62 const int HM_RIGHT = 4; //向右收缩
63
64 const int INTERVAL = 20; //触发粘附的最小间隔,单位为象素
65 const int INFALTE = 4; //触发收缩的小间隔,单位为象素
66
67
68 bool m_isWndHide = false; //窗口是否隐藏
69 bool m_isSizeChanged = false; //窗口大小是否改变了
70 bool m_isSetTimer = false; //窗口大小是否改变了
71 int m_oldWndHeight; //旧的窗口宽度
72 int m_hideMode = HM_NONE; //隐藏模式
73
74 Timer checkTimer = new Timer(); //定时器
75
76 protected override void OnHandleChange()
77 {
78 handle = this.Handle;
79 if (handle != IntPtr.Zero)
80 {
81 baseForm = (Form)Form.FromHandle(handle);
82 checkTimer.Interval = 200;
83 checkTimer.Tick +=new EventHandler(checkTimer_Tick);
84 }
85 base.OnHandleChange();
86 }
87
88 //修正移动时窗口的大小
89 void FixMoving(ref Message m)
90 {
91 //已经隐藏了的情况
92 if (m_hideMode != HM_NONE && m_isWndHide == true)
93 {
94 return;
95 }
96
97 if (Control.MousePosition.Y <= INTERVAL)
98 { //粘附在上边
99 m_hideMode = HM_TOP;
100 }
101 else if (Control.MousePosition.Y >= (Screen.PrimaryScreen.Bounds.Width - INTERVAL))
102 { //粘附在下边
103 m_hideMode = HM_BOTTOM;
104 }
105 else if (Control.MousePosition.X < INTERVAL)
106 { //粘附在左边
107 if (!m_isSizeChanged)
108 {
109 m_oldWndHeight = baseForm.Height;
110 }
111 m_isSizeChanged = true;
112 m_hideMode = HM_LEFT;
113 }
114 else if (Control.MousePosition.X >= (Screen.PrimaryScreen.Bounds.Width - INTERVAL))
115 { //粘附在右边
116 if (!m_isSizeChanged)
117 {
118 m_oldWndHeight = baseForm.Height;
119 }
120 m_isSizeChanged = true;
121 m_hideMode = HM_RIGHT;
122 }
123 else
124 { //不粘附
125
126 if (m_isSizeChanged)
127 { //如果收缩到两边,则拖出来后会变回原来大小
128 //在"拖动不显示窗口内容下"只有光栅变回原来大小
129 int left = Marshal.ReadInt32(m.LParam, sizeof(int) * 0);
130 int top = Marshal.ReadInt32(m.LParam, sizeof(int) * 1);
131 int right = Marshal.ReadInt32(m.LParam, sizeof(int) * 2);
132 Marshal.WriteInt32(m.LParam, sizeof(int) * 0, left); // left
133 Marshal.WriteInt32(m.LParam, sizeof(int) * 1, top); // top
134 Marshal.WriteInt32(m.LParam, sizeof(int) * 2, right); // right
135 Marshal.WriteInt32(m.LParam, sizeof(int) * 3, top + m_oldWndHeight); // bottom
136 m_isSizeChanged = false;
137 }
138 if (m_isSetTimer)
139 { //如果Timer开启了,则关闭之
140 checkTimer.Stop();
141 m_isSetTimer = false;
142 }
143 m_isWndHide = false;
144 m_hideMode = HM_NONE;
145 }
146 }
147
148 //从收缩状态显示窗口
149 void DoShow()
150 {
151 if (m_hideMode == HM_NONE || !m_isWndHide)
152 return;
153
154 switch (m_hideMode)
155 {
156 case HM_TOP:
157 baseForm.Location = new Point(baseForm.Location.X, 0);
158 m_isWndHide = false;
159 break;
160 case HM_BOTTOM:
161 //不处理
162 //m_isWndHide = false;
163 break;
164 case HM_LEFT:
165 baseForm.Location = new Point(0, 1);
166 m_isWndHide = false;
167 break;
168 case HM_RIGHT:
169 baseForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width - baseForm.Width, 1);
170 m_isWndHide = false;
171 break;
172 default:
173 break;
174 }
175 }
176
177 //从显示状态收缩窗口
178 void DoHide()
179 {
180 if (m_hideMode == HM_NONE || m_isWndHide)
181 return;
182
183 switch (m_hideMode)
184 {
185 case HM_TOP:
186 //此句必须放在MoveWindow之上,否则大小变成m_wndRect,其他case同样
187 m_isWndHide = true;
188 baseForm.Location = new Point(baseForm.Location.X, (baseForm.Height - INFALTE) * (-1));
189 break;
190 case HM_BOTTOM:
191 //m_isWndHide = true;
192 break;
193 case HM_LEFT:
194 m_isWndHide = true;
195 baseForm.Size = new Size(baseForm.Width, Screen.PrimaryScreen.WorkingArea.Height);
196 baseForm.Location = new Point((-1) * (baseForm.Width - INFALTE), 1);
197 break;
198 case HM_RIGHT:
199 m_isWndHide = true;
200 baseForm.Size = new Size(baseForm.Width, Screen.PrimaryScreen.WorkingArea.Height);
201 baseForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width - INFALTE, 1);
202 break;
203 default:
204 break;
205 }
206 }
207
208
209 const UInt32 SWP_NOSIZE = 0x0001;
210 const UInt32 SWP_NOMOVE = 0x0002;
211 const UInt32 SWP_NOZORDER = 0x0004;
212 const UInt32 SWP_NOREDRAW = 0x0008;
213 const UInt32 SWP_NOACTIVATE = 0x0010;
214 const UInt32 SWP_FRAMECHANGED = 0x0020; // The frame changed: send WM_NCCALCSIZE
215 const UInt32 SWP_SHOWWINDOW = 0x0040;
216 const UInt32 SWP_HIDEWINDOW = 0x0080;
217 const UInt32 SWP_NOCOPYBITS = 0x0100;
218 const UInt32 SWP_NOOWNERZORDER = 0x0200; // Don't do owner Z ordering
219 const UInt32 SWP_NOSENDCHANGING = 0x0400; // Don't send WM_WINDOWPOSCHANGING
220
221 [DllImport("user32.dll")]
222 static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
223 int Y, int cx, int cy, uint uFlags);
224
225 [DllImport("user32.dll")]
226 [return: MarshalAs(UnmanagedType.Bool)]
227 static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
228
229 //这个结构在改lparam时要用到
230 [StructLayout(LayoutKind.Sequential)]
231 public struct RECT
232 {
233 public int Left;
234 public int Top;
235 public int Right;
236 public int Bottom;
237 }
238
239 [DllImport("user32.dll")]
240 [return: MarshalAs(UnmanagedType.Bool)]
241 static extern bool GetCursorPos(out Point lpPoint);
242
243 [DllImport("user32.dll")]
244 static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth,
245 int nHeight, bool bRepaint);
246
247 [DllImport("user32.dll")]
248 static extern bool InflateRect(ref RECT lprc, int dx, int dy);
249
250 [DllImport("user32.dll")]
251 static extern bool PtInRect([In] ref RECT lprc, Point pt);
252
253
254 private void checkTimer_Tick(object sender, EventArgs e)
255 {
256 RECT tRect;
257 //获取此时窗口大小
258 GetWindowRect(this.Handle, out tRect);
259 //膨胀tRect,以达到鼠标离开窗口边沿一定距离才触发事件
260 InflateRect(ref tRect, INFALTE, INFALTE);
261
262 if (!PtInRect(ref tRect, Control.MousePosition)) //如果鼠标离开了这个区域
263 {
264 checkTimer.Stop();
265 m_isSetTimer = false;
266 DoHide(); //隐藏
267 }
268 }
269
270 const int WM_NCHITTEST = 0x84;
271 const int WM_MOVING = 0x216;
272 const int WM_MOVE = 0x3;
273 const int WM_SIZING = 0x214;
274 const int HTCAPTION = 0x0002;
275 const int WM_EXITSIZEMOVE = 0x232;
276 const int WM_ENTERSIZEMOVE = 0x231;
277 const int WM_SYSCOMMAND = 0x112;
278 const int SC_SIZE = 0xF000;
279 const int WM_SETTINGCHANGE = 0x1A;
280
281 protected override void WndProc(ref Message m)
282 {
283 if (m.Msg == WM_NCHITTEST)
284 {
285 if (m_hideMode != HM_NONE && !m_isSetTimer)
286 { //鼠标进入时,如果是从收缩状态到显示状态则开启Timer
287 checkTimer.Start();
288 m_isSetTimer = true;
289 DoShow();
290 }
291 }
292 else if (m.Msg == WM_MOVING)
293 {
294 FixMoving(ref m);
295 }
296 else if(m.Msg == WM_ENTERSIZEMOVE)
297 {
298 baseForm.SuspendLayout();
299 }
300 else if (m.Msg == WM_EXITSIZEMOVE)
301 {
302 baseForm.ResumeLayout();
303 }
304 base.WndProc(ref m);
305 }
306 }
307}
308