ToolStrip控件左右拖拽移动效果实现
1.主窗体下部添加一个Panel乘放ToolStrip控件以实现ToolStrip在窗体下部定位。
2.当ToolStrip控件中子控件超出屏幕时,拖动控件可以实现滑动效果。拖动到控件边缘距窗体边缘1/3宽度时(可设),自动回弹。拖动控件边缘在屏幕内时释放鼠标,控件自动回弹,边缘吸附窗体边缘。
3.当ToolStrip控件中子控件数目较少可以在屏幕上完全显示时,拖动效果不可见。
4.增加 添加、删除 按钮,点击时可增删一个ToolStripButton,方便拖动效果可见(ToolStrip控件中子控件超出屏幕)与不可见(ToolStrip控件中子控件可以在屏幕上完全显示时)的演示。
5.拖动鼠标离开ToolStrip控件再释放,不会触发MouseUp事件,引起控件边缘在屏幕中时释放鼠标自动吸附效果失效。待解决。
源码:https://files.cnblogs.com/files/tobeforever/DragDemo.rar
参考文章:WinForm 实现鼠标拖动控件跟随效果(图文) @SkySoot
http://www.cnblogs.com/SkySoot/archive/2011/12/20/2294733.html
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 }