您的位置:首页技术开发.Net 专栏 → 用重绘的滚动条控制ListBox的滚动

用重绘的滚动条控制ListBox的滚动

时间:2009/4/7 8:37:00来源:本站整理作者:我要评论(1)

查了很多资料,都找不到直接重写ListBox滚动条的方法,只能曲线救国,先自己重绘一个带皮肤的滚动条,然后让它取代ListBox现有的滚动条.
老习惯,先传个效果图,你觉得感兴趣就继续看下去,不喜欢的话就此打住,懒得耽误你宝

贵的时间,嘿嘿

注意,此图中的滚动条宽度明显小于ListBox本身滚动条的宽度,我目前只顾着实现功能了,毕竟,宽度调整相当简单哈。

下面简单介绍下重绘系统滚动条的详细步骤:

1.在项目中添加新项--用户控件,我们命名为CustomScrollbar.cs

2.准备几张图片添加进项目资源作为滚动条重绘时要用的背景,我用的图片如下:

 

     uparrow.png资源名称为uparrow   ,滚动条的上箭头
 

     ThumbBottom.png资源名称为ThumbBottom  ,滚动条中间滑道的背景
 


    ThumbMiddle.png资源名称为ThumbMiddle  ,滚动条的中间的拖动块


    downarrow.png资源名称为downarrow   ,滚动条的下箭头

 

3.然后就是利用上面图片做背景重画滚动条背景了,直接给出CustomScrollbar.cs的代码吧
Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Diagnostics;
namespace Winamp
{
    [Designer(typeof(ScrollbarControlDesigner))]
    public partial class CustomScrollbar : UserControl
    {

        protected Color moChannelColor = Color.Empty;
        protected Image moUpArrowImage = null;//上箭头
        //protected Image moUpArrowImage_Over = null;
        //protected Image moUpArrowImage_Down = null;
        protected Image moDownArrowImage = null;//下箭头
        //protected Image moDownArrowImage_Over = null;
        //protected Image moDownArrowImage_Down = null;
        protected Image moThumbArrowImage = null;

        protected Image moThumbTopImage = null;
        protected Image moThumbTopSpanImage = null;
        protected Image moThumbBottomImage = null;
        protected Image moThumbBottomSpanImage = null;
        protected Image moThumbMiddleImage = null;

        protected int moLargeChange = 10;
        protected int moSmallChange = 1;
        protected int moMinimum = 0;
        protected int moMaximum = 100;
        protected int moValue = 0;
        private int nClickPoint;

        protected int moThumbTop = 0;

        protected bool moAutoSize = false;

        private bool moThumbDown = false;
        private bool moThumbDragging = false;

        public new event EventHandler Scroll = null;
        public event EventHandler ValueChanged = null;

        private int GetThumbHeight()
        {
            int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
            float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
            int nThumbHeight = (int)fThumbHeight;

            if (nThumbHeight > nTrackHeight)
            {
                nThumbHeight = nTrackHeight;
                fThumbHeight = nTrackHeight;
            }
            if (nThumbHeight < 56)
            {
                nThumbHeight = 56;
                fThumbHeight = 56;
            }

            return nThumbHeight;
        }

        public CustomScrollbar()
        {

            InitializeComponent();
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);

            moChannelColor = Color.FromArgb(51, 166, 3);
            UpArrowImage = BASSSkin.uparrow;//上箭头
            DownArrowImage = BASSSkin.downarrow;//下肩头


            ThumbBottomImage = BASSSkin.ThumbBottom;

            ThumbMiddleImage = BASSSkin.ThumbMiddle;

