扩展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中打开一个窗体呢?

C# splitContainer1 调整子控件大小

Winforms 控件结合了 SplitContainer 和 TableLayoutPanel 的优点

winform 中控件被 被遮盖 怎么设置不会被其它控件遮盖 置顶没用比如SplitContainer

SplitContainer 面板调整大小问题