1.主窗体下部添加一个Panel乘放ToolStrip控件以实现ToolStrip在窗体下部定位。
2.当ToolStrip控件中子控件超出屏幕时,拖动控件可以实现滑动效果。拖动到控件边缘距窗体边缘1/3宽度时(可设),自动回弹。拖动控件边缘在屏幕内时释放鼠标,控件自动回弹,边缘吸附窗体边缘。
3.当ToolStrip控件中子控件数目较少可以在屏幕上完全显示时,拖动效果不可见。
4.增加 添加、删除 按钮,点击时可增删一个ToolStripButton,方便拖动效果可见(ToolStrip控件中子控件超出屏幕)与不可见(ToolStrip控件中子控件可以在屏幕上完全显示时)的演示。
5.拖动鼠标离开ToolStrip控件再释放,不会触发MouseUp事件,引起控件边缘在屏幕中时释放鼠标自动吸附效果失效。待解决。
源码:
参考文章:WinForm 实现鼠标拖动控件跟随效果(图文) @SkySoot
1 /*==================================================================================================
2 ** 类 名 称:FrmDragTest
3 ** 创 建 人:liu
4 ** 当前版本:V1.0.0
5 ** CLR 版本:4.0.30319.42000
6 ** 创建时间:2017/5/6 19:53:44
7
8 ** 修改人 修改时间 修改后版本 修改内容
9
10
11 ** 功能描述:ToolStrip控件左右拖拽移动效果实现
12
13 * 主窗体下部添加一个Panel乘放ToolStrip控件以实现ToolStrip在窗体下部定位。
14 * 当ToolStrip控件中子控件超出屏幕时,拖动控件可以实现滑动效果。拖动到控件边缘距窗体边缘1/3宽度时(可设),
15 自动回弹。拖动控件边缘在屏幕内时释放鼠标,控件自动回弹,边缘吸附窗体边缘。
16 * 当ToolStrip控件中子控件数目较少可以在屏幕上完全显示时,拖动效果不可见。
17 * 增加 添加、删除 按钮,点击时可增删一个ToolStripButton,方便拖动效果可见(ToolStrip控件中子控件超出屏幕)
18 与不可见(ToolStrip控件中子控件可以在屏幕上完全显示时)的演示。
19 * 拖动鼠标离开ToolStrip控件再释放,不会触发MouseUp事件,引起控件边缘在屏幕中时释放鼠标自动吸附效果失效。待解决。
20
21 ==================================================================================================
22 Copyright @2017. liu. All rights reserved.
23 ==================================================================================================*/
24 using System;
25 using System.Drawing;
26 using System.Windows.Forms;
27
28 namespace DragDemo
29 {
30 public partial class FrmDragTest : Form
31 {
32 #region 字段
33
34 /// <summary>
35 /// 被拖动的ToolStrip控件
36 /// </summary>
37 private ToolStrip _toolStrip;
38
39 /// <summary>
40 /// 当前ToolStripButton数目
41 /// </summary>
42 private int _itemCount;
43
44 #endregion
45
46 #region 构造
47
48 public FrmDragTest()
49 {
50 InitializeComponent();
51 }
52
53 #endregion
54
55 #region 初始化
56
57 private void FrmTest_Load(object sender, EventArgs e)
58 {
59 this.Size = new Size(530, 350);
60 // 窗体大小调整时,检查边缘是否留白
61 this.Resize += (sender1, e1) => { CheckBlank(); };
62 // 添加一个Panel乘放ToolStrip控件以实现ToolStrip在窗体下部定位
63 var pnlmain = new Panel { Dock = DockStyle.Bottom, Height = 80 };
64
65 _toolStrip = new ToolStrip
66 {
67 // 注意Dock属性必须为None
68 Dock = DockStyle.None,
69 AutoSize = true,
70 //BackgroundImageLayout = ImageLayout.None,
71 GripStyle = ToolStripGripStyle.Hidden,
72 // 子项除超出屏幕显示时不溢出显示
73 LayoutStyle = ToolStripLayoutStyle.Flow,
74 Height = 78,
75 Location = new Point(0, 1),
76 ImageScalingSize = new Size(102, 78)
77 };
78
79 //默认添加些Button以显示效果
80 for (int j = 0; j < 10; j++)
81 {
82 AddOneButton();
83 }
84
85 pnlmain.Controls.Add(_toolStrip);
86 this.Controls.Add(pnlmain);
87
88 // 添加键
89 var btnAdd = new Button { Size = new Size(80, 40), Text = @"Add", Location = new Point(150, 100) };
90 btnAdd.Click += btnAdd_Click;
91 this.Controls.Add(btnAdd);
92 // 移除键
93 var btnRemove = new Button { Size = new Size(80, 40), Text = @"Remove", Location = new Point(300, 100) };
94 btnRemove.Click += btnRemove_Click;
95 this.Controls.Add(btnRemove);
96 }
97
98 #endregion
99
100 #region 自动添加移除
101
102 private void btnAdd_Click(object sender, EventArgs e)
103 {
104 AddOneButton();
105 }
106
107 private void btnRemove_Click(object sender, EventArgs e)
108 {
109 RemoveOneButton();
110 }
111
112 /// <summary>
113 /// 向_toolStrip添加一个Button
114 /// </summary>
115 private void AddOneButton()
116 {
117 var tsbtn = new ToolStripButton
118 {
119 AutoSize = false,
120 DisplayStyle = ToolStripItemDisplayStyle.Text,
121 Text = (++_itemCount).ToString(),
122 Size = new Size(100, 78),
123 BackColor = Color.YellowGreen,
124 Margin = new Padding(0, 0, 2, 0)
125 };
126 tsbtn.MouseDown += Controls_MouseDown;
127 tsbtn.MouseMove += Controls_MouseMove;
128 tsbtn.MouseUp += Controls_MouseUp;
129 _toolStrip.Items.Add(tsbtn);
130 }
131
132 /// <summary>
133 /// 移除队尾的Button
134 /// </summary>
135 private void RemoveOneButton()
136 {
137 _toolStrip.Items.RemoveAt(--_itemCount);
138 }
139
140 #endregion
141
142 #region 拖动效果实现
143
144 /*
145 * 理解了下面的几个概念,就能完全明白相对坐标的变化.
146 * Cursor.Position 获取的是相对于用户屏幕的光标坐标
147 * PointToClient() 方法可将屏幕坐标 Cursor.Position 换算成工作区的坐标
148 */
149
150 /// <summary>
151 /// 保存拖动前鼠标X坐标
152 /// </summary>
153 private int _curX;
154 /// <summary>
155 /// 保存拖动前_ToolStrip控件X坐标
156 /// </summary>
157 private int _oldToolStripX;
158
159 /// <summary>
160 /// 按键按下,记录当前光标X坐标与拖动前_ToolStrip控件X坐标
161 /// </summary>
162 /// <param name="sender"></param>
163 /// <param name="e"></param>
164 private void Controls_MouseDown(object sender, MouseEventArgs e)
165 {
166 if (e.Button == MouseButtons.Left)
167 {
168 // 获取当前光标X坐标
169 _curX = Cursor.Position.X;
170 // 获取拖动前_ToolStrip控件X坐标
171 _oldToolStripX = _toolStrip.Location.X;
172 }
173 }
174
175 /// <summary>
176 /// 鼠标移动,拖动_ToolStrip控件
177 /// </summary>
178 /// <param name="sender"></param>
179 /// <param name="e"></param>
180 private void Controls_MouseMove(object sender, MouseEventArgs e)
181 {
182 if (e.Button == MouseButtons.Left)
183 {
184 // x最小值,对应右侧拖动到边界时x坐标值
185 int minX = this.Width - _toolStrip.Width;
186 // 图标当前可以全部显示,拖动效果不可见
187 if (minX > 0) return;
188
189 // _ToolStrip控件X轴新坐标
190 // 当前鼠标X坐标-拖动前鼠标X坐标=X轴鼠标偏移量,加上拖动前控件X坐标,即为新坐标
191 int newToolStripX = Cursor.Position.X - _curX + _oldToolStripX;
192
193 // 右侧空白超过屏幕宽度1/3,自动回弹
194 if (newToolStripX < minX - this.Width / 3)
195 {
196 // 左拖动过度,修正
197 newToolStripX = minX;
198 }
199 // 左侧空白超过屏幕宽度1/3,自动回弹
200 else if (newToolStripX > this.Width / 3)
201 {
202 // 右拖动过多,修正
203 newToolStripX = 0;
204 }
205
206 _toolStrip.Location = new Point(newToolStripX, 0);
207 }
208 }
209
210 /// <summary>
211 /// 鼠标松开,检查两侧是否留白
212 /// </summary>
213 /// <param name="sender"></param>
214 /// <param name="e"></param>
215 private void Controls_MouseUp(object sender, MouseEventArgs e)
216 {
217 if (e.Button == MouseButtons.Left)
218 {
219 CheckBlank();
220 }
221 }
222
223 /// <summary>
224 /// 检查两侧是否留白
225 /// </summary>
226 private void CheckBlank()
227 {
228
229 // x最小值,对应右侧拖动到边界时x坐标值
230 int minX = this.Width - _toolStrip.Width;
231 // 图标全部显示,拖动效果不可见
232 if (minX > 0) return;
233
234 // 左边界限制,左侧不留空
235 if (_toolStrip.Location.X > 0)
236 {
237 _toolStrip.Location = new Point(0, 0);
238 }
239 // 右边界限制,右侧不留空
240 else if (_toolStrip.Location.X < minX)
241 {
242 _toolStrip.Location = new Point(minX, 0);
243 }
244
245 }
246
247
248
249 #endregion
250 }
251 }