            this.Width = UpArrowImage.Width;//18px
            base.MinimumSize = new Size(UpArrowImage.Width, UpArrowImage.Height + DownArrowImage.Height + GetThumbHeight());
        }

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description("LargeChange")]
        public int LargeChange
        {
            get { return moLargeChange; }
            set
            {
                moLargeChange = value;
                Invalidate();
            }
        }

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description("SmallChange")]
        public int SmallChange
        {
            get { return moSmallChange; }
            set
            {
                moSmallChange = value;
                Invalidate();
            }
        }

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description("Minimum")]
        public int Minimum
        {
            get { return moMinimum; }
            set
            {
                moMinimum = value;
                Invalidate();
            }
        }

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description("Maximum")]
        public int Maximum
        {
            get { return moMaximum; }
            set
            {
                moMaximum = value;
                Invalidate();
            }
        }

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Behavior"), Description("Value")]
        public int Value
        {
            get { return moValue; }
            set
            {
                moValue = value;

                int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
                float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
                int nThumbHeight = (int)fThumbHeight;

                if (nThumbHeight > nTrackHeight)
                {
                    nThumbHeight = nTrackHeight;
                    fThumbHeight = nTrackHeight;
                }
                if (nThumbHeight < 56)
                {
                    nThumbHeight = 56;
                    fThumbHeight = 56;
                }

                //figure out value
                int nPixelRange = nTrackHeight - nThumbHeight;
                int nRealRange = (Maximum - Minimum) - LargeChange;
                float fPerc = 0.0f;
                if (nRealRange != 0)
                {
                    fPerc = (float)moValue / (float)nRealRange;

                }

                float fTop = fPerc * nPixelRange;
                moThumbTop = (int)fTop;


                Invalidate();
            }
        }

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Channel Color")]
        public Color ChannelColor
        {
            get { return moChannelColor; }
            set { moChannelColor = value; }
        }

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow Graphic")]
        public Image UpArrowImage
        {
            get { return moUpArrowImage; }
            set { moUpArrowImage = value; }
        }

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow Graphic")]
        public Image DownArrowImage
        {
            get { return moDownArrowImage; }
            set { moDownArrowImage = value; }
        }


        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow Graphic")]
        public Image ThumbBottomImage
        {
            get { return moThumbBottomImage; }
            set { moThumbBottomImage = value; }
        }

 

        [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("Skin"), Description("Up Arrow Graphic")]
        public Image ThumbMiddleImage
        {
            get { return moThumbMiddleImage; }
            set { moThumbMiddleImage = value; }
        }

        protected override void OnPaint(PaintEventArgs e)
        {

            e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;

            if (UpArrowImage != null)
            {
                e.Graphics.DrawImage(UpArrowImage, new Rectangle(new Point(0, 0), new Size(this.Width, UpArrowImage.Height)));
            }

            Brush oBrush = new SolidBrush(moChannelColor);
            Brush oWhiteBrush = new SolidBrush(Color.FromArgb(255, 255, 255));
            //          函数名: rectangle
            //功 能: 画一个矩形
            //用 法: void far rectangle(int left, int top, int right, int bottom);

            //draw channel left and right border colors
            e.Graphics.FillRectangle(oWhiteBrush, new Rectangle(0, UpArrowImage.Height, 1, (this.Height - DownArrowImage.Height)));
            e.Graphics.FillRectangle(oWhiteBrush, new Rectangle(this.Width - 1, UpArrowImage.Height, 1, (this.Height - DownArrowImage.Height)));

            //draw channel
            //e.Graphics.FillRectangle(oBrush, new Rectangle(1, UpArrowImage.Height, this.Width-2, (this.Height-DownArrowImage.Height)));
            e.Graphics.DrawImage(ThumbBottomImage, new Rectangle(0, UpArrowImage.Height, this.Width, (this.Height - DownArrowImage.Height)));
            //draw thumb
            int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
            float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
            int nThumbHeight = (int)fThumbHeight;

            if (nThumbHeight > nTrackHeight)
            {
                nThumbHeight = nTrackHeight;
                fThumbHeight = nTrackHeight;
            }
            //MessageBox.Show(nThumbHeight.ToString());
            if (nThumbHeight < 56)
            {
                nThumbHeight = 56;
                fThumbHeight = 56;
            }

            //Debug.WriteLine(nThumbHeight.ToString());

            //float fSpanHeight = (fThumbHeight - (ThumbMiddleImage.Height + ThumbTopImage.Height + ThumbBottomImage.Height)) / 2.0f;
            //int nSpanHeight = (int)fSpanHeight;

            int nTop = moThumbTop;//0
            nTop += UpArrowImage.Height;//9px

            //draw top画上面的按钮
            //e.Graphics.DrawImage(ThumbTopImage, new Rectangle(0, nTop, this.Width, ThumbTopImage.Height));

            //nTop += ThumbTopImage.Height;//10px
            //draw top span
            //Rectangle rect = new Rectangle(1, nTop, this.Width - 2, nSpanHeight);


            //e.Graphics.DrawImage(ThumbTopSpanImage, 1.0f,(float)nTop, (float)this.Width-2.0f, (float) fSpanHeight*2);

            // nTop += nSpanHeight;//11px
            //draw middle
            e.Graphics.DrawImage(ThumbMiddleImage, new Rectangle(0, nTop, this.Width, ThumbMiddleImage.Height));


            //nTop += ThumbMiddleImage.Height;
            //draw top span
            //rect = new Rectangle(1, nTop, this.Width - 2, nSpanHeight*2);
            //e.Graphics.DrawImage(ThumbBottomSpanImage, rect);

            //nTop += nSpanHeight;
            //draw bottom
            //e.Graphics.DrawImage(ThumbBottomImage, new Rectangle(1, nTop, this.Width - 2, nSpanHeight));

            if (DownArrowImage != null)
            {
                e.Graphics.DrawImage(DownArrowImage, new Rectangle(new Point(0, (this.Height - DownArrowImage.Height)), new Size(this.Width, DownArrowImage.Height)));
            }

        }


        public override bool AutoSize
        {
            get
            {
                return base.AutoSize;
            }
            set
            {
                base.AutoSize = value;
                if (base.AutoSize)
                {
                    this.Width = moUpArrowImage.Width;
                }
            }
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            //
            // CustomScrollbar
            //
            this.Name = "CustomScrollbar";
            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseDown);
            this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseMove);
            this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseUp);
            this.ResumeLayout(false);

        }

        private void CustomScrollbar_MouseDown(object sender, MouseEventArgs e)
        {
            Point ptPoint = this.PointToClient(Cursor.Position);
            int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
            float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
            int nThumbHeight = (int)fThumbHeight;

            if (nThumbHeight > nTrackHeight)
            {
                nThumbHeight = nTrackHeight;
                fThumbHeight = nTrackHeight;
            }
            if (nThumbHeight < 56)
            {
                nThumbHeight = 56;
                fThumbHeight = 56;
            }

            int nTop = moThumbTop;
            nTop += UpArrowImage.Height;


            Rectangle thumbrect = new Rectangle(new Point(1, nTop), new Size(ThumbMiddleImage.Width, nThumbHeight));
            if (thumbrect.Contains(ptPoint))
            {

                //hit the thumb
                nClickPoint = (ptPoint.Y - nTop);
                //MessageBox.Show(Convert.ToString((ptPoint.Y - nTop)));
                this.moThumbDown = true;
            }

            Rectangle uparrowrect = new Rectangle(new Point(1, 0), new Size(UpArrowImage.Width, UpArrowImage.Height));
            if (uparrowrect.Contains(ptPoint))
            {

                int nRealRange = (Maximum - Minimum) - LargeChange;
                int nPixelRange = (nTrackHeight - nThumbHeight);
                if (nRealRange > 0)
                {
                    if (nPixelRange > 0)
                    {
                        if ((moThumbTop - SmallChange) < 0)
                            moThumbTop = 0;
                        else
                            moThumbTop -= SmallChange;

                        //figure out value
                        float fPerc = (float)moThumbTop / (float)nPixelRange;
                        float fValue = fPerc * (Maximum - LargeChange);

                        moValue = (int)fValue;
                        Debug.WriteLine(moValue.ToString());

                        if (ValueChanged != null)
                            ValueChanged(this, new EventArgs());

                        if (Scroll != null)
                            Scroll(this, new EventArgs());

                        Invalidate();
                    }
                }
            }

            Rectangle downarrowrect = new Rectangle(new Point(1, UpArrowImage.Height + nTrackHeight), new Size(UpArrowImage.Width, UpArrowImage.Height));
            if (downarrowrect.Contains(ptPoint))
            {
                int nRealRange = (Maximum - Minimum) - LargeChange;
                int nPixelRange = (nTrackHeight - nThumbHeight);
                if (nRealRange > 0)
                {
                    if (nPixelRange > 0)
                    {
                        if ((moThumbTop + SmallChange) > nPixelRange)
                            moThumbTop = nPixelRange;
                        else
                            moThumbTop += SmallChange;

                        //figure out value
                        float fPerc = (float)moThumbTop / (float)nPixelRange;
                        float fValue = fPerc * (Maximum - LargeChange);

                        moValue = (int)fValue;
                        Debug.WriteLine(moValue.ToString());

                        if (ValueChanged != null)
                            ValueChanged(this, new EventArgs());          if (Scroll != null)
                            Scroll(this, new EventArgs());

 

                        Invalidate();
                    }
                }
            }
        }

        private void CustomScrollbar_MouseUp(object sender, MouseEventArgs e)
        {
            this.moThumbDown = false;
            this.moThumbDragging = false;
        }

        private void MoveThumb(int y)
        {
            int nRealRange = Maximum - Minimum;
            int nTrackHeight = (this.Height - (UpArrowImage.Height + DownArrowImage.Height));
            float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
            int nThumbHeight = (int)fThumbHeight;

            if (nThumbHeight > nTrackHeight)
            {
                nThumbHeight = nTrackHeight;
                fThumbHeight = nTrackHeight;
            }
            if (nThumbHeight < 56)
            {
                nThumbHeight = 56;
                fThumbHeight = 56;
            }

            int nSpot = nClickPoint;

            int nPixelRange = (nTrackHeight - nThumbHeight);
            if (moThumbDown && nRealRange > 0)
            {
                if (nPixelRange > 0)
                {
                    int nNewThumbTop = y - (UpArrowImage.Height + nSpot);

                    if (nNewThumbTop < 0)
                    {
                        moThumbTop = nNewThumbTop = 0;
                    }
                    else if (nNewThumbTop > nPixelRange)
                    {
                        moThumbTop = nNewThumbTop = nPixelRange;
                    }
                    else
                    {
                        moThumbTop = y - (UpArrowImage.Height + nSpot);
                    }

                    //figure out value
                    float fPerc = (float)moThumbTop / (float)nPixelRange;
                    float fValue = fPerc * (Maximum - LargeChange);
                    moValue = (int)fValue;
                    Debug.WriteLine(moValue.ToString());

                    Application.DoEvents();

                    Invalidate();
                }
            }
        }

        private void CustomScrollbar_MouseMove(object sender, MouseEventArgs e)
        {
            if (moThumbDown == true)
            {
                this.moThumbDragging = true;
            }

            if (this.moThumbDragging)
            {

                MoveThumb(e.Y);
            }

            if (ValueChanged != null)
                ValueChanged(this, new EventArgs());

            if (Scroll != null)
                Scroll(this, new EventArgs());
        }

    }

    internal class ScrollbarControlDesigner : System.Windows.Forms.Design.ControlDesigner
    {

 

        public override SelectionRules SelectionRules
        {
            get
            {
                SelectionRules selectionRules = base.SelectionRules;
                PropertyDescriptor propDescriptor = TypeDescriptor.GetProperties(this.Component)["AutoSize"];
                if (propDescriptor != null)
                {
                    bool autoSize = (bool)propDescriptor.GetValue(this.Component);
                    if (autoSize)
                    {
                        selectionRules = SelectionRules.Visible | SelectionRules.Moveable | SelectionRules.BottomSizeable | SelectionRules.TopSizeable;
                    }
                    else
                    {
                        selectionRules = SelectionRules.Visible | SelectionRules.AllSizeable | SelectionRules.Moveable;
                    }
                }
                return selectionRules;
            }
        }
    }
}
目前只想简单实现滚动条中上箭头/下箭头/滑道/拖动块的重写,所以以上代码中OnPaint函数里的部分内容被我注释了,好了,这个滚动条控件已经做好了,一个控件而已,你应该会使用它,我就不罗嗦了。

