C#自定义控件添加滚动条的通用设计方案

本文系原创,转载请注明出处:
https://blog.csdn.net/chengbao315/article/details/104842833

前言:在我工作中,总会手绘一些自定控件,很多时候都会用到滚动条来增加控件的显示内容,但是每次敲代码都有一些重复的操作,于是我想到了一个可以通用的解决方案。

一、滚动条原理
说起滚动条,我们先来了解一下滚动条的实现原理。在我们设计的控件当中,存在两个区域,一个是控件的可视区域,另一个是需要显示的内容区域,如图所示。
在这里插入图片描述
当需要显示的内容范围大于控件的可视范围时,就需要添加滚动条,通过滚动展示显示不下的内容。增加滚动条后,控件的可视范围会被滚动条占用,使”控件的可视范围”变得更小。
在这里插入图片描述
实现滚动条的滚动过程就是:
1.根据控件尺寸和内容范围确定滚动范围;
2.当滚动条滚动时,计算滚动距离;
3.触发控件绘制事件,将可视区域移动相应的滚动距离。

注意:当控件大小和显示内容发生改变时,需要重新确定滚动条是否需要显示,以及确定滚动条滚动范围。

二、滚动条控件的使用
在.NET系统控件中,自带了两个滚动条控件,分别是VScrollBar(竖向滚动条)/ HScrollBar(横向滚动条),实现滚动条效果需要使用控件的以下属性和事件。
属性
Maximum:可滚动范围的上限值(也就是内容区域和控件可视区的高度差/宽度差。)。
SmallChange/LargeChange:小距离移动值/ 大距离移动值,滚动一次的步距。
Value:滚动条的当前位置。
事件
Scroll:滚动条发生滚动时触发事件。

三、我的设计方案
1.创建一个视图类,为自定义控件动态添加滚动条,并处理滚动条的显示、隐藏,以及滚动事件。

	public class PaintView
    {      
		// 构造函数中传入自定义控件实例
        public PaintView(Control view)
        {
            _mDevice = view;
            _mhScroll = new HScrollBar();
            _mvScroll = new VScrollBar();
            _mDevice.Controls.Add(_mhScroll);
            _mDevice.Controls.Add(_mvScroll);

            // 设置控件属性
            _mhScroll.Dock = DockStyle.Bottom;
            _mvScroll.Dock = DockStyle.Right;
            worldWidth = view.Width;
            worldHeight = view.Height;

            // 订阅事件(匿名委托)
            _mDevice.Resize += (s, e) => this.Resize();
            // 根据滚轮滚动方向,滚动条滚动一个大移动值
            _mDevice.MouseWheel += (s, e)=> Y -= e.Delta > 0 ? _mvScroll.LargeChange : -_mvScroll.LargeChange; 
            _mhScroll.Scroll += (s, e) => X = e.NewValue;
            _mvScroll.Scroll += (s, e) => Y = e.NewValue;
			// 计算画布矩阵
            CaculateMatrix();
        }
    }

构造函数中的订阅事件是本文的重点:
1)控件Resize事件:当控件尺寸发生变化时,需要判断是否显示滚动条。
2)控件MouseWheel事件:当控件发生滚轮事件时,需要滚动滚动条位置。
3)滚动条Scroll事件:当滚动条滚动时,将画布平移滚动距离。
我们先来看Resize事件的处理方法:

	private void Resize()
    {
        if(worldWidth<= _mDevice.Width)
        {
            _mhScroll.Hide();
            _mhScroll.Value = 0;
        }
        else
        {
            _mhScroll.Show();
            _mhScroll.Maximum = worldWidth - _mDevice.Width;
        }
        if (worldHeight <= _mDevice.Height)
        {
         	_mvScroll.Hide();
            _mvScroll.Value = 0;
        }
        else
        {
	         _mvScroll.Show();
             _mvScroll.Maximum = worldHeight - _mDevice.Height;
        }
        CaculateMatrix();
		_mDevice.Invalidate();
	}

当显示区域小于或等于控件区域时,隐藏滚动条;当显示区域大于控件区域时,显示滚动条,同时设置滚动范围为长度差。接下来的鼠标滚轮事件和滚动轴滚动事件处理方法就比较容易了,直接设置画布矩阵为滚动的距离,这里定义一个方法CaculateMatrix。

	private void CaculateMatrix()
    {
            _mMatrix = new Matrix();
            // 平移画布滚轮偏移量
            _mMatrix.Translate(-X, -Y);
    }

2.接下来就要举个栗子了,我就以Label控件为例,给他添加滚动条,代码非常简单,在构造函数中实例化一个PaintView实体,之后重写OnPaint方法,设置控件的实际显示区域,然后进行画布矩阵平移,绘制文本字符串。

	public class ScrollLabel: Label
	{
        PaintView _mView;
        public ScrollLabel()
        {
            _mView = new PaintView(this);
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            SizeF sz = e.Graphics.MeasureString(this.Text, this.Font, this.Width);
            _mView.WorldHeight = (int)(sz.Height +1);
            e.Graphics.Transform = _mView.Projection;

            RectangleF rcText = new RectangleF(0, 0, sz.Width, sz.Height);
            e.Graphics.DrawString(this.Text, this.Font, Brushes.Black, rcText);
        }
	}

3.将自定义Label控件拖入窗体,运行程序效果如图所示:在这里插入图片描述
这个例子当中,我的Label控件对文本进行了自动换行处理,而且出现了滚动条,基本需求实现了。不过这个例子也有一些不足之处,就是之前讲原理提到的,滚动条出现会占用一些原有控件的显示区域,导致文本显示不全,由于时间关系,今天我就不继续深入研究了,这里只给大家提供一个设计思路,以后有精力我再慢慢完善,希望本文对你有所帮助。

如果本文有帮到你,记得加关注哦
源码地址:https://download.csdn.net/download/chengbao315/12253770
————————————————
版权声明:本文为CSDN博主「愤斗的程序猿」的原创文章,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chengbao315/article/details/104842833

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C#自定义控件滚动条的实现方法有多种。根据提供的引用内容,我可以为您提供以下方法和步骤来实现滚动条功能: 方法一: 1. 创建一个控件类,可以继承自Panel或者UserControl。该类将作为滚动条的容器。 2. 在该控件类中添加需要滚动的控件作为子控件。 3. 为该控件类添加滚动条控件,可以使用VScrollBar(竖向滚动条)或HScrollBar(横向滚动条)控件。 4. 设置滚动条控件的属性,如Maximum(可滚动范围的上限值)、SmallChange(小距离移动值)、LargeChange(大距离移动值)和Value(滚动条的当前位置)。 5. 给滚动条控件的Scroll事件添加处理方法,以便在滚动时对子控件进行相应操作。 方法二: 1. 创建一个视图类,为自定义控件动态添加滚动条,并处理滚动条的显示、隐藏和滚动事件。 2. 在该视图类的构造函数中传入自定义控件实例。 3. 在视图类中创建VScrollBar(竖向滚动条)和HScrollBar(横向滚动条)控件,并将其添加自定义控件中。 4. 设置滚动条控件的属性,如Dock(使滚动条固定在底部或右侧)、Maximum(可滚动范围的上限值)和LargeChange(大距离移动值)。 5. 订阅滚动条控件的事件,如Scroll(滚动条发生滚动时触发事件)和MouseWheel(根据滚轮滚动方向滚动滚动条)。 6. 在事件处理方法中,根据滚动条的值和滚动方向,对自定义控件进行滚动操作。 以上是两种常见的实现滚动条功能的方法。您可以根据自己的需求选择其中一种或根据具体情况进行修改和扩展。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值