扩展SplitContainer控件
Posted JustYong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扩展SplitContainer控件相关的知识,希望对你有一定的参考价值。
效果图:
自定义控件实现代码:
1 using System; 2 using System.ComponentModel; 3 using System.Drawing; 4 using System.Windows.Forms; 5 6 namespace WindowsFormsApplication1 7 { 8 [ToolboxBitmap(typeof(SplitContainer))] 9 public partial class SplitContainerEx : SplitContainer 10 { 11 #region Field 12 13 /// <summary> 14 /// 控制器绘制区域 15 /// </summary> 16 private Rectangle ControlRect 17 { 18 get 19 { 20 var rect = new Rectangle(); 21 22 if (Orientation == Orientation.Horizontal) 23 { 24 rect.X = Width <= 80 ? 0 : Width / 2 - 40; 25 rect.Y = SplitterDistance; 26 rect.Width = 80; 27 rect.Height = 9; 28 } 29 else 30 { 31 rect.X = SplitterDistance; 32 rect.Y = Height <= 80 ? 0 : Height / 2 - 40; 33 rect.Width = 9; 34 rect.Height = 80; 35 } 36 return rect; 37 } 38 } 39 40 /// <summary> 41 /// 鼠标状态(进入或离开) 42 /// </summary> 43 private MouseState _mouseState = MouseState.Normal; 44 45 /// <summary> 46 /// 定义折叠或展开的是哪一个面板 47 /// </summary> 48 private SplitterPanelEnum _collpaseOrExpandPanel; 49 50 /// <summary> 51 /// Splitter是否固定 52 /// </summary> 53 private bool _isSplitterFixed = true; 54 55 /// <summary> 56 /// 当前是否为折叠状态 57 /// </summary> 58 private bool _collpased; 59 60 #endregion 61 62 #region Property 63 64 /// <summary> 65 /// 进行折叠或展开的SplitterPanel,设置为属性,所以可以在页面进行重新设置 66 /// </summary> 67 [DefaultValue(SplitterPanelEnum.Panel1)] 68 public SplitterPanelEnum CollpaseOrExpandPanel 69 { 70 get 71 { 72 return _collpaseOrExpandPanel; 73 } 74 set 75 { 76 if (value != _collpaseOrExpandPanel) 77 { 78 _collpaseOrExpandPanel = value; 79 Invalidate(ControlRect); 80 } 81 } 82 } 83 84 /// <summary> 85 /// 设定Panel1是否为默认折叠 86 /// </summary> 87 private bool _panel1Collapsed; 88 [DefaultValue(false)] 89 public new bool Panel1Collapsed 90 { 91 get 92 { 93 return _panel1Collapsed; 94 } 95 set 96 { 97 //只有当CollpaseOrExpandPanel = Panel时,Panel1Collapsed的设置才会有效 98 if (CollpaseOrExpandPanel == SplitterPanelEnum.Panel1 && value != _panel1Collapsed) 99 { 100 _panel1Collapsed = value; 101 //设置_collpased值为value的相反值,再调用CollpaseOrExpand()进行折叠或展开. 102 _collpased = !value; 103 104 CollpaseOrExpand(); 105 } 106 } 107 } 108 109 /// <summary> 110 /// 设置Panel2是否为默认折叠 111 /// </summary> 112 private bool _panel2Colapsed; 113 [DefaultValue(false)] 114 public new bool Panel2Collapsed 115 { 116 get 117 { 118 return _panel2Colapsed; 119 } 120 set 121 { 122 //只有当CollpaseOrExpandPanel = Pane2时,Panel1Collapsed的设置才会有效 123 if (CollpaseOrExpandPanel == SplitterPanelEnum.Panel2 && value != _panel2Colapsed) 124 { 125 _panel2Colapsed = value; 126 //设置_collpased值为value的相反值,再调用CollpaseOrExpand()进行折叠或展开 127 _collpased = !value; 128 129 CollpaseOrExpand(); 130 } 131 } 132 } 133 134 /// <summary> 135 /// 用于固定保存显式设定的SplitterDistance,因为基类的SplitterDistance属性会变动 136 /// </summary> 137 public int DefaultSplitterDistance 138 { 139 get; 140 set; 141 } 142 143 #endregion 144 145 #region Ctor 146 147 public SplitContainerEx() 148 { 149 SetStyle( 150 ControlStyles.UserPaint | 151 ControlStyles.AllPaintingInWmPaint | 152 ControlStyles.OptimizedDoubleBuffer, true); 153 154 Panel1MinSize = 0; 155 Panel2MinSize = 0; 156 } 157 158 #endregion 159 160 #region Override 161 162 protected override void OnPaint(PaintEventArgs e) 163 { 164 base.OnPaint(e); 165 166 Color color = _mouseState == MouseState.Normal ? SystemColors.ButtonShadow : SystemColors.ControlDarkDark; 167 168 //需要绘制的图片 169 Bitmap bmp = CreateControlImage(color); 170 171 //对图片进行旋转 172 RotateFlip(bmp); 173 174 //清除绘制区域 175 e.Graphics.SetClip(SplitterRectangle); 176 e.Graphics.Clear(BackColor); 177 //绘制 178 e.Graphics.DrawImage(bmp, ControlRect); 179 } 180 181 protected override void OnMouseMove(MouseEventArgs e) 182 { 183 //鼠标在控制按钮区域 184 if (SplitterRectangle.Contains(e.Location)) 185 { 186 if (ControlRect.Contains(e.Location)) 187 { 188 //如果拆分器可移动,则鼠标在控制按钮范围内时临时关闭拆分器 189 if (!IsSplitterFixed) 190 { 191 IsSplitterFixed = true; 192 193 _isSplitterFixed = false; 194 } 195 196 Cursor = Cursors.Hand; 197 _mouseState = MouseState.Hover; 198 Invalidate(ControlRect); 199 } 200 else 201 { 202 //如果拆分器为临时关闭,则开启拆分器 203 if (!_isSplitterFixed) 204 { 205 IsSplitterFixed = false; 206 Cursor = Orientation == Orientation.Horizontal ? Cursors.HSplit : Cursors.VSplit; 207 } 208 else 209 { 210 Cursor = Cursors.Default; 211 } 212 _mouseState = MouseState.Normal; 213 Invalidate(ControlRect); 214 } 215 } 216 base.OnMouseMove(e); 217 } 218 219 protected override void OnMouseLeave(EventArgs e) 220 { 221 Cursor = Cursors.Default; 222 223 _mouseState = MouseState.Normal; 224 225 Invalidate(ControlRect); 226 227 base.OnMouseLeave(e); 228 } 229 230 protected override void OnMouseClick(MouseEventArgs e) 231 { 232 if (ControlRect.Contains(e.Location)) 233 { 234 CollpaseOrExpand(); 235 } 236 237 base.OnMouseClick(e); 238 } 239 240 #endregion 241 242 #region Method 243 244 /// <summary> 245 /// 折叠或展开 246 /// 1.当当前状态为折叠状态时,则进行展开操作 247 /// 2.当当前状态为展开状态时,则进行折叠操作 248 /// </summary> 249 private void CollpaseOrExpand() 250 { 251 //当前为缩小状态,进行Expand操作 252 if (_collpased) 253 { 254 //展开 255 SplitterDistance = DefaultSplitterDistance; 256 } 257 //当前为伸展状态,进行Collpase操作 258 else 259 { 260 //折叠 261 if (_collpaseOrExpandPanel == SplitterPanelEnum.Panel1) 262 { 263 SplitterDistance = 0; 264 } 265 else 266 { 267 if (Orientation == Orientation.Horizontal) 268 { 269 SplitterDistance = Height - 9; 270 } 271 else 272 { 273 SplitterDistance = Width - 9; 274 } 275 } 276 } 277 278 _collpased = !_collpased; 279 280 Invalidate(ControlRect); //局部刷新绘制 281 } 282 283 /// <summary> 284 /// 需要绘制的用于折叠窗口的按钮样式 285 /// </summary> 286 /// <param name="color"></param> 287 /// <returns></returns> 288 private Bitmap CreateControlImage(Color color) 289 { 290 var bmp = new Bitmap(80, 9); 291 for (int x = 5; x <= 30; x += 5) 292 { 293 for (int y = 1; y <= 7; y += 3) 294 { 295 bmp.SetPixel(x, y, color); 296 } 297 } 298 for (int x = 50; x <= 75; x += 5) 299 { 300 for (int y = 1; y <= 7; y += 3) 301 { 302 bmp.SetPixel(x, y, color); 303 } 304 } 305 306 int k = 0; 307 for (int y = 7; y >= 1; y--) 308 { 309 for (int x = 35 + k; x <= 45 - k; x++) 310 { 311 bmp.SetPixel(x, y, color); 312 } 313 k++; 314 } 315 316 return bmp; 317 } 318 319 private void RotateFlip(Bitmap bmp) 320 { 321 if (Orientation == Orientation.Horizontal) 322 { 323 if (_collpaseOrExpandPanel == SplitterPanelEnum.Panel1 && !_collpased || 324 _collpaseOrExpandPanel == SplitterPanelEnum.Panel2 && _collpased) 325 { 326 bmp.RotateFlip(RotateFlipType.RotateNoneFlipX); 327 } 328 else 329 { 330 bmp.RotateFlip(RotateFlipType.Rotate180FlipX); 331 } 332 } 333 else 334 { 335 if (_collpaseOrExpandPanel == SplitterPanelEnum.Panel1 && !_collpased || 336 _collpaseOrExpandPanel == SplitterPanelEnum.Panel2 && _collpased) 337 { 338 bmp.RotateFlip(RotateFlipType.Rotate90FlipX); 339 } 340 else 341 { 342 bmp.RotateFlip(RotateFlipType.Rotate270FlipX); 343 } 344 } 345 } 346 347 #endregion 348 349 #region Enums 350 351 enum MouseState 352 { 353 /// <summary> 354 /// 正常 355 /// </summary> 356 Normal, 357 /// <summary> 358 /// 鼠标移入 359 /// </summary> 360 Hover 361 } 362 363 public enum SplitterPanelEnum 364 { 365 Panel1, 366 Panel2 367 } 368 369 #endregion 370 } 371 }
以上是关于扩展SplitContainer控件的主要内容,如果未能解决你的问题,请参考以下文章
C# WinForm的SplitContainer控件固定Panel大小
c#中关于splitContainer控件的用法:如何做到不清除控件就能在panel2中打开一个窗体呢?
Winforms 控件结合了 SplitContainer 和 TableLayoutPanel 的优点