接下来就是怎么用它来控制ListBox的内容滚动的问题了,这需要调用API函数来实现,同时又不能设置ListBox无滚动条,因为ListBox没有滚动条也就没有滚动的事件可捕获,那就达不到滚动的效果了。

在你的窗体里拖一个listbox控件和一个上边我们制作好的用户控件,分明命名为listBox和customScrollbar1,

然后往listBox中随便多弄写内容,使之出现滚动条即可。调整customScrollbar1的位置使之覆盖在listBox的滚动条上,呵呵,这方法不错吧?

然后我们定义一下Win32API,代码如下:

Code
public class Win32API
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct tagSCROLLINFO
            {
                public uint cbSize;
                public uint fMask;
                public int nMin;
                public int nMax;
                public uint nPage;
                public int nPos;
                public int nTrackPos;
            }
            public enum fnBar
            {
                SB_HORZ = 0,
                SB_VERT = 1,
                SB_CTL = 2
            }
            public enum fMask
            {
                SIF_ALL,
                SIF_DISABLENOSCROLL = 0X0010,
                SIF_PAGE = 0X0002,
                SIF_POS = 0X0004,
                SIF_RANGE = 0X0001,
                SIF_TRACKPOS = 0X0008
            }

            public static int MakeLong(short lowPart, short highPart)
            {
                return (int)(((ushort)lowPart) | (uint)(highPart << 16));
            }
            public const int SB_THUMBTRACK = 5;
            public const int WM_HSCROLL = 0x114;
            public const int WM_VSCROLL = 0x115;
            [DllImport("user32.dll", EntryPoint = "GetScrollInfo")]
            public static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);
         [DllImport("user32.dll", EntryPoint = "SetScrollInfo")]
        public static extern int SetScrollInfo(IntPtr hwnd, int fnBar, [In] ref SCROLLINFO  lpsi, bool fRedraw);

        [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool PostMessage(IntPtr hWnd, uint Msg, long wParam,int lParam);
        }


             
        public struct SCROLLINFO
        {
            public uint cbSize;
            public uint fMask;
            public int nMin;
            public int nMax;
            public uint nPage;
            public int nPos;
            public int nTrackPos;
        }
        enum ScrollInfoMask
        {
            SIF_RANGE = 0x1,
            SIF_PAGE = 0x2,
            SIF_POS = 0x4,
            SIF_DISABLENOSCROLL = 0x8,
            SIF_TRACKPOS = 0x10,
            SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS
        }
         enum ScrollBarDirection
        {
            SB_HORZ = 0,
            SB_VERT = 1,
            SB_CTL = 2,
            SB_BOTH = 3
        }


        public SCROLLINFO tvImageListScrollInfo
        {

            get
            {

                SCROLLINFO si = new SCROLLINFO();

                si.cbSize = (uint)Marshal.SizeOf(si);

                si.fMask = (int)(ScrollInfoMask.SIF_DISABLENOSCROLL | ScrollInfoMask.SIF_ALL);

                Win32API.GetScrollInfo(listBox.Handle, (int)ScrollBarDirection.SB_VERT, ref si);

                return si;

            }

        }
        //当鼠标滚动时,设置该滚动条

