├── .gitignore
├── .tfignore
├── CustomControls
├── CheckGroupBox.cs
├── CheckableGroupBox.cs
├── IRadioControl.cs
├── MessageBoxEx.cs
└── RadioGroupBox.cs
├── DialogDragger.cs
├── FmMDI.Designer.cs
├── FmMDI.cs
├── FmMDI.resx
├── FmTabMDI.Designer.cs
├── FmTabMDI.cs
├── FmTabMDI.resx
├── FmTabSub.Designer.cs
├── FmTabSub.cs
├── FmTabSub.resx
├── FmTestDrag.Designer.cs
├── FmTestDrag.cs
├── FmTestDrag.resx
├── FormDragger.cs
├── FormDraggerDemo.csproj
├── FormDraggerDemo.sln
├── Program.cs
├── Properties
└── AssemblyInfo.cs
├── README.md
└── pic.png
/.gitignore:
--------------------------------------------------------------------------------
1 | Thumbs.db
2 | *.obj
3 | *.exe
4 | *.pdb
5 | *.user
6 | *.aps
7 | *.pch
8 | *.vspscc
9 | *_i.c
10 | *_p.c
11 | *.ncb
12 | *.suo
13 | *.sln.docstates
14 | *.tlb
15 | *.tlh
16 | *.bak
17 | *.cache
18 | *.ilk
19 | *.log
20 | [Bb]in
21 | [Dd]ebug*/
22 | *.lib
23 | *.sbr
24 | obj/
25 | [Rr]elease*/
26 | _ReSharper*/
27 | [Tt]est[Rr]esult*
28 | *.vssscc
29 | $tf*/
30 | .vs/
--------------------------------------------------------------------------------
/.tfignore:
--------------------------------------------------------------------------------
1 | \.git
--------------------------------------------------------------------------------
/CustomControls/CheckGroupBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Windows.Forms;
4 |
5 | namespace AhDung.WinForm.Controls
6 | {
7 | ///
8 | /// 复选组面板
9 | ///
10 | [ToolboxItem(true)]
11 | public class CheckGroupBox : CheckableGroupBox
12 | {
13 | CheckBox CheckBoxControl
14 | {
15 | get { return (CheckBox)CheckControl; }
16 | }
17 |
18 | ///
19 | /// 获取或设置勾选状态
20 | ///
21 | [Description("勾选状态")]
22 | [DefaultValue(CheckState.Unchecked)]
23 | public CheckState CheckState
24 | {
25 | get { return CheckBoxControl.CheckState; }
26 | set { CheckBoxControl.CheckState = value; }
27 | }
28 |
29 | ///
30 | /// 获取或设置是否允许三态
31 | ///
32 | [Description("是否允许三态")]
33 | [DefaultValue(false)]
34 | public bool ThreeState
35 | {
36 | get { return CheckBoxControl.ThreeState; }
37 | set { CheckBoxControl.ThreeState = value; }
38 | }
39 |
40 | ///
41 | /// 选中状态改变后
42 | ///
43 | public event EventHandler CheckStateChanged;
44 |
45 | ///
46 | /// 初始化本类
47 | ///
48 | public CheckGroupBox()
49 | : base(true)
50 | {
51 | CheckBoxControl.CheckStateChanged += checkControl_CheckStateChanged;
52 | }
53 |
54 | protected virtual void OnCheckStateChanged(EventArgs e)
55 | {
56 | var handler = CheckStateChanged;
57 | if (handler != null)
58 | {
59 | handler(this, e);
60 | }
61 | }
62 |
63 | void checkControl_CheckStateChanged(object sender, EventArgs e)
64 | {
65 | OnCheckStateChanged(EventArgs.Empty);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/CustomControls/CheckableGroupBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Drawing;
4 | using System.Windows.Forms;
5 | using System.Windows.Forms.Design;
6 |
7 | namespace AhDung.WinForm.Controls
8 | {
9 | ///
10 | /// 可Check的分组框
11 | ///
12 | [Designer(typeof(CheckableGroupBoxDesigner))]
13 | [ToolboxItem(false)]
14 | [DefaultEvent("CheckedChanged")]
15 | [DefaultProperty("Checked")]
16 | public class CheckableGroupBox : UserControl
17 | {
18 | readonly bool _isCheckBox;
19 | protected ButtonBase CheckControl;
20 | GroupBoxInner _grpBox;
21 | bool _autoDisableContent;
22 | Color _titleColor;
23 |
24 | ///
25 | /// 获取或设置文本
26 | ///
27 | [Description("抬头文字")]
28 | [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] //不是蛋疼
29 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] //不是蛋疼
30 | public override string Text
31 | {
32 | get { return CheckControl.Text; }
33 | set { CheckControl.Text = value; }
34 | }
35 |
36 | ///
37 | /// 获取或设置标题颜色
38 | ///
39 | [Description("标题颜色")]
40 | [DefaultValue(typeof(Color), "0, 70, 213")]
41 | public Color TitleColor
42 | {
43 | get { return _titleColor; }
44 | set
45 | {
46 | if (_titleColor == value) { return; }
47 | _titleColor = value;
48 | CheckControl.ForeColor = _titleColor;
49 | }
50 | }
51 |
52 | ///
53 | /// 获取或设置是否勾选
54 | ///
55 | [Description("是否勾选")]
56 | [DefaultValue(false)]
57 | public bool Checked
58 | {
59 | get
60 | {
61 | return _isCheckBox
62 | ? ((CheckBox)CheckControl).Checked
63 | : ((RadioButton)CheckControl).Checked;
64 | }
65 | set
66 | {
67 | if (_isCheckBox)
68 | {
69 | ((CheckBox)CheckControl).Checked = value;
70 | }
71 | else
72 | {
73 | ((RadioButton)CheckControl).Checked = value;
74 | }
75 | }
76 | }
77 |
78 | [Description("取消Checked时是否屏蔽内容区")]
79 | [EditorBrowsable(EditorBrowsableState.Never)]
80 | [DefaultValue(true)]
81 | public bool AutoDisableContent
82 | {
83 | get { return _autoDisableContent; }
84 | set
85 | {
86 | if (_autoDisableContent == value) { return; }
87 | _autoDisableContent = value;
88 | if (!_autoDisableContent)//当开闭状态不联动时,强制开启
89 | {
90 | _grpBox.Enabled = true;
91 | }
92 | }
93 | }
94 |
95 | ///
96 | /// 是否选中改变后
97 | ///
98 | public event EventHandler CheckedChanged;
99 |
100 | [Browsable(false)]
101 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
102 | public GroupBoxInner GroupBoxControl
103 | {
104 | get { return _grpBox; }
105 | }
106 |
107 | ///
108 | /// 初始化本类
109 | ///
110 | /// true为复选框,false为单选框
111 | protected CheckableGroupBox(bool isCheckBox)
112 | {
113 | _isCheckBox = isCheckBox;
114 | _titleColor = Color.FromArgb(0, 70, 213);
115 | InitializeComponent();
116 | AutoDisableContent = true;
117 | _grpBox.Enabled = false;
118 | }
119 |
120 | private void InitializeComponent()
121 | {
122 | this._grpBox = new GroupBoxInner();
123 | this.SuspendLayout();
124 | this._grpBox.SuspendLayout();
125 | //
126 | // CheckControl
127 | //
128 | if (_isCheckBox)
129 | {
130 | CheckControl = new CheckBox();
131 | ((CheckBox)CheckControl).CheckedChanged += checkControl_CheckedChanged;
132 | }
133 | else
134 | {
135 | CheckControl = new RadioButton();
136 | ((RadioButton)CheckControl).CheckedChanged += checkControl_CheckedChanged;
137 | }
138 | this.CheckControl.AutoSize = true;
139 | this.CheckControl.ForeColor = _titleColor;
140 | this.CheckControl.Location = new System.Drawing.Point(8, -1);
141 | this.CheckControl.Name = "CheckControl";
142 | this.CheckControl.TabIndex = 0;
143 | //
144 | // _grpBox
145 | //
146 | this._grpBox.Dock = System.Windows.Forms.DockStyle.Fill;
147 | this._grpBox.Name = "_grpBox";
148 | this._grpBox.TabIndex = 1;
149 | //
150 | // CheckedGroupBox
151 | //
152 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
153 | this.Controls.Add(CheckControl);
154 | this.Controls.Add(this._grpBox);
155 | this._grpBox.ResumeLayout(false);
156 | this.ResumeLayout(false);
157 | this.PerformLayout();
158 | }
159 |
160 | protected virtual void OnCheckedChanged(EventArgs e)
161 | {
162 | var handler = CheckedChanged;
163 | if (handler != null)
164 | {
165 | handler(this, e);
166 | }
167 | }
168 |
169 | void checkControl_CheckedChanged(object sender, EventArgs e)
170 | {
171 | if (AutoDisableContent)
172 | {
173 | _grpBox.Enabled = this.Checked;
174 | }
175 | OnCheckedChanged(EventArgs.Empty);
176 | }
177 |
178 | [ToolboxItem(false)]
179 | public class GroupBoxInner : GroupBox
180 | {
181 | // ReSharper disable UnusedMember.Global
182 | [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
183 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
184 | public override DockStyle Dock
185 | {
186 | get { return base.Dock; }
187 | set { base.Dock = value; }
188 | }
189 |
190 | [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
191 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
192 | public new bool Enabled
193 | {
194 | get { return base.Enabled; }
195 | set { base.Enabled = value; }
196 | }
197 |
198 | [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
199 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
200 | public new Point Location
201 | {
202 | get { return base.Location; }
203 | set { base.Location = value; }
204 | }
205 |
206 | [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
207 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
208 | public new string Name
209 | {
210 | get { return base.Name; }
211 | set { base.Name = value; }
212 | }
213 |
214 | [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
215 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
216 | public new int TabIndex
217 | {
218 | get { return base.TabIndex; }
219 | set { base.TabIndex = value; }
220 | }
221 |
222 | [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
223 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
224 | public new bool TabStop
225 | {
226 | get { return base.TabStop; }
227 | set { base.TabStop = value; }
228 | }
229 |
230 | [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
231 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
232 | public override string Text
233 | {
234 | get { return base.Text; }
235 | set { base.Text = value; }
236 | }
237 | // ReSharper restore UnusedMember.Global
238 | }
239 | }
240 |
241 | public class CheckableGroupBoxDesigner : ParentControlDesigner
242 | {
243 | public override void Initialize(IComponent component)
244 | {
245 | base.Initialize(component);
246 |
247 | if (this.Control is CheckableGroupBox)
248 | {
249 | EnableDesignMode(((CheckableGroupBox)this.Control).GroupBoxControl, "GroupBoxControl");
250 | }
251 | }
252 | }
253 | }
254 |
255 |
256 |
--------------------------------------------------------------------------------
/CustomControls/IRadioControl.cs:
--------------------------------------------------------------------------------
1 | namespace AhDung.WinForm
2 | {
3 | ///
4 | /// 单选互斥类控件
5 | ///
6 | interface IRadioControl
7 | {
8 | ///
9 | /// 获取或设置选中状态
10 | ///
11 | bool Checked { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/CustomControls/MessageBoxEx.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Drawing;
4 | using System.IO;
5 | using System.Runtime.InteropServices;
6 | using System.Threading;
7 | using System.Windows.Forms;
8 |
9 | namespace AhDung.WinForm
10 | {
11 | ///
12 | /// 可以携带详细信息的消息框
13 | ///
14 | public static class MessageBoxEx
15 | {
16 | //异常消息文本
17 | private const string InvalidButtonExString = "按钮参数不是有效的枚举项!";
18 | private const string InvalidIconExString = "图标参数不是有效的枚举项!";
19 | private const string InvalidDfButtonExString = "默认按钮参数不是有效的枚举项!";
20 |
21 | ///
22 | /// 是否启用动画效果
23 | ///
24 | public static bool EnableAnimate { get; set; }
25 |
26 | ///
27 | /// 是否启用声音反馈
28 | ///
29 | public static bool EnableSound { get; set; }
30 |
31 | //静态构造
32 | static MessageBoxEx()
33 | {
34 | //默认启用动画+声音
35 | EnableAnimate = true;
36 | EnableSound = true;
37 | }
38 |
39 | #region 公开方法
40 |
41 | ///
42 | /// 显示消息框
43 | ///
44 | /// 消息文本
45 | /// 消息框标题
46 | /// 附加消息
47 | public static DialogResult Show(string message, string caption = null, string attachMessage = null)
48 | {
49 | return ShowCore(message, caption, attachMessage, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
50 | }
51 |
52 | /*下面这仨弄成重载而不是可选方法是为了避免不必要的参数检查*/
53 |
54 | ///
55 | /// 显示消息框
56 | ///
57 | /// 消息文本
58 | /// 消息框标题
59 | /// 附加消息
60 | /// 按钮组合
61 | public static DialogResult Show(string message, string caption, string attachMessage, MessageBoxButtons buttons)
62 | {
63 | if (!Enum.IsDefined(typeof(MessageBoxButtons), buttons)) { throw new InvalidEnumArgumentException(InvalidButtonExString); }
64 |
65 | return ShowCore(message, caption, attachMessage, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
66 | }
67 |
68 | ///
69 | /// 显示消息框
70 | ///
71 | /// 消息文本
72 | /// 消息框标题
73 | /// 附加消息
74 | /// 按钮组合
75 | /// 图标
76 | public static DialogResult Show(string message, string caption, string attachMessage, MessageBoxButtons buttons, MessageBoxIcon icon)
77 | {
78 | if (!Enum.IsDefined(typeof(MessageBoxButtons), buttons)) { throw new InvalidEnumArgumentException(InvalidButtonExString); }
79 | if (!Enum.IsDefined(typeof(MessageBoxIcon), icon)) { throw new InvalidEnumArgumentException(InvalidIconExString); }
80 |
81 | return ShowCore(message, caption, attachMessage, buttons, icon, MessageBoxDefaultButton.Button1);
82 | }
83 |
84 | ///
85 | /// 显示消息框
86 | ///
87 | /// 消息文本
88 | /// 消息框标题
89 | /// 附加消息
90 | /// 按钮组合
91 | /// 图标
92 | /// 默认按钮
93 | public static DialogResult Show(string message, string caption, string attachMessage, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
94 | {
95 | if (!Enum.IsDefined(typeof(MessageBoxButtons), buttons)) { throw new InvalidEnumArgumentException(InvalidButtonExString); }
96 | if (!Enum.IsDefined(typeof(MessageBoxIcon), icon)) { throw new InvalidEnumArgumentException(InvalidIconExString); }
97 | if (!Enum.IsDefined(typeof(MessageBoxDefaultButton), defaultButton)) { throw new InvalidEnumArgumentException(InvalidDfButtonExString); }
98 |
99 | return ShowCore(message, caption, attachMessage, buttons, icon, defaultButton);
100 | }
101 |
102 | /********传入异常的重载********/
103 |
104 | ///
105 | /// 显示消息框
106 | ///
107 | /// 消息文本
108 | /// 消息框标题
109 | /// 异常实例
110 | public static DialogResult Show(string message, string caption, Exception exception)
111 | {
112 | return Show(message, caption, exception == null ? string.Empty : exception.ToString());
113 | }
114 |
115 | ///
116 | /// 显示消息框
117 | ///
118 | /// 消息文本
119 | /// 消息框标题
120 | /// 异常实例
121 | /// 按钮组合
122 | public static DialogResult Show(string message, string caption, Exception exception, MessageBoxButtons buttons)
123 | {
124 | return Show(message, caption, exception == null ? string.Empty : exception.ToString(), buttons);
125 | }
126 |
127 | ///
128 | /// 显示消息框
129 | ///
130 | /// 消息文本
131 | /// 消息框标题
132 | /// 异常实例
133 | /// 按钮组合
134 | /// 图标
135 | public static DialogResult Show(string message, string caption, Exception exception, MessageBoxButtons buttons, MessageBoxIcon icon)
136 | {
137 | return Show(message, caption, exception == null ? string.Empty : exception.ToString(), buttons, icon);
138 | }
139 |
140 | ///
141 | /// 显示消息框
142 | ///
143 | /// 消息文本
144 | /// 消息框标题
145 | /// 异常实例
146 | /// 按钮组合
147 | /// 图标
148 | /// 默认按钮
149 | public static DialogResult Show(string message, string caption, Exception exception, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
150 | {
151 | return Show(message, caption, exception == null ? string.Empty : exception.ToString(), buttons, icon, defaultButton);
152 | }
153 |
154 | #endregion
155 |
156 | //内部方法,不检查参数有效性
157 | private static DialogResult ShowCore(string message, string caption, string attachMessage, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
158 | {
159 | using (MessageForm f = new MessageForm(message, caption, buttons, icon, defaultButton, attachMessage, EnableAnimate, EnableSound))
160 | {
161 | return f.ShowDialog();
162 | }
163 | }
164 |
165 |
166 | /*----------------
167 | 下面是消息窗体相关
168 | ---------------*/
169 |
170 | ///
171 | /// 消息窗体
172 | ///
173 | /// 参数有效性由MessageBoxEx负责
174 | private class MessageForm : Form
175 | {
176 | /* todo 存在问题:
177 | * 当消息区文本非常非常多时,且反复进行改变消息框窗口大小、位置、展开收起的操作,那么在某次展开时
178 | 详细信息文本框可能会在原位置(即消息区内某rect)瞬闪一下,
179 | 原因是文本框控件在显示时总会在原位置WM_NCPAINT + WM_ERASEBKGND一下,暂无解决办法。
180 | 实际应用中碰到的几率很小,就算碰到,影响也可以忽略。
181 | */
182 |
183 | #region 控件初始化
184 |
185 | ///
186 | /// 必需的设计器变量。
187 | ///
188 | private System.ComponentModel.IContainer components = null;
189 |
190 | ///
191 | /// 清理所有正在使用的资源。
192 | ///
193 | /// 如果应释放托管资源,为 true;否则为 false。
194 | protected override void Dispose(bool disposing)
195 | {
196 | if (disposing && (components != null))
197 | {
198 | components.Dispose();
199 | }
200 | base.Dispose(disposing);
201 | }
202 |
203 | #region Windows 窗体设计器生成的代码
204 |
205 | ///
206 | /// 设计器支持所需的方法 - 不要
207 | /// 使用代码编辑器修改此方法的内容。
208 | ///
209 | private void InitializeComponent()
210 | {
211 | this.button3 = new System.Windows.Forms.Button();
212 | this.txbAttach = new TextBoxUnSelectAllable();
213 | this.button2 = new System.Windows.Forms.Button();
214 | this.button1 = new System.Windows.Forms.Button();
215 | this.plButtonsZone = new AhDung.WinForm.MessageBoxEx.MessageForm.PanelBasic();
216 | this.ckbToggle = new AhDung.WinForm.MessageBoxEx.MessageForm.ToggleButton(this.UseAnimate);
217 | this.plAttachZone = new AhDung.WinForm.MessageBoxEx.MessageForm.PanelBasic();
218 | this.lbMsg = new AhDung.WinForm.MessageBoxEx.MessageForm.MessageViewer();
219 | this.plButtonsZone.SuspendLayout();
220 | this.plAttachZone.SuspendLayout();
221 | this.SuspendLayout();
222 | //
223 | // button3
224 | //
225 | this.button3.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
226 | this.button3.Location = new System.Drawing.Point(320, 8);
227 | this.button3.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
228 | this.button3.Name = "button3";
229 | this.button3.Size = new System.Drawing.Size(85, 27);
230 | this.button3.TabIndex = 2;
231 | //
232 | // txbAttach
233 | //
234 | this.txbAttach.Anchor = ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
235 | | System.Windows.Forms.AnchorStyles.Left)
236 | | System.Windows.Forms.AnchorStyles.Right;
237 | this.txbAttach.Location = new System.Drawing.Point(10, 7);
238 | this.txbAttach.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1);
239 | this.txbAttach.Name = "txbAttach";
240 | this.txbAttach.ReadOnly = true;
241 | this.txbAttach.Multiline = true;
242 | this.txbAttach.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
243 | this.txbAttach.Size = new System.Drawing.Size(395, 105);
244 | this.txbAttach.TabIndex = 0;
245 | //
246 | // button2
247 | //
248 | this.button2.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
249 | this.button2.Location = new System.Drawing.Point(229, 8);
250 | this.button2.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
251 | this.button2.Name = "button2";
252 | this.button2.Size = new System.Drawing.Size(85, 27);
253 | this.button2.TabIndex = 1;
254 | //
255 | // button1
256 | //
257 | this.button1.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
258 | this.button1.Location = new System.Drawing.Point(138, 8);
259 | this.button1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
260 | this.button1.Name = "button1";
261 | this.button1.Size = new System.Drawing.Size(85, 27);
262 | this.button1.TabIndex = 0;
263 | //
264 | // plButtonsZone
265 | //
266 | this.plButtonsZone.Controls.Add(this.ckbToggle);
267 | this.plButtonsZone.Controls.Add(this.button1);
268 | this.plButtonsZone.Controls.Add(this.button2);
269 | this.plButtonsZone.Controls.Add(this.button3);
270 | this.plButtonsZone.Dock = System.Windows.Forms.DockStyle.Bottom;
271 | this.plButtonsZone.Location = new System.Drawing.Point(0, 96);
272 | this.plButtonsZone.Margin = new System.Windows.Forms.Padding(3, 1, 3, 1);
273 | this.plButtonsZone.Name = "plButtonsZone";
274 | this.plButtonsZone.Size = new System.Drawing.Size(415, 36);
275 | this.plButtonsZone.TabIndex = 1;
276 | //
277 | // ckbToggle
278 | //
279 | this.ckbToggle.Location = new System.Drawing.Point(10, 8);
280 | this.ckbToggle.Name = "ckbToggle";
281 | this.ckbToggle.Size = new System.Drawing.Size(93, 27);
282 | this.ckbToggle.TabIndex = 3;
283 | this.ckbToggle.Text = "详细信息(&D)";
284 | this.ckbToggle.CheckedChanged += this.ckbToggle_CheckedChanged;
285 | //
286 | // plAttachZone
287 | //
288 | this.plAttachZone.Controls.Add(this.txbAttach);
289 | this.plAttachZone.Dock = System.Windows.Forms.DockStyle.Fill;
290 | this.plAttachZone.Location = new System.Drawing.Point(0, 130);
291 | this.plAttachZone.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
292 | this.plAttachZone.Name = "plAttachZone";
293 | this.plAttachZone.Size = new System.Drawing.Size(415, 114);
294 | this.plAttachZone.TabIndex = 2;
295 | this.plAttachZone.Visible = false;
296 | //
297 | // lbMsg
298 | //
299 | this.lbMsg.Dock = System.Windows.Forms.DockStyle.Fill;
300 | this.lbMsg.Icon = null;
301 | this.lbMsg.Location = new System.Drawing.Point(0, 0);
302 | this.lbMsg.Name = "lbMsg";
303 | this.lbMsg.Padding = new System.Windows.Forms.Padding(21, 18, 21, 18);
304 | //this.lbMsg.Size = new System.Drawing.Size(415, 96);
305 | this.lbMsg.TabIndex = 0;
306 | //
307 | // FmMsg
308 | //
309 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
310 | //this.ClientSize = new System.Drawing.Size(415, 261);
311 | this.Controls.Add(this.lbMsg);
312 | this.Controls.Add(this.plButtonsZone);
313 | this.Controls.Add(this.plAttachZone);
314 | this.DoubleBuffered = true;
315 | this.MaximizeBox = false;
316 | this.Name = "MessageForm";
317 | this.Padding = new System.Windows.Forms.Padding(0, 0, 0, 17);
318 | this.ShowIcon = false;
319 | this.ShowInTaskbar = false;
320 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
321 | this.plButtonsZone.ResumeLayout(false);
322 | this.plAttachZone.ResumeLayout(false);
323 | this.plAttachZone.PerformLayout();
324 | this.ResumeLayout(false);
325 | }
326 |
327 | #endregion
328 |
329 | private ToggleButton ckbToggle;
330 | private TextBoxUnSelectAllable txbAttach;
331 | private MessageViewer lbMsg;
332 | private System.Windows.Forms.Button button2;
333 | private System.Windows.Forms.Button button1;
334 | private PanelBasic plButtonsZone;
335 | private PanelBasic plAttachZone;
336 | private System.Windows.Forms.Button button3;
337 |
338 | #endregion
339 |
340 | ///
341 | /// 最大默认窗体客户区宽度
342 | ///
343 | const int MaxClientWidth = 700;
344 |
345 | string messageSound;//存储供PlaySound API使用的系统消息音别名,在ProcessIcon中赋值,OnShown中取用
346 |
347 | int expandHeight;
348 | ///
349 | /// 详细信息区展开高度
350 | ///
351 | private int ExpandHeight
352 | {
353 | get { return expandHeight < 150 ? 150 : expandHeight; }
354 | set { expandHeight = value; }
355 | }
356 |
357 | #region 属性
358 |
359 | ///
360 | /// 是否启用动画效果
361 | ///
362 | /// 此处还弄该属性是为了保证窗体类的独立性
363 | private bool UseAnimate { get; set; }
364 |
365 | ///
366 | /// 是否启用声音反馈
367 | ///
368 | /// 此处还弄该属性是为了保证窗体类的独立性
369 | private bool UseSound { get; set; }
370 |
371 | ///
372 | /// 消息按钮
373 | ///
374 | private MessageBoxButtons MessageButtons { get; set; }
375 |
376 | ///
377 | /// 消息图标
378 | ///
379 | private MessageBoxIcon MessageIcon { get; set; }
380 |
381 | ///
382 | /// 默认按钮
383 | ///
384 | private MessageBoxDefaultButton DefaultButton { get; set; }
385 |
386 | #endregion
387 |
388 | ///
389 | /// 创建消息窗体
390 | ///
391 | private MessageForm(bool enableAnimate)
392 | {
393 | this.UseAnimate = enableAnimate;//须尽早设置,要供展开按钮初始化用
394 | InitializeComponent();
395 | this.StartPosition = Form.ActiveForm == null ? FormStartPosition.CenterScreen : FormStartPosition.CenterParent;
396 | this.Font = SystemFonts.MessageBoxFont;
397 |
398 | //注册事件
399 | this.button1.Click += button_Click;
400 | this.button2.Click += button_Click;
401 | this.button3.Click += button_Click;
402 | this.plAttachZone.Resize += plAttachZone_Resize;
403 | }
404 |
405 | ///
406 | /// 创建消息窗体
407 | ///
408 | public MessageForm(string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, string attachMessage, bool enableAnimate, bool enableSound)
409 | : this(enableAnimate)
410 | {
411 | this.lbMsg.Text = message;
412 | this.Text = caption;
413 | this.txbAttach.Text = attachMessage;
414 | this.MessageButtons = buttons;
415 | this.MessageIcon = icon;
416 | this.DefaultButton = defaultButton;
417 | this.UseSound = enableSound;
418 | }
419 |
420 | #region 重写基类方法
421 |
422 | protected override void OnLoad(EventArgs e)
423 | {
424 | //须在计算各种尺寸前搞掂
425 | ProcessIcon();
426 | ProcessButtons();
427 |
428 | this.MinimumSize = SizeFromClientSize(new Size(GetPanelButtonMinWidth(), GetClientMinHeight()));
429 |
430 | //参数意义定为客户区最大大小,所以需刨掉非客户区高度后传入
431 | this.ClientSize = this.GetPreferredSize(new Size(MaxClientWidth, Screen.PrimaryScreen.WorkingArea.Height - (this.Height - this.ClientSize.Height)));
432 |
433 | base.OnLoad(e);
434 | }
435 |
436 | protected override void OnShown(EventArgs e)
437 | {
438 | //设置默认按钮焦点。须在OnShown中设置按钮焦点才有用
439 | Button dfBtn;
440 | if ((dfBtn = this.AcceptButton as Button) != null)
441 | {
442 | dfBtn.Focus();
443 | }
444 |
445 | //播放消息提示音
446 | if (this.UseSound) { PlaySystemSound(this.messageSound); }
447 |
448 | base.OnShown(e);
449 | }
450 |
451 | //重写窗体参数
452 | protected override CreateParams CreateParams
453 | {
454 | get
455 | {
456 | CreateParams prms = base.CreateParams;
457 |
458 | if ((Convert.ToInt32(this.MessageButtons) & 1) == 0) //没有Cancel按钮时屏蔽关闭按钮,刚好在偶数项
459 | {
460 | prms.ClassStyle |= 0x200;
461 | }
462 |
463 | return prms;
464 | }
465 | }
466 |
467 | ///
468 | /// 计算合适的窗口尺寸
469 | ///
470 | /// 该参数此处定义为客户区可设置的最大尺寸
471 | public override Size GetPreferredSize(Size proposedSize)
472 | {
473 | int reservedHeight = plButtonsZone.Height + Padding.Bottom;
474 | Size size = lbMsg.GetPreferredSize(new Size(proposedSize.Width, proposedSize.Height - reservedHeight));
475 | size.Height += reservedHeight;
476 | return size;
477 | }
478 |
479 | #endregion
480 |
481 | #region 事件处理方法
482 |
483 | //展开收起
484 | private void ckbToggle_CheckedChanged(object sender, EventArgs e)
485 | {
486 | this.SuspendLayout();
487 |
488 | if (ckbToggle.Checked)
489 | {
490 | plButtonsZone.SendToBack();
491 | lbMsg.SendToBack();
492 |
493 | lbMsg.Dock = DockStyle.Top;
494 | plButtonsZone.Dock = DockStyle.Top;
495 |
496 | ChangeFormHeight(ExpandHeight);
497 | plAttachZone.Visible = true;
498 | }
499 | else
500 | {
501 | ExpandHeight = plAttachZone.Height;//为再次展开记忆高度
502 | plAttachZone.Visible = false;
503 | ChangeFormHeight(-plAttachZone.Height);//收起时直接取pl高度,不要取ExpandHeight
504 |
505 | plButtonsZone.SendToBack();
506 |
507 | plButtonsZone.Dock = DockStyle.Bottom;
508 | lbMsg.Dock = DockStyle.Fill;
509 | }
510 |
511 | this.ResumeLayout();
512 | }
513 |
514 | //按钮事件
515 | private void button_Click(object sender, EventArgs e)
516 | {
517 | this.DialogResult = (DialogResult)((sender as Button).Tag);
518 | }
519 |
520 | //用户手工收完详细区则触发折叠
521 | private void plAttachZone_Resize(object sender, EventArgs e)
522 | {
523 | if (ckbToggle.Checked && plAttachZone.Height == 0)
524 | {
525 | ckbToggle.Checked = false;
526 | }
527 | }
528 |
529 | #endregion
530 |
531 | #region 辅助+私有方法
532 |
533 | ///
534 | /// 处理按钮相关
535 | ///
536 | private void ProcessButtons()
537 | {
538 | this.ckbToggle.Visible = txbAttach.Text.Trim().Length != 0; //无详细信息就不显示展开按钮
539 |
540 | int btnCount = 3; //按钮数量
541 |
542 | switch (MessageButtons) //老实用case,可读点。给确定和取消加了助记键
543 | {
544 | case MessageBoxButtons.AbortRetryIgnore:
545 | button1.Text = "中止(&A)"; button1.Tag = DialogResult.Abort;
546 | button2.Text = "重试(&R)"; button2.Tag = DialogResult.Retry;
547 | button3.Text = "忽略(&I)"; button3.Tag = DialogResult.Ignore;
548 | break;
549 | case MessageBoxButtons.OK:
550 | button1.Visible = false;
551 | button2.Visible = false;
552 | button3.Text = "确定(&O)"; button3.Tag = DialogResult.OK;
553 | btnCount = 1;
554 | break;
555 | case MessageBoxButtons.OKCancel:
556 | button1.Visible = false;
557 | button2.Text = "确定(&O)"; button2.Tag = DialogResult.OK;
558 | button3.Text = "取消(&C)"; button3.Tag = DialogResult.Cancel;
559 | btnCount = 2;
560 | break;
561 | case MessageBoxButtons.RetryCancel:
562 | button1.Visible = false;
563 | button2.Text = "重试(&R)"; button2.Tag = DialogResult.Retry;
564 | button3.Text = "取消(&C)"; button3.Tag = DialogResult.Cancel;
565 | btnCount = 2;
566 | break;
567 | case MessageBoxButtons.YesNo:
568 | button1.Visible = false;
569 | button2.Text = "是(&Y)"; button2.Tag = DialogResult.Yes;
570 | button3.Text = "否(&N)"; button3.Tag = DialogResult.No;
571 | btnCount = 2;
572 | break;
573 | case MessageBoxButtons.YesNoCancel:
574 | button1.Text = "是(&Y)"; button1.Tag = DialogResult.Yes;
575 | button2.Text = "否(&N)"; button2.Tag = DialogResult.No;
576 | button3.Text = "取消(&C)"; button3.Tag = DialogResult.Cancel;
577 | break;
578 | default: break;
579 | }
580 |
581 | //仅有OK和有取消按钮时设CancelButton
582 | if ((int)MessageButtons == 0 || ((int)MessageButtons & 1) == 1)
583 | {
584 | this.CancelButton = button3;
585 | }
586 |
587 | //处理默认按钮
588 | if (btnCount == 1)
589 | {
590 | this.AcceptButton = button3;
591 | }
592 | else if (btnCount == 2)
593 | {
594 | this.AcceptButton = DefaultButton == MessageBoxDefaultButton.Button2 ? button3 : button2;
595 | }
596 | else
597 | {
598 | Button[] btnArray = { button1, button2, button3 };
599 | this.AcceptButton = btnArray[Convert.ToInt32(DefaultButton) / 0x100];
600 | }
601 | }
602 |
603 | ///
604 | /// 处理图标(含声音)
605 | ///
606 | private void ProcessIcon()
607 | {
608 | switch (MessageIcon)
609 | {
610 | //MessageBoxIcon.Information同样
611 | case MessageBoxIcon.Asterisk:
612 | lbMsg.Icon = SystemIcons.Information;
613 | messageSound = "SystemAsterisk";
614 | break;
615 |
616 | //MessageBoxIcon.Hand、MessageBoxIcon.Stop同样
617 | case MessageBoxIcon.Error:
618 | lbMsg.Icon = SystemIcons.Error;
619 | messageSound = "SystemHand";
620 | break;
621 |
622 | //MessageBoxIcon.Warning同样
623 | case MessageBoxIcon.Exclamation:
624 | lbMsg.Icon = SystemIcons.Warning;
625 | messageSound = "SystemExclamation";
626 | break;
627 |
628 | case MessageBoxIcon.Question:
629 | lbMsg.Icon = SystemIcons.Question;
630 | messageSound = "SystemAsterisk";//Question原本是没声音的,此实现让它蹭一下Information的
631 | break;
632 |
633 | default: //MessageBoxIcon.None
634 | lbMsg.Icon = null;
635 | messageSound = "SystemDefault";
636 | break;
637 | }
638 | }
639 |
640 | ///
641 | /// 计算窗体客户区最小高度
642 | ///
643 | private int GetClientMinHeight()
644 | {
645 | return lbMsg.MinimumHeight + plButtonsZone.Height + Padding.Bottom;
646 | }
647 |
648 | ///
649 | /// 计算按钮区最小宽度
650 | ///
651 | private int GetPanelButtonMinWidth()
652 | {
653 | int r = 20 /*左右Padding*/, visibleCount = -1 /*因为两个以上才会有间距*/;
654 |
655 | if (ckbToggle.Visible) { r += ckbToggle.Width; visibleCount++; }
656 | if (button1.Visible) { r += button1.Width * 3; visibleCount += 3; }
657 | else if (button2.Visible) { r += button2.Width * 2; visibleCount += 2; }
658 | else { r += button3.Width; visibleCount++; }
659 |
660 | if (visibleCount != -1) { r += visibleCount * 6; } //按钮间距
661 |
662 | return r;
663 | }
664 |
665 | ///
666 | /// 改变窗体高度。内部有动画处理
667 | ///
668 | /// 增量(负数即为减小高度)
669 | private void ChangeFormHeight(int increment)
670 | {
671 | int finalHeight = this.Height + increment; //正确的目标高度
672 |
673 | if (!this.UseAnimate) //不使用动画
674 | {
675 | this.Height = finalHeight;
676 | return;
677 | }
678 |
679 | const int step = 8; //帧数
680 |
681 | for (int i = 0; i < step; i++)
682 | {
683 | if (i == step - 1) //最后一步直达目标
684 | {
685 | this.Height = finalHeight;
686 | return;
687 | }
688 |
689 | this.Height += increment / step;
690 |
691 | Application.DoEvents(); //必要
692 | Thread.Sleep(10);
693 | }
694 | }
695 |
696 | ///
697 | /// 播放系统事件声音
698 | ///
699 | /// 之所以不用MessageBeep API是因为这货在srv08上不出声,所以用PlaySound代替
700 | private static void PlaySystemSound(string soundAlias)
701 | {
702 | PlaySound(soundAlias, IntPtr.Zero, 0x10000 /*SND_ALIAS*/| 0x1 /*SND_ASYNC*/);
703 | }
704 |
705 | [DllImport("winmm.dll", CharSet = CharSet.Auto)]
706 | private static extern bool PlaySound([MarshalAs(UnmanagedType.LPWStr)] string soundName, IntPtr hmod, int soundFlags);
707 |
708 | #endregion
709 |
710 | #region 嵌套类
711 |
712 | ///
713 | /// 基础面板
714 | ///
715 | private class PanelBasic : Control
716 | {
717 | public PanelBasic()
718 | {
719 | SetStyle(ControlStyles.AllPaintingInWmPaint, false);//关键,不然其上的ToolBar不正常
720 | SetStyle(ControlStyles.OptimizedDoubleBuffer, true);//重要。不设置的话控件绘制不正常
721 | SetStyle(ControlStyles.ContainerControl, true);
722 | SetStyle(ControlStyles.Selectable, false);
723 | }
724 |
725 | protected override void WndProc(ref Message m)
726 | {
727 | //屏蔽WM_ERASEBKGND。防止显示时在原位置快闪
728 | //不能通过ControlStyles.AllPaintingInWmPaint=true屏蔽
729 | //会影响其上的ToolBar
730 | if (m.Msg == 0x14) { return; }
731 |
732 | base.WndProc(ref m);
733 | }
734 |
735 | protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
736 | {
737 | //防Dock时面板短暂滞留在原位置
738 | base.SetBoundsCore(x, y, width, height, specified | BoundsSpecified.Y | BoundsSpecified.Width);
739 | }
740 | }
741 |
742 | ///
743 | /// 消息呈现控件
744 | ///
745 | private class MessageViewer : Control
746 | {
747 | const TextFormatFlags textFlags = TextFormatFlags.EndEllipsis //未完省略号
748 | | TextFormatFlags.WordBreak //允许换行
749 | | TextFormatFlags.NoPadding //无边距
750 | | TextFormatFlags.ExternalLeading //行间空白。NT5必须,不然文字挤在一起
751 | | TextFormatFlags.TextBoxControl; //避免半行
752 |
753 | const int IconSpace = 5; //图标与文本间距
754 |
755 | const float PreferredScale = 13;//最佳文本区块比例(宽/高)
756 |
757 | ///
758 | /// 最小高度。不要重写MinimumSize,那会在窗体移动和缩放时都会执行
759 | ///
760 | public int MinimumHeight
761 | {
762 | get
763 | {
764 | return (this.Icon != null ? Math.Max(this.Icon.Height, this.FontHeight) : this.FontHeight) + Padding.Vertical;
765 | }
766 | }
767 |
768 | ///
769 | /// 获取或设置图标
770 | ///
771 | public Icon Icon { get; set; }
772 |
773 | public MessageViewer()
774 | {
775 | this.SetStyle(ControlStyles.CacheText, true);
776 | this.SetStyle(ControlStyles.UserPaint, true);
777 | this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
778 | this.SetStyle(ControlStyles.Selectable, false);
779 | this.SetStyle(ControlStyles.ResizeRedraw, true); //重要
780 |
781 | this.DoubleBuffered = true; //双缓冲
782 | BackColor = Environment.OSVersion.Version.Major == 5 ? SystemColors.Control : Color.White;
783 | }
784 |
785 | //防Dock改变尺寸
786 | protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
787 | {
788 | base.SetBoundsCore(x, y, width, height, specified | BoundsSpecified.Size);
789 | }
790 |
791 | ///
792 | /// 计算合适的消息区尺寸
793 | ///
794 | /// 该参数此处定义为此控件可设置的最大尺寸
795 | /// 该方法对太长的单行文本有做比例优化处理,避免用户摆头幅度过大扭到脖子
796 | public override Size GetPreferredSize(Size proposedSize)
797 | {
798 | if (proposedSize.Width < 10) { proposedSize.Width = int.MaxValue; }
799 | if (proposedSize.Height < 10) { proposedSize.Height = int.MaxValue; }
800 |
801 | int reservedWidth = Padding.Horizontal + (this.Icon == null ? 0 : (this.Icon.Width + IconSpace));
802 |
803 | Size wellSize = Size.Empty;
804 | if (!string.IsNullOrEmpty(this.Text))
805 | {
806 | //优化文本块宽高比例
807 | Size size = TextRenderer.MeasureText(this.Text, this.Font, new Size(proposedSize.Width - reservedWidth, 0), textFlags);//用指定宽度测量文本面积
808 | wellSize = Convert.ToSingle(size.Width) / size.Height > PreferredScale //过于宽扁的情况
809 | ? Size.Ceiling(GetSameSizeWithNewScale(size, PreferredScale))
810 | : size;
811 |
812 | //凑齐整行高,确保尾行显示
813 | int lineHeight = TextRenderer.MeasureText(" ", this.Font, new Size(int.MaxValue, 0), textFlags).Height;//单行高,Font.Height不靠谱
814 | int differ;
815 | wellSize.Height += (differ = wellSize.Height % lineHeight) == 0 ? 0 : (lineHeight - differ);
816 | }
817 | if (this.Icon != null)
818 | {
819 | wellSize.Width += this.Icon.Width + IconSpace;
820 | wellSize.Height = Math.Max(this.Icon.Height, wellSize.Height);
821 | }
822 | wellSize += Padding.Size;
823 |
824 | //不应超过指定尺寸。宽度在上面已确保不会超过
825 | if (wellSize.Height > proposedSize.Height) { wellSize.Height = proposedSize.Height; }
826 |
827 | return wellSize;
828 | }
829 |
830 | ///
831 | /// 重绘
832 | ///
833 | protected override void OnPaint(PaintEventArgs e)
834 | {
835 | Graphics g = e.Graphics;
836 | Rectangle rect = GetPaddedRectangle();
837 |
838 | //绘制图标
839 | if (this.Icon != null)
840 | {
841 | g.DrawIcon(this.Icon, Padding.Left, Padding.Top);
842 |
843 | //右移文本区
844 | rect.X += this.Icon.Width + IconSpace;
845 | rect.Width -= this.Icon.Width + IconSpace;
846 |
847 | //若文字太少,则与图标垂直居中
848 | if (this.Text.Length < 100)
849 | {
850 | Size textSize = TextRenderer.MeasureText(g, this.Text, this.Font, rect.Size, textFlags);
851 | if (textSize.Height <= this.Icon.Height)
852 | {
853 | rect.Y += (this.Icon.Height - textSize.Height) / 2;
854 | }
855 | }
856 | }
857 |
858 | //g.FillRectangle(Brushes.Gainsboro, rect);//test
859 |
860 | //绘制文本
861 | TextRenderer.DrawText(g, this.Text, this.Font, rect, Color.Black, textFlags);
862 |
863 | base.OnPaint(e);
864 | }
865 |
866 | ///
867 | /// 根据原尺寸,得到相同面积、且指定比例的新尺寸
868 | ///
869 | /// 原尺寸
870 | /// 新尺寸比例。需是width/height
871 | private static SizeF GetSameSizeWithNewScale(Size src, float scale)
872 | {
873 | int sqr = src.Width * src.Height;//原面积
874 | double w = Math.Sqrt(sqr * scale);//新面积宽
875 | return new SizeF(Convert.ToSingle(w), Convert.ToSingle(sqr / w));
876 | }
877 |
878 | ///
879 | /// 获取刨去Padding的内容区
880 | ///
881 | private Rectangle GetPaddedRectangle()
882 | {
883 | Rectangle r = this.ClientRectangle;
884 | r.X += this.Padding.Left;
885 | r.Y += this.Padding.Top;
886 | r.Width -= this.Padding.Horizontal;
887 | r.Height -= this.Padding.Vertical;
888 | return r;
889 | }
890 | }
891 |
892 | ///
893 | /// 屏蔽全选消息的文本框
894 | ///
895 | private class TextBoxUnSelectAllable : TextBox
896 | {
897 | protected override void WndProc(ref Message m)
898 | {
899 | //EM_SETSEL
900 | if (m.Msg == 0xB1) { return; }
901 |
902 | base.WndProc(ref m);
903 | }
904 | }
905 |
906 | ///
907 | /// 包装ToolBarButton为单一控件
908 | ///
909 | private class ToggleButton : Control
910 | {
911 | ///
912 | /// 展开/收起图标数据
913 | ///
914 | const string ImgDataBase64 =
915 | @"iVBORw0KGgoAAAANSUhEUgAAACAAAAAQCAYAAAB3AH1ZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ
916 | bWFnZVJlYWR5ccllPAAAA3NJREFUeNqklVlPFEEQx/8zPccue6gorMd6gBegeCAQD4w+oCx+AInx
917 | IB4EfTK8+g2MQUUTcBU8En0wmvigEkyMxgcTjRrUqHFVUBRQQaJGl2WPmbG6dzCLWUiESf7T0739
918 | 666urqqVDjVcxT9PAWkfqZKUY491ktpIzaRXGPv5L15J+dZIRx26dqAwf56c48+Cx+1CzDDR//13
919 | /seevvx3HZ8OxmLxMzSvjhT5Z+Nx8UoKfHOu31e+qWwZPBkOMBkwTAvRuAE21QuvJwNz5s6U25++
920 | rv365dtC+4SxifJsfeVWvsCJ2TOzqyo2FsHt1OBSFeiqTItIsOhHw7JgGBZM+s72TcOvX+GccHgw
921 | k7qttgHj5slOLNE0tXZNSQGYJEEhiDEJusLoW4ZMfZnGJVv0QmHhYuiaup+zE+W5Aftyc/xMURRh
922 | acJIKpowqDVhkhu5LCspiY6k0OIL5s9mdrCNyp9sDKL+6PExeW5AwOebigRNiiVMkoFIPIFwlLcG
923 | huIm4mRI3DRpAQg38oPMmD6Nuz4wGn+koRGH64/hxr1HuHjl2qg8D8JcZ4ZTRCtLSDjT1Ijz51rS
924 | 5lfVzj2o2rWXXCzDPcnNh3L5K5WntdHYdAqng6cwa/EK+AuK8SDUSx65gUAlxR1ZkcqLLDBpkJ+S
925 | R8yOvbXw+vx4GOoZsXlZyQqsK10pNlDpjlVZDPMs0FL55mATLl04C39+EWblFf3l2zs+w7jZii1b
926 | Kkfw3IDOcDiS5/G4yLjknQcCAbrPW3j8plvMWlu8XGwOsblMASYjFh3i3S4SS+W3Vddg++6apJ8t
927 | OwN4HHH/p+G5AW3f+gbyvB632DwGHigSyjdvpn4b9ElZWF9aJE6uMAanJsOlK3jdNcAXuE2y0vEQ
928 | rcXfyeCT0vPcES0funoNRTJpgixSRUQsLbapogIbVq8S47rKCORShQvbX7437NI6Km8Ol9sxeG7A
929 | i2g0Fnz2PAQ3TcjQGBw02UGWOqig8L7bweB1qCSFxHD3/nMMDkWDnJ0oP1yK6z529y1i8ovydaVL
930 | wXOaXxl3W7K4yKKykY/Rdq8dofe9d+x6jonyw6WYu+Pyj5/hzLedPcU61dDJLh1T3E4BRgYjCHV0
931 | 4/qdJ+bn/h+naW41KZpiwLh5Kc3fMS+vNXaRybVT7YMdcM2228d6/ov/I8AAPfkI7yO+mM8AAAAA
932 | SUVORK5CYII=";
933 |
934 | readonly bool isToggleMode;
935 | bool isChecked;
936 | bool useAnimate;
937 | readonly ImageList imgList;
938 |
939 | ///
940 | /// Checked改变后
941 | ///
942 | public event EventHandler CheckedChanged;
943 |
944 | ///
945 | /// 使用动画按钮效果
946 | ///
947 | private bool UseAnimate
948 | {
949 | get { return useAnimate; }
950 | set
951 | {
952 | if (useAnimate == value) { return; }
953 |
954 | useAnimate = value;
955 | if (IsHandleCreated) { this.CreateHandle(); }
956 | }
957 | }
958 |
959 | ///
960 | /// 获取或设置按钮是否处于按下状态
961 | ///
962 | [Description("获取或设置按钮是否处于按下状态"), DefaultValue(false)]
963 | public bool Checked
964 | {
965 | get
966 | {
967 | if (IsHandleCreated)
968 | {
969 | //保证isChecked与实情吻合。TB_ISBUTTONCHECKED
970 | isChecked = Convert.ToBoolean(SendMessage(this.Handle, 0x40A, IntPtr.Zero, IntPtr.Zero).ToInt32());
971 | }
972 | return isChecked;
973 | }
974 | set
975 | {
976 | if (isChecked == value || !isToggleMode) { return; }
977 |
978 | isChecked = value;
979 |
980 | if (IsHandleCreated)
981 | {
982 | //TB_CHECKBUTTON
983 | SendMessage(this.Handle, 0x402, IntPtr.Zero, new IntPtr(Convert.ToInt32(value)));
984 | }
985 |
986 | OnCheckedChanged(EventArgs.Empty);
987 | }
988 | }
989 |
990 | ///
991 | /// 创建ToolBarButtonControl
992 | ///
993 | public ToggleButton(bool useAnimate)
994 | {
995 | SetStyle(ControlStyles.UserPaint, false);
996 | SetStyle(ControlStyles.AllPaintingInWmPaint, true);
997 | SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
998 | SetStyle(ControlStyles.ResizeRedraw, true);
999 |
1000 | this.isToggleMode = true;//写死好了,独立版才提供设置
1001 | this.UseAnimate = useAnimate;
1002 |
1003 | //将图标加入imageList
1004 | imgList = new ImageList { ImageSize = new System.Drawing.Size(16, 16), ColorDepth = ColorDepth.Depth32Bit };
1005 | using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(ImgDataBase64)))
1006 | {
1007 | imgList.Images.AddStrip(Image.FromStream(ms));
1008 | }
1009 | }
1010 |
1011 | ///
1012 | /// 执行左键单击
1013 | ///
1014 | public void PerformClick()
1015 | {
1016 | SendMessage(this.Handle, 0x201, new IntPtr(0x1), IntPtr.Zero);//WM_LBUTTONDOWN
1017 | Application.DoEvents();
1018 | SendMessage(this.Handle, 0x202, IntPtr.Zero, IntPtr.Zero); //WM_LBUTTONUP
1019 | }
1020 |
1021 | protected override void WndProc(ref Message m)
1022 | {
1023 | //忽略鼠标双击消息,WM_LBUTTONDBLCLK
1024 | if (m.Msg == 0x203) { return; }
1025 |
1026 | //有节操的响应鼠标动作
1027 | if ((m.Msg == 0x201 || m.Msg == 0x202) && (!this.Enabled || !this.Visible))
1028 | {
1029 | return;
1030 | }
1031 | base.WndProc(ref m);
1032 | }
1033 |
1034 | //创建ToolBar
1035 | protected override CreateParams CreateParams
1036 | {
1037 | get
1038 | {
1039 | CreateParams prms = base.CreateParams;
1040 | prms.ClassName = "ToolbarWindow32";
1041 | prms.Style = 0x40000000
1042 | | 0x10000000
1043 | //| 0x2000000 //WS_CLIPCHILDREN
1044 | //| 0x8000
1045 | | 0x1
1046 | | 0x4
1047 | | 0x8
1048 | | 0x40
1049 | | 0x1000 //TBSTYLE_LIST,图标文本横排
1050 | ;
1051 | if (UseAnimate) { prms.Style |= 0x800; }//TBSTYLE_FLAT。flat模式在NT6.x下,按钮按下会有动画效果
1052 |
1053 | prms.ExStyle = 0;
1054 |
1055 | return prms;
1056 | }
1057 | }
1058 |
1059 | protected override void OnHandleCreated(EventArgs e)
1060 | {
1061 | base.OnHandleCreated(e);
1062 |
1063 | //设置imgList
1064 | SendMessage(this.Handle, 0x430, IntPtr.Zero, imgList.Handle);//TB_SETIMAGELIST
1065 |
1066 | //准备添加按钮
1067 | int btnStructSize = Marshal.SizeOf(typeof(TBBUTTON));
1068 | SendMessage(this.Handle, 0x41E, new IntPtr(btnStructSize), IntPtr.Zero);//TB_BUTTONSTRUCTSIZE,必须在添加按钮前
1069 |
1070 | //构建按钮信息
1071 | TBBUTTON btnStruct = new TBBUTTON
1072 | {
1073 | //iBitmap = 0,
1074 | //idCommand = 0,
1075 | fsState = 0x4, //TBSTATE_ENABLED
1076 | iString = SendMessage(this.Handle, 0x44D, 0, this.Text + '\0')//TB_ADDSTRING
1077 | };
1078 | if (this.isToggleMode) { btnStruct.fsStyle = 0x2; }//BTNS_CHECK。作为切换按钮时
1079 |
1080 | IntPtr btnStructStart = IntPtr.Zero;
1081 | try
1082 | {
1083 | btnStructStart = Marshal.AllocHGlobal(btnStructSize);//在非托管区创建一个指针
1084 | Marshal.StructureToPtr(btnStruct, btnStructStart, true);//把结构体塞到上述指针
1085 |
1086 | //添加按钮
1087 | SendMessage(this.Handle, 0x444, new IntPtr(1)/*按钮数量*/, btnStructStart);//TB_ADDBUTTONS。从指针取按钮信息
1088 |
1089 | //设置按钮尺寸刚好为ToolBar尺寸
1090 | AdjustButtonSize();
1091 | }
1092 | finally
1093 | {
1094 | if (btnStructStart != IntPtr.Zero) { Marshal.FreeHGlobal(btnStructStart); }
1095 | }
1096 | }
1097 |
1098 | protected override bool ProcessCmdKey(ref Message m, Keys keyData)
1099 | {
1100 | //将空格和回车作为鼠标单击处理
1101 | if (m.Msg == 0x100 && (keyData == Keys.Enter || keyData == Keys.Space))
1102 | {
1103 | PerformClick();
1104 | return true;
1105 | }
1106 |
1107 | return base.ProcessCmdKey(ref m, keyData);
1108 | }
1109 |
1110 | ///
1111 | /// 处理助记键
1112 | ///
1113 | protected override bool ProcessMnemonic(char charCode)
1114 | {
1115 | if (IsMnemonic(charCode, this.Text))
1116 | {
1117 | PerformClick();
1118 | return true;
1119 | }
1120 |
1121 | return base.ProcessMnemonic(charCode);
1122 | }
1123 |
1124 | protected override void OnClick(EventArgs e)
1125 | {
1126 | //忽略鼠标右键
1127 | MouseEventArgs me = e as MouseEventArgs;
1128 | if (me != null && me.Button != System.Windows.Forms.MouseButtons.Left)
1129 | { return; }
1130 |
1131 | //若是切换模式,直接引发Checked事件(不要通过设置Checked属性引发,因为OnClick发送之前就已经Check了)
1132 | //存在理论上的不可靠,但暂无更好办法
1133 | if (isToggleMode)
1134 | { this.OnCheckedChanged(EventArgs.Empty); }
1135 |
1136 | base.OnClick(e);
1137 | }
1138 |
1139 | //重绘后重设按钮尺寸
1140 | protected override void OnInvalidated(InvalidateEventArgs e)
1141 | {
1142 | base.OnInvalidated(e);
1143 | AdjustButtonSize();
1144 | }
1145 |
1146 | ///
1147 | /// 引发CheckedChanged事件
1148 | ///
1149 | protected virtual void OnCheckedChanged(EventArgs e)
1150 | {
1151 | SetImageIndex(this.Checked ? 1 : 0);
1152 |
1153 | if (CheckedChanged != null) { CheckedChanged(this, e); }
1154 | }
1155 |
1156 | ///
1157 | /// 设置图标索引
1158 | ///
1159 | private void SetImageIndex(int index)
1160 | {
1161 | //TB_CHANGEBITMAP
1162 | SendMessage(this.Handle, 0x42B, IntPtr.Zero, new IntPtr(index));
1163 | }
1164 |
1165 | ///
1166 | /// 调整按钮尺寸刚好为ToolBar尺寸
1167 | ///
1168 | private void AdjustButtonSize()
1169 | {
1170 | IntPtr lParam = new IntPtr((this.Width & 0xFFFF) | (this.Height << 0x10)); //MakeLParam手法
1171 | SendMessage(this.Handle, 0x41F, IntPtr.Zero, lParam); //TB_SETBUTTONSIZE
1172 | }
1173 |
1174 | #region Win32 API
1175 |
1176 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
1177 | private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
1178 |
1179 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
1180 | private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, string lParam);
1181 |
1182 | [StructLayout(LayoutKind.Sequential)]
1183 | private struct TBBUTTON
1184 | {
1185 | public int iBitmap;
1186 | public int idCommand;
1187 | public byte fsState;
1188 | public byte fsStyle;
1189 | public byte bReserved0;
1190 | public byte bReserved1;
1191 | public IntPtr dwData;
1192 | public IntPtr iString;
1193 | }
1194 |
1195 | #endregion
1196 | }
1197 |
1198 | #endregion
1199 | }
1200 | }
1201 | }
1202 |
--------------------------------------------------------------------------------
/CustomControls/RadioGroupBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Windows.Forms;
4 |
5 | namespace AhDung.WinForm.Controls
6 | {
7 | ///
8 | /// 单选组面板
9 | ///
10 | [ToolboxItem(true)]
11 | public class RadioGroupBox : CheckableGroupBox, IRadioControl
12 | {
13 | Control _lastParent;
14 |
15 | ///
16 | /// 初始化本类
17 | ///
18 | public RadioGroupBox()
19 | : base(false)
20 | {
21 | this.ParentChanged += RadioGroupBox_ParentChanged;
22 | }
23 |
24 | void RadioGroupBox_ParentChanged(object sender, EventArgs e)
25 | {
26 | if (_lastParent != null)
27 | {
28 | foreach (Control c in _lastParent.Controls)
29 | {
30 | if (c is RadioButton)
31 | {
32 | ((RadioButton)c).CheckedChanged -= RadioGroupBox_CheckedChanged;
33 | }
34 | }
35 | _lastParent.ControlAdded -= Parent_ControlAdded;
36 | _lastParent.ControlRemoved -= Parent_ControlRemoved;
37 | }
38 | _lastParent = Parent;
39 | if (_lastParent != null)
40 | {
41 | foreach (Control c in _lastParent.Controls)
42 | {
43 | if (c is RadioButton)
44 | {
45 | ((RadioButton)c).CheckedChanged += RadioGroupBox_CheckedChanged;
46 | }
47 | }
48 | _lastParent.ControlAdded += Parent_ControlAdded;
49 | _lastParent.ControlRemoved += Parent_ControlRemoved;
50 | }
51 | }
52 |
53 | void RadioGroupBox_CheckedChanged(object sender, EventArgs e)
54 | {
55 | var rb = sender as RadioButton;
56 | if (rb.Checked)
57 | {
58 | this.Checked = false;
59 | }
60 | }
61 |
62 | void Parent_ControlAdded(object sender, ControlEventArgs e)
63 | {
64 | if (e.Control is RadioButton)
65 | {
66 | ((RadioButton)e.Control).CheckedChanged += RadioGroupBox_CheckedChanged;
67 | }
68 | }
69 |
70 | void Parent_ControlRemoved(object sender, ControlEventArgs e)
71 | {
72 | if (e.Control is RadioButton)
73 | {
74 | ((RadioButton)e.Control).CheckedChanged -= RadioGroupBox_CheckedChanged;
75 | }
76 | }
77 |
78 | protected override void OnCheckedChanged(EventArgs e)
79 | {
80 | //互斥。
81 | if (this.Checked && this.Parent != null)
82 | {
83 | foreach (Control c in this.Parent.Controls)
84 | {
85 | if (c == this) { continue; }
86 |
87 | if (c is RadioButton)
88 | {
89 | ((RadioButton)c).Checked = false;
90 | }
91 | else if (c is IRadioControl)
92 | {
93 | ((IRadioControl)c).Checked = false;
94 | }
95 | }
96 | }
97 | base.OnCheckedChanged(e);
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/DialogDragger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Drawing;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 |
7 | namespace AhDung.WinForm
8 | {
9 | //todo 颜色对话框有问题,禁止使用
10 | ///
11 | /// 对话框拖拽器
12 | ///
13 | [Obsolete("尚有严重问题,禁用", true)]
14 | internal static class DialogDragger
15 | {
16 | private static bool CanDrag(IntPtr hWnd)//, POINT pt)
17 | {
18 | var name = GetClassName(hWnd);
19 | switch (name)
20 | {
21 | case "SysTabControl32":
22 | case "msctls_progress32":
23 | case "msctls_statusbar32":
24 | return true;
25 |
26 | case "Static":
27 | return !HasStyle(hWnd, 0xB/*SS_SIMPLE*/);
28 |
29 | case "Button":
30 | return HasStyle(hWnd, 7/*BS_GROUPBOX*/);
31 | }
32 | return false;
33 | }
34 |
35 | ///
36 | /// 钩子消息处理过程
37 | ///
38 | private static IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam)
39 | {
40 | if (nCode == 0/*MSGF_DIALOGBOX*/)
41 | {
42 | var m = (MSG)Marshal.PtrToStructure(lParam, typeof(MSG));
43 | switch (m.Msg)
44 | {
45 | case 0x201:
46 | //todo 颜色对话框中的色块点击时得到的句柄是窗体本身,暂时没办法处理
47 | if ((int)m.wParam != 1) { break; }
48 | if (GetClassName(m.hWnd) == "ComboLBox") { break; }
49 |
50 | var hForm = GetAncestor(m.hWnd, 2/*GA_ROOT*/);
51 | if (m.hWnd == hForm || CanDrag(m.hWnd))
52 | {
53 | SendMessage(hForm, 0xA1, (IntPtr)2, IntPtr.Zero);
54 | return (IntPtr)1;
55 | }
56 | break;
57 | }
58 | }
59 | return CallNextHookEx(_hHook, nCode, wParam, lParam);
60 | }
61 |
62 |
63 | static IntPtr _hHook;
64 | static HookProcDelegate _proc = HookProc;
65 |
66 | ///
67 | /// 安装钩子。不能重复安装
68 | ///
69 | ///
70 | ///
71 | private static void Install()
72 | {
73 | if (_hHook != IntPtr.Zero)
74 | {
75 | throw new InvalidOperationException();
76 | }
77 | // ReSharper disable once CSharpWarnings::CS0618
78 | _hHook = SetWindowsHookEx(-1/*WH_MSGFILTER*/, _proc, IntPtr.Zero, AppDomain.GetCurrentThreadId());
79 | if (_hHook == IntPtr.Zero)
80 | {
81 | throw new Win32Exception();
82 | }
83 | }
84 |
85 | ///
86 | /// 卸载钩子
87 | ///
88 | ///
89 | private static void UnInstall()
90 | {
91 | if (_hHook == IntPtr.Zero)
92 | {
93 | return;
94 | }
95 | if (UnhookWindowsHookEx(_hHook))
96 | {
97 | _hHook = IntPtr.Zero;
98 | }
99 | else
100 | {
101 | throw new Win32Exception();
102 | }
103 | }
104 |
105 | [StructLayout(LayoutKind.Sequential)]
106 | private struct MSG
107 | {
108 | public IntPtr hWnd;
109 | public int Msg;
110 | public IntPtr wParam;
111 | public IntPtr lParam;
112 | public int time;
113 | public POINT pt;
114 | }
115 |
116 | delegate IntPtr HookProcDelegate(int nCode, IntPtr wParam, IntPtr lParam);
117 |
118 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
119 | private static extern bool UnhookWindowsHookEx(IntPtr hhk);
120 |
121 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
122 | private static extern IntPtr SetWindowsHookEx(int idHook, HookProcDelegate lpfn, IntPtr hMod, int dwThreadId);
123 |
124 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
125 | private static extern IntPtr CallNextHookEx(IntPtr hhook, int code, IntPtr wparam, IntPtr lparam);
126 |
127 |
128 | ///
129 | /// 检查窗口是否含有指定样式
130 | ///
131 | private static bool HasStyle(IntPtr hWnd, int style, bool isExStyle = false)
132 | {
133 | var s = unchecked((int)(long)GetWindowLong(hWnd, isExStyle
134 | ? -20/*GWL_EXSTYLE*/
135 | : -16/*GWL_STYLE*/));
136 | return (s & style) == style;
137 | }
138 |
139 | private static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
140 | {
141 | if (IntPtr.Size == 4)
142 | {
143 | return GetWindowLong32(hWnd, nIndex);
144 | }
145 | return GetWindowLongPtr64(hWnd, nIndex);
146 | }
147 |
148 | [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindowLong")]
149 | private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
150 |
151 | [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindowLongPtr")]
152 | private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
153 |
154 | ///
155 | /// 获取窗口类名
156 | ///
157 | private static string GetClassName(IntPtr hWnd)
158 | {
159 | var sb = new StringBuilder(255);
160 | if (GetClassName(hWnd, sb, sb.Capacity) == 0)
161 | {
162 | throw new Win32Exception();
163 | }
164 | return sb.ToString();
165 | }
166 |
167 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
168 | private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
169 |
170 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
171 | private static extern IntPtr GetAncestor(IntPtr hWnd, int flags);
172 |
173 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
174 | private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
175 |
176 | [StructLayout(LayoutKind.Sequential)]
177 | private struct POINT
178 | {
179 | public int X;
180 | public int Y;
181 |
182 | public static explicit operator POINT(Point pt)
183 | {
184 | return new POINT { X = pt.X, Y = pt.Y };
185 | }
186 |
187 | public static explicit operator Point(POINT pt)
188 | {
189 | return new Point(pt.X, pt.Y);
190 | }
191 |
192 | public override string ToString()
193 | {
194 | return X + ", " + Y;
195 | }
196 | }
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/FmMDI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Windows.Forms;
4 | using AhDung.WinForm;
5 |
6 | namespace AhDung
7 | {
8 | public partial class FmMDI : Form
9 | {
10 | public FmMDI()
11 | {
12 | InitializeComponent();
13 |
14 | FormDragger.Dragging += FormDragger_Dragging;
15 | FormDragger.EnabledChanged += FormDragger_EnabledChanged;
16 |
17 | //例外方式一:将控件添加进例外列表
18 | //FormDragger.ExcludeControls.Add(pictureBox1);
19 | }
20 |
21 | void FormDragger_Dragging(object sender, FormDraggingCancelEventArgs e)
22 | {
23 | //例外方式二:在FormDragging事件中令Cancel = true
24 | //if (e.Control == pictureBox1)
25 | //{
26 | // e.Cancel = true;
27 | //}
28 | statusBarPanel1.Text = string.Format("{0}, {1}:{2}",
29 | e.Control.GetType().Name, e.IsClientArea ? "客户区坐标" : "屏幕坐标", e.MousePosition);
30 | }
31 |
32 | //图片点击事件。仅当该控件处于例外或关闭整个拖拽器时会触发
33 | private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
34 | {
35 | VisitAuthorHome();
36 | }
37 |
38 | private void checkBox1_CheckedChanged(object sender, EventArgs e)
39 | {
40 | //拖拽器开关
41 | FormDragger.Enabled = toolStripCheckBox1.Checked;
42 | }
43 |
44 | void FormDragger_EnabledChanged(object sender, EventArgs e)
45 | {
46 | //放心这里不会造成来回触发,因为Enabled内部有重入处理
47 | if (FormDragger.Enabled)
48 | {
49 | toolStripCheckBox1.Checked = true;
50 | toolStripCheckBox1.Text = "拖拽:开";
51 | }
52 | else
53 | {
54 | toolStripCheckBox1.Checked = false;
55 | toolStripCheckBox1.Text = "拖拽:关";
56 | }
57 | }
58 |
59 | private void FmMDI_Load(object sender, EventArgs e)
60 | {
61 | linkLabel1.Links.Add(2, 5, "AAA");
62 | linkLabel1.Links.Add(8, 6, "BBB").Enabled = false;
63 |
64 | treeView1.ExpandAll();
65 |
66 | this.ContextMenu = contextMenu1;
67 | }
68 |
69 | private void VisitAuthorHome()
70 | {
71 | Process.Start("http://www.cnblogs.com/ahdung/p/FormDragger.html");
72 | }
73 |
74 | private void btnAbout_Click(object sender, EventArgs e)
75 | {
76 | VisitAuthorHome();
77 | }
78 |
79 | private void newChild_Click(object sender, EventArgs e)
80 | {
81 | new FmTestDrag { MdiParent = this }.Show();
82 | }
83 |
84 | private void newNormal_Click(object sender, EventArgs e)
85 | {
86 | new FmTestDrag().Show();
87 | }
88 |
89 | private void newModal_Click(object sender, EventArgs e)
90 | {
91 | new FmTestDrag().ShowDialog();
92 | }
93 |
94 | //private void btnShowMsgBox_Click(object sender, EventArgs e)
95 | //{
96 | // MessageBox.Show("拖我试试");
97 | //}
98 |
99 | //private void miOpenFileDialog_Click(object sender, EventArgs e)
100 | //{
101 | // new OpenFileDialog().ShowDialog();
102 | //}
103 |
104 | //private void miSaveFileDialog_Click(object sender, EventArgs e)
105 | //{
106 | // new SaveFileDialog().ShowDialog();
107 | //}
108 |
109 | //private void miFolderBrowserDialog_Click(object sender, EventArgs e)
110 | //{
111 | // new FolderBrowserDialog().ShowDialog();
112 | //}
113 |
114 | //private void miColorDialog_Click(object sender, EventArgs e)
115 | //{
116 | // new ColorDialog().ShowDialog();
117 | //}
118 |
119 | //private void miFontDialog_Click(object sender, EventArgs e)
120 | //{
121 | // new FontDialog().ShowDialog();
122 | //}
123 |
124 | //private void miPageSetupDialog_Click(object sender, EventArgs e)
125 | //{
126 | // new PageSetupDialog() { Document = new PrintDocument() }.ShowDialog();
127 | //}
128 |
129 | //private void miPrintDialog_Click(object sender, EventArgs e)
130 | //{
131 | // //todo 勾不到
132 | // new PrintDialog() { UseEXDialog = true }.ShowDialog();
133 | //}
134 |
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/FmTabMDI.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace AhDung
2 | {
3 | partial class FmTabMDI
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.tabControl1 = new System.Windows.Forms.TabControl();
32 | this.tabPage1 = new System.Windows.Forms.TabPage();
33 | this.tabPage2 = new System.Windows.Forms.TabPage();
34 | this.button1 = new System.Windows.Forms.Button();
35 | this.tabControl1.SuspendLayout();
36 | this.SuspendLayout();
37 | //
38 | // tabControl1
39 | //
40 | this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
41 | | System.Windows.Forms.AnchorStyles.Left)
42 | | System.Windows.Forms.AnchorStyles.Right)));
43 | this.tabControl1.Controls.Add(this.tabPage1);
44 | this.tabControl1.Controls.Add(this.tabPage2);
45 | this.tabControl1.Location = new System.Drawing.Point(12, 71);
46 | this.tabControl1.Name = "tabControl1";
47 | this.tabControl1.SelectedIndex = 0;
48 | this.tabControl1.Size = new System.Drawing.Size(776, 367);
49 | this.tabControl1.TabIndex = 0;
50 | //
51 | // tabPage1
52 | //
53 | this.tabPage1.Location = new System.Drawing.Point(4, 22);
54 | this.tabPage1.Name = "tabPage1";
55 | this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
56 | this.tabPage1.Size = new System.Drawing.Size(768, 341);
57 | this.tabPage1.TabIndex = 0;
58 | this.tabPage1.Text = "tabPage1";
59 | this.tabPage1.UseVisualStyleBackColor = true;
60 | //
61 | // tabPage2
62 | //
63 | this.tabPage2.Location = new System.Drawing.Point(4, 22);
64 | this.tabPage2.Name = "tabPage2";
65 | this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
66 | this.tabPage2.Size = new System.Drawing.Size(192, 74);
67 | this.tabPage2.TabIndex = 1;
68 | this.tabPage2.Text = "tabPage2";
69 | this.tabPage2.UseVisualStyleBackColor = true;
70 | //
71 | // button1
72 | //
73 | this.button1.Location = new System.Drawing.Point(16, 12);
74 | this.button1.Name = "button1";
75 | this.button1.Size = new System.Drawing.Size(163, 23);
76 | this.button1.TabIndex = 1;
77 | this.button1.Text = "ShowCustomMessageBox";
78 | this.button1.UseVisualStyleBackColor = true;
79 | this.button1.Click += new System.EventHandler(this.button1_Click);
80 | //
81 | // FmTabMDI
82 | //
83 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
84 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
85 | this.ClientSize = new System.Drawing.Size(800, 450);
86 | this.Controls.Add(this.button1);
87 | this.Controls.Add(this.tabControl1);
88 | this.Name = "FmTabMDI";
89 | this.Text = "FmTabMDI";
90 | this.Load += new System.EventHandler(this.FmTabMDI_Load);
91 | this.tabControl1.ResumeLayout(false);
92 | this.ResumeLayout(false);
93 |
94 | }
95 |
96 | #endregion
97 |
98 | private System.Windows.Forms.TabControl tabControl1;
99 | private System.Windows.Forms.TabPage tabPage1;
100 | private System.Windows.Forms.TabPage tabPage2;
101 | private System.Windows.Forms.Button button1;
102 | }
103 | }
--------------------------------------------------------------------------------
/FmTabMDI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using AhDung.WinForm;
4 |
5 | namespace AhDung
6 | {
7 | public partial class FmTabMDI : Form
8 | {
9 | public FmTabMDI()
10 | {
11 | InitializeComponent();
12 | }
13 |
14 | private void button1_Click(object sender, EventArgs e)
15 | {
16 | var form = tabControl1.SelectedTab.Controls[0];
17 | MessageBoxEx.Show(form.GetType().ToString(), "Custom message box", "attach message");
18 | }
19 |
20 | private void FmTabMDI_Load(object sender, EventArgs e)
21 | {
22 | foreach (TabPage page in tabControl1.TabPages)
23 | {
24 | page.Controls.Add(new FmTabSub { TopLevel = false, Dock = DockStyle.Fill, FormBorderStyle = FormBorderStyle.None, Visible = true });
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/FmTabMDI.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/FmTabSub.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace AhDung
2 | {
3 | partial class FmTabSub
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.label1 = new System.Windows.Forms.Label();
32 | this.button1 = new System.Windows.Forms.Button();
33 | this.SuspendLayout();
34 | //
35 | // label1
36 | //
37 | this.label1.AutoSize = true;
38 | this.label1.Location = new System.Drawing.Point(85, 57);
39 | this.label1.Name = "label1";
40 | this.label1.Size = new System.Drawing.Size(155, 12);
41 | this.label1.TabIndex = 0;
42 | this.label1.Text = "This is a Form in TabPage";
43 | //
44 | // button1
45 | //
46 | this.button1.Location = new System.Drawing.Point(87, 145);
47 | this.button1.Name = "button1";
48 | this.button1.Size = new System.Drawing.Size(75, 23);
49 | this.button1.TabIndex = 1;
50 | this.button1.Text = "button1";
51 | this.button1.UseVisualStyleBackColor = true;
52 | this.button1.Click += new System.EventHandler(this.button1_Click);
53 | //
54 | // FmTabSub
55 | //
56 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
57 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
58 | this.ClientSize = new System.Drawing.Size(537, 374);
59 | this.Controls.Add(this.button1);
60 | this.Controls.Add(this.label1);
61 | this.Name = "FmTabSub";
62 | this.Text = "FmTabSub";
63 | this.ResumeLayout(false);
64 | this.PerformLayout();
65 |
66 | }
67 |
68 | #endregion
69 |
70 | private System.Windows.Forms.Label label1;
71 | private System.Windows.Forms.Button button1;
72 | }
73 | }
--------------------------------------------------------------------------------
/FmTabSub.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Text;
7 | using System.Windows.Forms;
8 | using AhDung.WinForm;
9 |
10 | namespace AhDung
11 | {
12 | public partial class FmTabSub : Form
13 | {
14 | public FmTabSub()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | private void button1_Click(object sender, EventArgs e)
20 | {
21 | DialogResult = DialogResult.OK;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/FmTabSub.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/FmTestDrag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Windows.Forms;
4 | using AhDung.WinForm;
5 |
6 | namespace AhDung
7 | {
8 | public partial class FmTestDrag : Form
9 | {
10 | public FmTestDrag()
11 | {
12 | InitializeComponent();
13 |
14 | FormDragger.Dragging += FormDragger_Dragging;
15 | FormDragger.EnabledChanged += FormDragger_EnabledChanged;
16 |
17 | //例外方式一:将控件添加进例外列表
18 | //FormDragger.ExcludeControls.Add(pictureBox1);
19 | }
20 |
21 | void FormDragger_Dragging(object sender, FormDraggingCancelEventArgs e)
22 | {
23 | //例外方式二:在FormDragging事件中令Cancel = true
24 | //if (e.Control == pictureBox1)
25 | //{
26 | // e.Cancel = true;
27 | //}
28 | statusBarPanel1.Text = string.Format("{0}, {1}:{2}",
29 | e.Control.GetType().Name, e.IsClientArea ? "客户区坐标" : "屏幕坐标", e.MousePosition);
30 | }
31 |
32 | //图片点击事件。仅当该控件处于例外或关闭整个拖拽器时会触发
33 | private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
34 | {
35 | VisitAuthorHome();
36 | }
37 |
38 | private void checkBox1_CheckedChanged(object sender, EventArgs e)
39 | {
40 | //拖拽器开关
41 | FormDragger.Enabled = toolStripCheckBox1.Checked;
42 | }
43 |
44 | void FormDragger_EnabledChanged(object sender, EventArgs e)
45 | {
46 | //放心这里不会造成来回触发,因为Enabled内部有重入处理
47 | if (FormDragger.Enabled)
48 | {
49 | toolStripCheckBox1.Checked = true;
50 | toolStripCheckBox1.Text = "拖拽:开";
51 | }
52 | else
53 | {
54 | toolStripCheckBox1.Checked = false;
55 | toolStripCheckBox1.Text = "拖拽:关";
56 | }
57 | }
58 |
59 | private void FmMDI_Load(object sender, EventArgs e)
60 | {
61 | linkLabel1.Links.Add(2, 5, "AAA");
62 | linkLabel1.Links.Add(8, 6, "BBB").Enabled = false;
63 |
64 | treeView1.ExpandAll();
65 |
66 | this.ContextMenu = contextMenu1;
67 | }
68 |
69 | private void VisitAuthorHome()
70 | {
71 | Process.Start("http://www.cnblogs.com/ahdung/p/FormDragger.html");
72 | }
73 |
74 | private void btnAbout_Click(object sender, EventArgs e)
75 | {
76 | VisitAuthorHome();
77 | }
78 |
79 | private void newNormal_Click(object sender, EventArgs e)
80 | {
81 | new FmTestDrag().Show();
82 | }
83 |
84 | private void newModal_Click(object sender, EventArgs e)
85 | {
86 | new FmTestDrag().ShowDialog();
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/FmTestDrag.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 |
123 | /9j/4AAQSkZJRgABAQEAAAAAAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkK
124 | DA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQ
125 | EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCACkAeADASIAAhEBAxEB/8QA
126 | HwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIh
127 | MUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVW
128 | V1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG
129 | x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQF
130 | BgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV
131 | YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
132 | hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq
133 | 8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5K/ak1NNcuNB12e2Ntdtbvp+o2pPz2lzE5Z0IxwAXLA9CBkcV
134 | 43cald6papoSsn2skiNhIFG07cA5xjIXP/Avavpr9pu08M+LNIh8R6Qim7tr6ayuJQu0sAJAVYdyGUMC
135 | eTkHocV8uQ+Htd1iZvsdpLdSRfKOSSpC5AHrgAflRCS5rHfVozk+ZGx4U0648QQnw99qjsooHe5e4kJI
136 | O07Qq+pwV/75PrXreg+EvBttIWubwzu0jShphtCkqFAAHYBQOa8It5b2NRaMHCgjgEjaMkkDnvkdfSrs
137 | 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
491 | t2lU4yjKWI/NQfxNfnhoZzKh/wBiiipgbdD/2Q==
492 |
493 |
494 |
495 | True
496 |
497 |
498 | True
499 |
500 |
501 | True
502 |
503 |
504 | 720, 17
505 |
506 |
507 |
508 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
509 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
510 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
511 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
512 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
513 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
514 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
515 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
516 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
517 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
518 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
519 |
520 |
521 |
522 |
523 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
524 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
525 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
526 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
527 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
528 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
529 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
530 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
531 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
532 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
533 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
534 |
535 |
536 |
537 | 610, 17
538 |
539 |
540 |
541 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
542 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAERSURBVDhPrZDbSgJRGIXnpewd6jXsjSQvIrwoI0RQMChU
543 | 0iiDPCGiE3ZCRkvR8VzTeBhnyR5/ccaZNnPhB4t9sdf6Ln5hb8QeathNJFVFKF5C8DqL4ksDVHWGDf7j
544 | LHyPg6NjviSaFqlu5yQYR+KpupaIkrMknCxT3Y7v/NYYb0ITK1c3BarbWWhLQ7IR0cTKReyZ6lZ0XYei
545 | ztHpK4bAc+h1FgQijzSxMptrGIxVSO0xX3AaStFki7bUMVFmaMm/eJMGfIH/MkGzLep0AXn4h/r3CJV3
546 | mS9gn2bY4UY/UzQ7E9TqfeTFtnuB+XAfzSHKr11kSl/uBebDiZ89ZCst3OUkdwL28sIVsE83ock+EIQV
547 | 2Mz2wxeg6/UAAAAASUVORK5CYII=
548 |
549 |
550 |
551 |
552 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
553 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIySURBVDhPrZLfS5NRGMfff6H7boIuuq2pMZyL1eAt11CW
554 | DcOKsB9vpFmaLtNExco0av6CbIVLJ61Wk3BSkT/AFCkRZSpZmrmiJQ41xSaCwdfznL15XEUX0Reem5f3
555 | 8znnec4j/Zc8fxYGla91CS3eRTx0z6OpMYS7jmnU1X6B/VYA18snUVoyjsKCt8jLHcH5c36ouCQR2NUJ
556 | 1Nas4G9ZXlmFKbULh1Kf8lJxSfI+WeCCyopv6q+/h+DQ/DJ2WV5Ao1FgPegRAveDOS4oLfmq/h6dn/DH
557 | 4AJizD4UXJrCAUuzEDgbZrjgou2DiohshIcnQtgme5GTPYbkJKcQ1N8OckHW2REVi+RXuM8fxGaDG4oy
558 | ALPZIQQ11Z+5QDk1oKJ/hjv7P2FTfCMOH3mFxMQ6IbhROYWOdrCnBI4dfwPr0V4+bRoY9UzXppMjcDdS
559 | rC8hy3YhuFI2gTYf2A4Aza4f7N2/o/zaLB8qDYx6zszwr8P7k1thNFYIweXCMXgeAfedq2xxwjClZUeV
560 | Jd2GtDNFETiJwfs8MBjKhMCWN8pgoLoqzE8miH1GjE7G4PsZjE7OQsm9ij2mFg7rdrug1xcJAa2l4w7W
561 | r00Cgk/n38S7wBwC04u4UGxHrMHF4CbEJtyDLj5fCDIzhljfSxzeavRgyw4Zj9t64GvvQ0d3P3pfD2Kv
562 | 2QqNvgFxDN6urYdWmyMElJMnevh60obRktA701PRtGlg1DOdSkXwzrisaMG/RZLWAE60OMW5fNhvAAAA
563 | AElFTkSuQmCC
564 |
565 |
566 |
567 |
568 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
569 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIpSURBVDhPtZL/T1JRGMb5p1itrVZbbRpqZbawnBENV1I0
570 | jGlByTSyJTXJwq2oKZQb1KAv6JCYWSxvBrkkZUq4CeQEiRABFeLL072Xa0zRra31bO8v57zP5znnPYf1
571 | X+TxhWF6O7VtGYcnwbSWijKPOLzYrPSvLPwLS3huGUMlT7o9wGD9grVUBj+icdid03S9tDmgNxNwTgVQ
572 | J+rA8XNtWwM+uuZATMwxmQVRycuJFNyzIRitDlScugKzjSgFRGJJaIwEsrk8AsHIhnSL/Ssck37UNipQ
573 | I5DjtuYV7uksRYhr2kebhx2eP6nrycFIEh5fBA/1Nvru8q5+PDaOovK0rABwfwugWzcErfkzHhjsePL6
574 | E7q1VrTdNUDcrgGvSYlDZHN5XTNOnL8BVe8AJAoNDtZfLgDu9L1BPJmikzcrk81hlRwodZJwdBXziwnI
575 | OrVoaOkiT8C8hKLHBPO7CbywOaE1jeC+bhAd6meQdvZC1KoG/5IS3MZ2HObLUHZSggvkWq3wOvbWiAqA
576 | VpWeyStVfCUNf3AZ4zNhfHCFMEDMgye+hYr6FrDLzxQAUuVTpr0ocn74mchg5vsKRt1RcHp2Qv9+kZ78
577 | UcE17KkWFgHNN/uQzgBkGKLJPBZiecyGchjzrmFwPIF++xJUbDbUQzEacIArLpopSRSP4CUN1Obf1Abz
578 | uqob5KjiXwWH/GVl5HPt5zZh37GL2H1EiF1VZ7GDI6CNW5r/TSzWbwHYL0mKJ5czAAAAAElFTkSuQmCC
579 |
580 |
581 |
582 |
583 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
584 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHkSURBVDhPvZHfS1NhHIf3p5QypLr2D4goMwoMCi/qIugH
585 | Xe1Cr7qKDIMkZixwNhfWLGWbnuki0kXKzLU023KubBNPJrbRdOzocm6e2dPOO21mMS+CHvjcvOf9PF++
586 | 79H9M+7RT2iRRsIi9sEAXe43yAvf2LpSHq28G9uAnytNT4jMLewtcQ2Ht2pF8ps/aOt+gccX5lxD694S
587 | +1BQFD1RkN5DSFa4Z3uONKbgHE3h8KZ4OJTC1J8UiSzmfhd2uf1CoJHbyKOsZokl0kKwm+aeJaov+wjO
588 | rpQkVqdXfOz0bWAcVLghfaXxkUz3y2VxvpMGSwL3uMKh+gHezSSLEnNhX23vtYzKUirDfGyFj/Iy1mdx
589 | UWqR8iKhwtQLxjgH659y4EwvVXWPiwJt3/Ws+muywRrlqvkDdx3zQrCN8l1ldnEd3/QqFmkS/akHJYGS
590 | zjLzOUEwEsMf+sLI2zmaOou/93pPGoM5zvk7UU7fnBKxSBPoT7SXBNW1F/9Io2lKCNTCeomUyrS8xnBA
591 | wfUqyf1eP5U1ptJD/o1LzeNCsHPydtqdr6k4aiwvOHvNSya3ibU/QIdrEkvfhJislc32MfYfuV1eUGPw
592 | FF7bIVJVZ0N/soPK421UHGstlFvYd/hWecF/Qqf7CR0A5wwgSQA2AAAAAElFTkSuQmCC
593 |
594 |
595 |
596 |
597 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
598 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJSSURBVDhPtZJrSJNRGMdf6IN9KbpQn/pUEH2JIoLqQ0Zh
599 | FqYZRmJG1iKmUqKyLB2pqSm6vC1Nm5GXoeatEsVJ0RASR3eNzegikRq5lrV3857Fr/d9ddlICoL+8OfA
600 | Oef/e57zcIT/os7WLMw302muSGJ2689qqi7A44q8IzjtNYzarzHQm8tZtT8FmRqu6LToMxN+B8qhCbGR
601 | KVcDE85ajKUaxoaryEuL4UVXIudPB5Ko2oy98xjDptXERuz3hsgAOTzlqqMk6yjdllzE90UM9Wp5azlB
602 | S1kwkeG+1CSv4mmBQPThfd6Ahqq8GYB4A11yBKmaMLQxoZyLDkGjDiZOFUhUuB+FsWsUQFiArzegtlzH
603 | pFjPpMPA2GA2jucx2KqWK7ZWLqO7dBGP9D5KWLbfto3eAKMhi3FHBeP9GYy9PMXos4OIrYvJrzSRbWjm
604 | wuV6EnVG4tLLiEzSExGf4w0oL05nZEDPaK+akceBuO9v4uPtFUrYo6npbzhdE/QPOQmNSiPouHYOUpaf
605 | gvgqA/dDf9wd63G1r2SgUlAqyyq/1anYUGfG2mdXwne7bOwJUc1AinOS+NxzBpd5HWLbUhyNPvRdF5S2
606 | v05/54tbqvzBifWNHUvPOwLC4/CXwrv2HsB3+w6EwosJOB5ESeElfGpayGD1AmwlArHSm+W2PR1clToo
607 | MrbT0mFTVtlbN6xFuJQar3wQz5Q9VksD+7XyPctrJdx4p5s605M5gKz8lJPSDwtGFbKboJ1blAN52vKb
608 | PdXm80/AfDokTVu+8DfPXv9XCcIPTvjvLQ8YoakAAAAASUVORK5CYII=
609 |
610 |
611 |
612 |
613 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
614 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
615 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
616 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
617 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
618 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
619 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
620 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
621 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
622 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
623 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
624 |
625 |
626 |
627 |
628 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
629 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
630 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
631 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
632 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
633 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
634 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
635 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
636 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
637 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
638 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
639 |
640 |
641 |
642 | 259, 17
643 |
644 |
645 | 17, 17
646 |
647 |
648 | 139, 17
649 |
650 |
651 | 379, 17
652 |
653 |
654 |
655 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
656 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
657 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
658 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
659 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
660 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
661 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
662 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
663 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
664 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
665 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
666 |
667 |
668 |
669 |
670 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
671 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
672 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
673 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
674 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
675 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
676 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
677 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
678 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
679 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
680 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
681 |
682 |
683 |
684 | 500, 17
685 |
686 |
687 |
688 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
689 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
690 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
691 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
692 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
693 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
694 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
695 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
696 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
697 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
698 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
699 |
700 |
701 |
702 |
703 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
704 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
705 | YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
706 | 0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
707 | bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
708 | VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
709 | c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
710 | Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
711 | mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
712 | kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
713 | TgDQASA1MVpwzwAAAABJRU5ErkJggg==
714 |
715 |
716 |
717 |
718 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
719 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIpSURBVDhPtZL/T1JRGMb5p1itrVZbbRpqZbawnBENV1I0
720 | jGlByTSyJTXJwq2oKZQb1KAv6JCYWSxvBrkkZUq4CeQEiRABFeLL072Xa0zRra31bO8v57zP5znnPYf1
721 | X+TxhWF6O7VtGYcnwbSWijKPOLzYrPSvLPwLS3huGUMlT7o9wGD9grVUBj+icdid03S9tDmgNxNwTgVQ
722 | J+rA8XNtWwM+uuZATMwxmQVRycuJFNyzIRitDlScugKzjSgFRGJJaIwEsrk8AsHIhnSL/Ssck37UNipQ
723 | I5DjtuYV7uksRYhr2kebhx2eP6nrycFIEh5fBA/1Nvru8q5+PDaOovK0rABwfwugWzcErfkzHhjsePL6
724 | E7q1VrTdNUDcrgGvSYlDZHN5XTNOnL8BVe8AJAoNDtZfLgDu9L1BPJmikzcrk81hlRwodZJwdBXziwnI
725 | OrVoaOkiT8C8hKLHBPO7CbywOaE1jeC+bhAd6meQdvZC1KoG/5IS3MZ2HObLUHZSggvkWq3wOvbWiAqA
726 | VpWeyStVfCUNf3AZ4zNhfHCFMEDMgye+hYr6FrDLzxQAUuVTpr0ocn74mchg5vsKRt1RcHp2Qv9+kZ78
727 | UcE17KkWFgHNN/uQzgBkGKLJPBZiecyGchjzrmFwPIF++xJUbDbUQzEacIArLpopSRSP4CUN1Obf1Abz
728 | uqob5KjiXwWH/GVl5HPt5zZh37GL2H1EiF1VZ7GDI6CNW5r/TSzWbwHYL0mKJ5czAAAAAElFTkSuQmCC
729 |
730 |
731 |
732 | 841, 17
733 |
734 |
--------------------------------------------------------------------------------
/FormDragger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Drawing;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Security;
8 | using System.Text;
9 | using System.Windows.Forms;
10 |
11 | namespace AhDung.WinForm
12 | {
13 | ///
14 | /// 窗体拖拽器
15 | /// - 使窗体客户区可拖动
16 | /// - 若多次调用Application.Run,建议在每次调用之前都启用
17 | ///
18 | [SuppressUnmanagedCodeSecurity]
19 | public static class FormDragger
20 | {
21 | static bool _enabled;
22 | static MouseLeftDownMessageFilter _filter;
23 |
24 | ///
25 | /// 拖拽发生时
26 | /// - 令Cancel = true可取消拖拽
27 | /// - 注意sender为null
28 | ///
29 | public static event EventHandler Dragging;
30 |
31 | private static void OnDragging(FormDraggingCancelEventArgs e) => Dragging?.Invoke(null, e);
32 |
33 | ///
34 | /// 拖拽器开关状态改变后
35 | ///
36 | /// - 注意sender为null
37 | public static event EventHandler EnabledChanged;
38 |
39 | private static void OnEnabledChanged(EventArgs e) => EnabledChanged?.Invoke(null, e);
40 |
41 | ///
42 | /// 获取或设置是否启用拖拽器
43 | ///
44 | public static bool Enabled
45 | {
46 | get => _enabled;
47 | set
48 | {
49 | //先移除再加入。这样做是允许重复Enable,
50 | //因为存在多次Application.Run的情况下,每次Run都有可能会启动新
51 | //线程上下文(ThreadContext),从而导致过滤器因未加入新context
52 | //而失效,所以需要在每次Run之前都启用
53 |
54 | Application.RemoveMessageFilter(_filter);
55 |
56 | if (value)
57 | {
58 | if (_filter == null)
59 | {
60 | _filter = new MouseLeftDownMessageFilter();
61 | }
62 | Application.AddMessageFilter(_filter);
63 | }
64 |
65 | if (_enabled != value)
66 | {
67 | _enabled = value;
68 | OnEnabledChanged(EventArgs.Empty);
69 | }
70 | }
71 | }
72 |
73 | /////
74 | ///// 检测本消息过滤器是否还在工作
75 | /////
76 | /////
77 | //private static bool FilterExists()
78 | //{
79 | // if (_filter == null)
80 | // {
81 | // return false;
82 | // }
83 |
84 | // var type = Assembly.GetAssembly(typeof(Application)).GetType("System.Windows.Forms.Application+ThreadContext");
85 | // var crrThreadContext = type.GetMethod("FromCurrent", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, null);
86 | // if (crrThreadContext != null)
87 | // {
88 | // var filterArr = type.GetField("messageFilters", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(crrThreadContext);
89 | // if (filterArr != null)
90 | // {
91 | // return ((ArrayList)filterArr).Contains(_filter);
92 | // }
93 | // }
94 |
95 | // return false;
96 | //}
97 |
98 | static List _excludeControls;
99 |
100 | ///
101 | /// 例外控件
102 | ///
103 | public static List ExcludeControls => _excludeControls ?? (_excludeControls = new List());
104 |
105 | ///
106 | /// 左键单击消息过滤器
107 | ///
108 | private class MouseLeftDownMessageFilter : IMessageFilter
109 | {
110 | public bool PreFilterMessage(ref Message m)
111 | {
112 | Point point;
113 | switch (m.Msg)
114 | {
115 | case 0x201://WM_LBUTTONDOWN
116 | //System.Diagnostics.Debug.WriteLine(m.HWnd.ToString("X8") + "\t" + m.WParam + "\t" + GetPoint(m.LParam));
117 |
118 | if ((int)m.WParam != 1) { break; }//仅处理单纯的左键单击
119 |
120 | point = GetPoint(m.LParam);
121 | var c = Control.FromHandle(m.HWnd);
122 |
123 | if (c != null)
124 | {
125 | if (CanDrag(c, point)
126 | || c is UserControl && CanDrag(c.GetChildAtPoint(point), point)) //支持自定义容器控件)
127 | {
128 | return DoDrag(c, point, true);
129 | }
130 | }
131 | else
132 | {
133 | var className = GetClassName(m.HWnd);
134 |
135 | //标头控件。如ListView的标题栏
136 | if (string.Equals("SysHeader32", className, StringComparison.OrdinalIgnoreCase))
137 | {
138 | var info = new HDHITTESTINFO { pt = (POINT)point };
139 | var hInfo = GCHandle.Alloc(info, GCHandleType.Pinned);
140 | SendMessage(m.HWnd, 0x1206/*HDM_HITTEST*/, IntPtr.Zero, hInfo.AddrOfPinnedObject());
141 | info = (HDHITTESTINFO)hInfo.Target;
142 | hInfo.Free();
143 |
144 | //当点到非列头(右侧)或列头不用来交互(如点击排序)时执行拖动
145 | if (info.flags == 1/*HHT_NOWHERE*/
146 | || info.flags == 2/*HHT_ONHEADER*/ && !HasStyle(m.HWnd, 2/*HDS_BUTTONS*/))
147 | {
148 | //标头控件并未封装到.net中,所以FromHandle会得到null,这里取标头控件所在的父控件,
149 | //通常就是ListView,所以其实point是相对于标头控件而不是ListView,
150 | //只不过因为标头控件往往是在LiveView的顶部,所以应该不会引起问题
151 | return DoDrag(Control.FromChildHandle(m.HWnd), point, true);
152 | }
153 | }
154 | }
155 | break;
156 |
157 | case 0xA1://WM_NCLBUTTONDOWN
158 | var ht = (int)m.WParam;
159 | if (ht == 5/*HTMENU*/)//点到MainMenu时
160 | {
161 | //判断是否点到菜单项。若不是或菜单项不可用则拖拽
162 | //点击菜单时m.HWnd为窗体句柄而非菜单句柄
163 | point = GetPoint(m.LParam);
164 | var menu = GetMenu(m.HWnd);
165 | var item = MenuItemFromPoint(m.HWnd, menu, (POINT)point);
166 | if (item == -1
167 | || (GetMenuState(menu, item, 0x400/*MF_BYPOSITION*/) & 2/*MF_DISABLED*/) == 2)
168 | {
169 | return DoDrag(Control.FromHandle(m.HWnd), point, false);
170 | }
171 | }
172 | else if (ht == 4/*HTSIZE*/ || ht == 18/*HTBORDER*/)//点到两个滚动条右下空白、控件边框时
173 | {
174 | return DoDrag(Control.FromHandle(m.HWnd), GetPoint(m.LParam), false);
175 | }
176 | else if (ht == 6/*HTHSCROLL*/ || ht == 7/*HTVSCROLL*/)//点到滚动条时
177 | {
178 | //获取滚动条状态,若处于无效则拖拽
179 | //OBJID_HSCROLL=0xFFFFFFFA
180 | //OBJID_VSCROLL=0xFFFFFFFB
181 | var idObject = unchecked((int)(ht + 0xFFFFFFF4));
182 | SCROLLBARINFO sbi = new SCROLLBARINFO { cbSize = SizeOfSCROLLBARINFO };
183 | if (GetScrollBarInfo(m.HWnd, idObject, ref sbi)
184 | && sbi.scrollBarInfo == 1/*STATE_SYSTEM_UNAVAILABLE*/)
185 | {
186 | return DoDrag(Control.FromHandle(m.HWnd), GetPoint(m.LParam), false);
187 | }
188 | }
189 | break;
190 | }
191 | return false;
192 | }
193 | }
194 |
195 |
196 | ///
197 | /// 执行拖拽
198 | ///
199 | /// 指示是否拦截消息
200 | private static bool DoDrag(Control c, Point point, bool isClientArea)
201 | {
202 | try
203 | {
204 | Form form;
205 | if (c == null || (form = c.FindForm()) == null)
206 | {
207 | return false;
208 | }
209 | var e = new FormDraggingCancelEventArgs(c, point, isClientArea);
210 | OnDragging(e);
211 | if (e.Cancel)
212 | {
213 | return false;
214 | }
215 | //当作为MDI子窗体且最大化时,拖MDI主窗体
216 | if (form.WindowState == FormWindowState.Maximized || !form.TopLevel && form.Dock == DockStyle.Fill)
217 | {
218 | form = form.MdiParent ?? form.ParentForm ?? form;
219 | }
220 | SendMessage(form.Handle, 0xA1/*WM_NCLBUTTONDOWN*/, (IntPtr)2, IntPtr.Zero);
221 | return true;
222 | }
223 | catch
224 | {
225 | return false;
226 | }
227 | }
228 |
229 | static PropertyInfo _linkState;
230 |
231 | ///
232 | /// 判断是否处于可拖拽情形
233 | ///
234 | private static bool CanDrag(Control c, Point pt)
235 | {
236 | if (c == null || _excludeControls != null && _excludeControls.Contains(c))
237 | {
238 | return false;
239 | }
240 |
241 | if (c is Form
242 | || c is Label && !(c is LinkLabel)
243 | || c is Panel
244 | || c is GroupBox
245 | || c is PictureBox
246 | || c is ProgressBar
247 | || c is StatusBar
248 | || c is MdiClient
249 | )
250 | {
251 | return true;
252 | }
253 |
254 | if (c is LinkLabel linkLabel)
255 | {
256 | //若点到链接部分且链接可用则不拦截
257 | //取State优于调用PointInLink
258 | foreach (LinkLabel.Link link in linkLabel.Links)
259 | {
260 | if (_linkState == null)
261 | {
262 | _linkState = typeof(LinkLabel.Link).GetProperty("State", BindingFlags.Instance | BindingFlags.NonPublic);
263 | }
264 | var state = (LinkState)_linkState.GetValue(link, null);
265 | if ((state & LinkState.Hover) == LinkState.Hover && link.Enabled)
266 | {
267 | return false;
268 | }
269 | }
270 | return true;
271 | }
272 |
273 | if (c is ToolStrip strip)
274 | {
275 | var item = strip.GetItemAt(pt);
276 | if (item == null
277 | || !item.Enabled
278 | || item is ToolStripSeparator
279 | || (item is ToolStripLabel label && !label.IsLink))
280 | {
281 | return true;
282 | }
283 | return false;
284 | }
285 |
286 | if (c is ToolBar bar)
287 | {
288 | //判断鼠标是否点击在按钮上
289 | var ptPoint = GCHandle.Alloc((POINT)pt, GCHandleType.Pinned);
290 | var index = (int)SendMessage(bar.Handle, (0x400 + 69)/*TB_HITTEST */, IntPtr.Zero, ptPoint.AddrOfPinnedObject());
291 | ptPoint.Free();
292 |
293 | //若点击在按钮上且当按钮可用时则不拦截
294 | if (index >= 0 && bar.Buttons[index].Enabled)
295 | {
296 | return false;
297 | }
298 | return true;
299 | }
300 |
301 | if (c is DataGridView dgv)
302 | {
303 | return dgv.HitTest(pt.X, pt.Y).Type == DataGridViewHitTestType.None;
304 | }
305 |
306 | if (c is DataGrid grid)
307 | {
308 | return grid.HitTest(pt).Type == DataGrid.HitTestType.None;
309 | }
310 |
311 | if (c.Parent is UpDownBase)
312 | {
313 | return false;
314 | }
315 |
316 | return !c.CanSelect; // || HasStyle(c.Handle, 0x10000/*WS_EX_CONTROLPARENT*/, true);加上这个有问题,对有Spliter的控件如PropertyGrid不能区分Spliter
317 | }
318 |
319 | #region Win32 API
320 |
321 | // ReSharper disable MemberCanBePrivate.Local
322 | // ReSharper disable FieldCanBeMadeReadOnly.Local
323 | static Point GetPoint(IntPtr lParam) => new Point(unchecked((int)(long)lParam));
324 |
325 | [DllImport("user32.dll", SetLastError = true)]
326 | static extern bool GetScrollBarInfo(IntPtr hwnd, int idObject, ref SCROLLBARINFO psbi);
327 |
328 | static readonly int SizeOfSCROLLBARINFO = Marshal.SizeOf(typeof(SCROLLBARINFO));
329 |
330 | [StructLayout(LayoutKind.Sequential)]
331 | private struct SCROLLBARINFO
332 | {
333 | public int cbSize;
334 | public int rcLeft;
335 | public int rcTop;
336 | public int rcRight;
337 | public int rcBottom;
338 | public int dxyLineButton;
339 | public int xyThumbTop;
340 | public int xyThumbBottom;
341 | public int reserved;
342 | public int scrollBarInfo;
343 | public int upArrowInfo;
344 | public int largeDecrementInfo;
345 | public int thumbnfo;
346 | public int largeIncrementInfo;
347 | public int downArrowInfo;
348 | }
349 |
350 | [DllImport("user32.dll")]
351 | static extern int GetMenuState(IntPtr hMenu, int uId, int uFlags);
352 |
353 | [DllImport("user32.dll")]
354 | static extern IntPtr GetMenu(IntPtr hWnd);
355 |
356 | [DllImport("user32.dll")]
357 | static extern int MenuItemFromPoint(IntPtr hWnd, IntPtr hMenu, POINT ptScreen);
358 |
359 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
360 | static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
361 |
362 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
363 | static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
364 |
365 | static string GetClassName(IntPtr hWnd)
366 | {
367 | const int MaxClassNameLength = 256;
368 | var sb = new StringBuilder(MaxClassNameLength);
369 | if (GetClassName(hWnd, sb, MaxClassNameLength) == 0)
370 | {
371 | throw new Win32Exception();
372 | }
373 | return sb.ToString();
374 | }
375 |
376 | [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindowLong")]
377 | static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
378 |
379 | [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindowLongPtr")]
380 | static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
381 |
382 | static int GetWindowStyle(IntPtr hWnd, bool isExStyle = false)
383 | {
384 | var nIndex = isExStyle ? -20/*GWL_EXSTYLE*/: -16/*GWL_STYLE*/;
385 | return unchecked((int)(long)(IntPtr.Size == 4 ? GetWindowLong32(hWnd, nIndex) : GetWindowLongPtr64(hWnd, nIndex)));
386 | }
387 |
388 | static bool HasStyle(IntPtr hWnd, int style, bool isExStyle = false) =>
389 | (GetWindowStyle(hWnd, isExStyle) & style) == style;
390 |
391 | [StructLayout(LayoutKind.Sequential)]
392 | private struct POINT
393 | {
394 | public int X;
395 | public int Y;
396 |
397 | public static explicit operator POINT(Point pt) => new POINT { X = pt.X, Y = pt.Y };
398 |
399 | public static explicit operator Point(POINT pt) => new Point(pt.X, pt.Y);
400 |
401 | public override string ToString() => $"{X}, {Y}";
402 | }
403 |
404 | [StructLayout(LayoutKind.Sequential)]
405 | private struct HDHITTESTINFO
406 | {
407 | public POINT pt;
408 | public uint flags;
409 | public int iItem;
410 | }
411 |
412 | // ReSharper restore FieldCanBeMadeReadOnly.Local
413 | // ReSharper restore MemberCanBePrivate.Local
414 |
415 | #endregion
416 | }
417 |
418 | ///
419 | ///
420 | /// 窗体拖拽取消事件参数
421 | ///
422 | public class FormDraggingCancelEventArgs : CancelEventArgs
423 | {
424 | ///
425 | /// 获取点击控件
426 | ///
427 | public Control Control { get; }
428 |
429 | ///
430 | /// 获取鼠标位置
431 | /// - 取自点击消息产生时的lParam
432 | /// - 当IsClientArea = true时,相对Control的客户区坐标,否则相对屏幕坐标
433 | ///
434 | public Point MousePosition { get; }
435 |
436 | ///
437 | /// 是否控件客户区
438 | ///
439 | public bool IsClientArea { get; }
440 |
441 | public FormDraggingCancelEventArgs(Control c, Point point, bool isClientArea)
442 | {
443 | Control = c;
444 | MousePosition = point;
445 | IsClientArea = isClientArea;
446 | }
447 | }
448 | }
449 |
--------------------------------------------------------------------------------
/FormDraggerDemo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}
9 | WinExe
10 | Properties
11 | AhDung
12 | FormDraggerDemo
13 | v2.0
14 | 512
15 |
16 |
17 | x86
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | x86
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 | true
37 | bin\Debug\
38 | DEBUG;TRACE
39 | full
40 | AnyCPU
41 | bin\Debug\FormDraggerDemo.exe.CodeAnalysisLog.xml
42 | true
43 | GlobalSuppressions.cs
44 | prompt
45 | MinimumRecommendedRules.ruleset
46 | ;D:\Microsoft Visual Studio\Team Tools\Static Analysis Tools\\Rule Sets
47 | ;D:\Microsoft Visual Studio\Team Tools\Static Analysis Tools\FxCop\\Rules
48 |
49 |
50 | bin\Release\
51 | TRACE
52 | true
53 | pdbonly
54 | AnyCPU
55 | bin\Release\FormDraggerDemo.exe.CodeAnalysisLog.xml
56 | true
57 | GlobalSuppressions.cs
58 | prompt
59 | MinimumRecommendedRules.ruleset
60 | ;D:\Microsoft Visual Studio\Team Tools\Static Analysis Tools\\Rule Sets
61 | true
62 | ;D:\Microsoft Visual Studio\Team Tools\Static Analysis Tools\FxCop\\Rules
63 | true
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | UserControl
76 |
77 |
78 | UserControl
79 |
80 |
81 |
82 |
83 | UserControl
84 |
85 |
86 |
87 | Form
88 |
89 |
90 | FmMDI.cs
91 |
92 |
93 | Form
94 |
95 |
96 | FmTabMDI.cs
97 |
98 |
99 | Form
100 |
101 |
102 | FmTabSub.cs
103 |
104 |
105 | Form
106 |
107 |
108 | FmTestDrag.cs
109 |
110 |
111 |
112 |
113 |
114 | FmMDI.cs
115 |
116 |
117 | FmTabMDI.cs
118 |
119 |
120 | FmTabSub.cs
121 |
122 |
123 | FmTestDrag.cs
124 |
125 |
126 |
127 |
134 |
--------------------------------------------------------------------------------
/FormDraggerDemo.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormDraggerDemo", "FormDraggerDemo.csproj", "{70F4498F-A6E3-483B-A75C-BE528DAEF5F5}"
5 | EndProject
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9FCF9ABC-B721-4BCF-BFC4-5342626C2B4C}"
7 | ProjectSection(SolutionItems) = preProject
8 | pic.png = pic.png
9 | README.md = README.md
10 | EndProjectSection
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Debug|x86 = Debug|x86
16 | Release|Any CPU = Release|Any CPU
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}.Debug|x86.ActiveCfg = Debug|x86
23 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}.Debug|x86.Build.0 = Debug|x86
24 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}.Release|x86.ActiveCfg = Release|x86
27 | {70F4498F-A6E3-483B-A75C-BE528DAEF5F5}.Release|x86.Build.0 = Release|x86
28 | EndGlobalSection
29 | GlobalSection(SolutionProperties) = preSolution
30 | HideSolutionNode = FALSE
31 | EndGlobalSection
32 | EndGlobal
33 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using AhDung.WinForm;
4 |
5 | namespace AhDung
6 | {
7 | static class Program
8 | {
9 | ///
10 | /// 应用程序的主入口点。
11 | ///
12 | [STAThread]
13 | static void Main()
14 | {
15 | Application.EnableVisualStyles();
16 | Application.SetCompatibleTextRenderingDefault(false);
17 |
18 | FormDragger.Enabled = true;//启用拖拽器
19 | //Application.Run(new FmMDI());
20 | Application.Run(new FmTabMDI());
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的常规信息通过以下
6 | // 特性集控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("FormDraggerDemo")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("AhDung")]
12 | [assembly: AssemblyProduct("FormDraggerDemo")]
13 | [assembly: AssemblyCopyright("Copyright © AhDung 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 使此程序集中的类型
18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
19 | // 则将该类型上的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("473aac92-9341-4e61-9dcd-4d7d2d55a66f")]
24 |
25 | // 程序集的版本信息由下面四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 内部版本号
30 | // 修订号
31 | //
32 | // 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FormDragger
2 | 一个可在窗体内随意拖动窗体的方案。可拖动区域包括不限于Form/Panel/GroupBox/TabControl等空白区域、Label、无效控件、无效菜单/工具栏项、状态栏等等任何你觉得可以拖动的地方。
3 | A solution for easily dragging window within client area nor children control. The range of dragging includes but not limited to blank areas, like Form/Panel/GroupBox/TabControl, also includes anywhere you can drag such as Label, disabled Controls/MenuItems/ToolStripItems, menu/toolbar and status bar. etc.
4 |
5 | 
--------------------------------------------------------------------------------
/pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ahdung/FormDraggerDemo/774675932a8f6bfdbb2d2b7ce365d245336a4549/pic.png
--------------------------------------------------------------------------------