c# 自定义多个SplitContainer 支持点击放大缩小

设计起因:最近在做winfrom自定义打印工具,其中项目中需要为打印界面分四个区 于是想到了splitcontainer,由于是在tabcontrol中放入splitcontainer,所以做成自定义splitcontainer是没毛病的

1.先介绍自定义单个SplitContainer放大缩小:

在自己的winfrom项目下新建一个组件类,名为SplitContainerEx.cs

然后写上如下代码,具体可以自己看

  1     public partial class SplitContainerEx : SplitContainer
  2     {
  3         enum MouseState
  4         {
  5             /// <summary>
  6             /// 正常
  7             /// </summary>
  8             Normal,
  9             /// <summary>
 10             /// 鼠标移入
 11             /// </summary>
 12             Hover
 13         }
 14         
 15         public SplitContainerEx()
 16         {            
 17             this.SetStyle(
 18                 ControlStyles.UserPaint |
 19                 ControlStyles.AllPaintingInWmPaint |
 20                 ControlStyles.OptimizedDoubleBuffer, true);
 21             this.SplitterWidth = 11;
 22             this.Panel1MinSize = 0;
 23             this.Panel2MinSize = 0;
 24             this.Orientation = Orientation.Horizontal;
 25             this.SplitterDistance = 50;
 26         }
 27 
 28         [Browsable(false)]
 29         [EditorBrowsable(EditorBrowsableState.Never)]
 30         public new int SplitterWidth
 31         {
 32             get
 33             {
 34                 return base.SplitterWidth;
 35             }
 36             set
 37             {
 38                 base.SplitterWidth = 11;
 39             }
 40         }
 41 
 42         [Browsable(false)]
 43         [EditorBrowsable(EditorBrowsableState.Never)]
 44         public new int Panel1MinSize
 45         {
 46             get
 47             {
 48                 return base.Panel1MinSize;
 49             }
 50             set
 51             {
 52                 base.Panel1MinSize = 0;
 53             }
 54         }
 55 
 56         [Browsable(false)]
 57         [EditorBrowsable(EditorBrowsableState.Never)]
 58         public new int Panel2MinSize
 59         {
 60             get
 61             {
 62                 return base.Panel2MinSize;
 63             }
 64             set
 65             {
 66                 base.Panel2MinSize = 0;
 67             }
 68         }
 69 
 70         public enum SplitterPanelEnum
 71         {
 72             Panel1,
 73             Panel2
 74         }
 75 
 76         SplitterPanelEnum mCollpasePanel = SplitterPanelEnum.Panel1;
 77         /// <summary>
 78         /// 进行折叠或展开的SplitterPanel
 79         /// </summary>
 80         [DefaultValue(SplitterPanelEnum.Panel2)]
 81         public SplitterPanelEnum CollpasePanel
 82         {
 83             get
 84             {
 85                 return mCollpasePanel;
 86             }
 87             set
 88             {
 89                 if (value != mCollpasePanel)
 90                 {
 91                     mCollpasePanel = value;
 92                     this.Invalidate(this.ControlRect);
 93                 }
 94             }
 95         }
 96 
 97         bool mCollpased = false;
 98         /// <summary>
 99         /// 是否为折叠状态
100         /// </summary>
101         public bool IsCollpased
102         {
103             get { return mCollpased; }
104         }
105 
106         Rectangle mRect = new Rectangle();
107         /// <summary>
108         /// 控制器绘制区域
109         /// </summary>
110         private Rectangle ControlRect
111         {
112             get
113             {
114                 if (this.Orientation == Orientation.Horizontal)
115                 {
116                     mRect.X = this.Width <= 80 ? 0 : this.Width / 2 - 40;
117                     mRect.Y = this.SplitterDistance;
118                     mRect.Width = 80;
119                     mRect.Height = 11;
120                 }
121                 else
122                 {
123                     mRect.X = this.SplitterDistance;
124                     mRect.Y = this.Height <= 80 ? 0 : this.Height / 2 - 40;
125                     mRect.Width = 11;
126                     mRect.Height = 80;
127                 }
128                 return mRect;
129             }
130         }
131 
132 
133         private Rectangle ControlRect1
134         {
135             get
136             {
137                 mRect.X = 0;
138                 mRect.Y = this.SplitterDistance;
139                 mRect.Width = 80;
140                 mRect.Height = 11;
141                 return mRect;
142             }            
143         }
144 
145         /// <summary>
146         /// 鼠标状态
147         /// </summary>
148         MouseState mMouseState = MouseState.Normal;
149 
150         protected override void OnPaint(PaintEventArgs e)
151         {
152             base.OnPaint(e);
153             //绘制参数
154             bool collpase = false;
155             if ((this.CollpasePanel == SplitterPanelEnum.Panel1 && mCollpased == false)
156                 || this.CollpasePanel == SplitterPanelEnum.Panel2 && mCollpased)
157             {
158                 collpase = true;
159             }
160             Color color = mMouseState == MouseState.Normal ? SystemColors.ButtonShadow : SystemColors.ControlDarkDark;
161             //需要绘制的图片
162             Bitmap bmp = CreateControlImage(collpase, color);
163             //绘制区域
164             if (this.Orientation == Orientation.Vertical)
165             {
166                 bmp.RotateFlip(RotateFlipType.Rotate90FlipX);
167             }
168             //清除绘制区域
169             e.Graphics.SetClip(this.SplitterRectangle);   //这里需要注意一点就是需要清除拆分器整个区域,如果仅清除控制按钮区域,则会出现虚线状态
170             e.Graphics.Clear(this.BackColor);
171             //绘制
172             e.Graphics.DrawImage(bmp, this.ControlRect);
173 
174             e.Graphics.DrawString("text", new System.Drawing.Font("宋体", 9), new SolidBrush(Color.Black), this.ControlRect1);
175         }
176 
177         public new bool IsSplitterFixed
178         {
179             get
180             {
181                 return base.IsSplitterFixed;
182             }
183             set
184             {
185                 base.IsSplitterFixed = value;
186                 //此处设计防止运行时更改base.IsSplitterFixed属性时导致mIsSplitterFixed变量判断失效
187                 if (value && mIsSplitterFixed == false)
188                 {
189                     mIsSplitterFixed = true;
190                 }
191             }
192         }
193 
194         bool mIsSplitterFixed = true;
195         protected override void OnMouseMove(MouseEventArgs e)
196         {
197             //鼠标在控制按钮区域
198             if (this.SplitterRectangle.Contains(e.Location))
199             {
200                 if (this.ControlRect.Contains(e.Location))
201                 {
202                     //如果拆分器可移动,则鼠标在控制按钮范围内时临时关闭拆分器
203                     if (this.IsSplitterFixed == false)
204                     {
205                         this.IsSplitterFixed = true;
206                         mIsSplitterFixed = false;
207                     }
208                     this.Cursor = Cursors.Hand;
209                     mMouseState = MouseState.Hover;
210                     this.Invalidate(this.ControlRect);
211                 }
212                 else
213                 {
214                     //如果拆分器为临时关闭,则开启拆分器
215                     if (mIsSplitterFixed == false)
216                     {
217                         this.IsSplitterFixed = false;
218                         if (this.Orientation == Orientation.Horizontal)
219                         {
220                             this.Cursor = Cursors.HSplit;
221                         }
222                         else
223                         {
224                             this.Cursor = Cursors.VSplit;
225                         }
226                     }
227                     else
228                     {
229                         this.Cursor = Cursors.Default;
230                     }
231                     mMouseState = MouseState.Normal;
232                     this.Invalidate(this.ControlRect);
233                 }
234             }
235             base.OnMouseMove(e);
236         }
237 
238         protected override void OnMouseLeave(EventArgs e)
239         {
240             this.Cursor = Cursors.Default;
241             mMouseState = MouseState.Normal;
242             this.Invalidate(this.ControlRect);
243             base.OnMouseLeave(e);
244         }
245 
246         protected override void OnMouseClick(MouseEventArgs e)
247         {
248             if (this.ControlRect.Contains(e.Location))
249             {
250                 CollpaseOrExpand();
251             }
252             base.OnMouseClick(e);
253         }
254 
255         int _HeightOrWidth;
256         /// <summary>
257         /// 折叠或展开
258         /// </summary>
259         public void CollpaseOrExpand()
260         {
261             if (mCollpased)
262             {
263                 mCollpased = false;
264                 this.SplitterDistance = _HeightOrWidth;
265             }
266             else
267             {
268                 mCollpased = true;
269                 _HeightOrWidth = this.SplitterDistance;
270                 if (CollpasePanel == SplitterPanelEnum.Panel1)
271                 {
272                     this.SplitterDistance = 0;
273                 }
274                 else
275                 {
276                     if (this.Orientation == Orientation.Horizontal)
277                     {
278                         this.SplitterDistance = this.Height - 9;
279                     }
280                     else
281                     {
282                         this.SplitterDistance = this.Width - 9;
283                     }
284                 }
285             }
286             this.Invalidate(this.ControlRect); //局部刷新绘制
287         }
288 
289 
290         /// <summary>
291         /// 需要绘制的用于折叠窗口的按钮样式
292         /// </summary>
293         /// <param name="collapse"></param>
294         /// <param name="color"></param>
295         /// <returns></returns>
296         private Bitmap CreateControlImage(bool collapse, Color color)
297         {
298             Bitmap bmp = new Bitmap(80, 9);
299             for (int x = 5; x <= 30; x += 5)
300             {
301                 for (int y = 1; y <= 7; y += 3)
302                 {
303                     bmp.SetPixel(x, y, color);
304                 }
305             }
306             for (int x = 50; x <= 75; x += 5)
307             {
308                 for (int y = 1; y <= 7; y += 3)
309                 {
310                     bmp.SetPixel(x, y, color);
311                 }
312             }
313             //控制小三角底边向上或者向下
314             if (collapse)
315             {
316                 int k = 0;
317                 for (int y = 7; y >= 1; y--)
318                 {
319                     for (int x = 35 + k; x <= 45 - k; x++)
320                     {
321                         bmp.SetPixel(x, y, color);
322                     }
323                     k++;
324                 }
325             }
326             else
327             {
328                 int k = 0;
329                 for (int y = 1; y <= 7; y++)
330                 {
331                     for (int x = 35 + k; x <= 45 - k; x++)
332                     {
333                         bmp.SetPixel(x, y, color);
334                     }
335                     k++;
336                 }
337             }
338             return bmp;
339         }

可以在工具箱中看到就算完成了。

2.多个自定义splitcontainer

新建一个组件类,名为FreeSplit.cs,继承UserControl类 就可以任意拖动刚才自定义的splitcontainer了。效果如下

3.在tabcontrol中铺满

        private int _componentCount = 0;
        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            
            TabPage tabpage = new TabPage("New" + _userControlCount);
            propertyGrid.FreeSplit sp = new propertyGrid.FreeSplit();
            sp.Parent = tabpage;
            sp.Dock = DockStyle.Fill;//控件的各个边缘分别停靠在其包含控件的各个边缘,并且适当调整大小
            tabControl1.TabPages.Add(tabpage);
            tabControl1.SelectedIndex = tabControl1.TabPages.Count - 1;
                
        }

 

转载于:https://www.cnblogs.com/cxyzhangjie/p/8364854.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值