private void SetImageListScroll()

{

SCROLLINFO info = tvImageListScrollInfo;

if (info.nMax > 0)

{

int pos = info.nPos - 1;

if (pos >= 0)

{

    customScrollbar1.Value = pos;

}

}

}
定义customScrollbar1的滚动事件函数customScrollbar1_Scroll,实现在滚动条滚动的同时发消息给listBox使之同步滚动

Code
private void customScrollbar1_Scroll(object sender, EventArgs m)
        {
            //当滚动条滚动时,通知控件也跟着滚动吧。。。

            SCROLLINFO info = tvImageListScrollInfo;

            info.nPos = customScrollbar1.Value;

            Win32API.SetScrollInfo(listBox.Handle, (int)ScrollBarDirection.SB_VERT, ref info, true);

            Win32API.PostMessage(listBox.Handle, Win32API.WM_VSCROLL, Win32API.MakeLong((short)Win32API.SB_THUMBTRACK, (short)(info.nPos)), 0);


        }

相关视频

    没有数据

相关阅读 用重绘的滚动条控制ListBox的滚动用重绘的滚动条控制ListBox的滚动怎么让小程序view-scroll高度100% 视图滚动效果设置方法详解王者荣耀荣耀时刻需要怎样条件 王者荣耀荣耀时刻活动条件一览阴阳师封魔密信以下哪个技能可以增加己方行动条 答案是什么阴阳师速度和行动条有什么关系 速度和行动关系详解faststone capture怎么滚动截屏 faststone capture滚动截图怎么三星Note3智能滚动怎么用 三星Note3智能滚动怎么开启

文章评论
发表评论

热门文章 没有查询到任何记录。

最新文章 什么是.NET中的TDD?ASP.NET AJAX入门简介 WebMatrix入门教程VC++2008中如何调用GetOpenFileName打开文件PlaySound函数在VC++6.0中如何播放音乐及声请问VC++回调函数怎么用

人气排行 嵌入式实时操作系统VxWorks入门教程ArrayList 与 string、string[] 的转换C#遍历整个文件夹及子目录的文件代码WebMatrix入门教程asp.net判断文件或文件夹是否存在c#判断数据NULL值的方法vc++6.0怎么写Windows简单窗口代码.net解决数据导出excel时的格式问题