程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WinForm中重繪滾動條以及用重繪的滾動條控制ListBox的滾動

WinForm中重繪滾動條以及用重繪的滾動條控制ListBox的滾動

編輯:關於.NET

在本人的上一篇隨筆<<高仿QQMusic播放器,淺談WinForm關於UI的制作 >>一文中,本人對播放器列表右邊的灰色滾動條極為不滿意,也影響到整個 軟件UI的協調性,遂下決心要重繪一個符合自己UI風格的滾動條.

查了很多資料,都找不到直接重寫ListBox滾動條的方法,只能曲線救國,先自己 重繪一個帶皮膚的滾動條,然後讓它取代ListBox現有的滾動條.

老習慣,先傳個效果圖,你覺得感興趣就繼續看下去,不喜歡的話就此打住, 懶得耽誤你寶

貴的時間,嘿嘿

注意,此圖中的滾動條寬度明顯小於ListBox本身滾動條的寬度,我目前只顧 著實現功能了,畢竟,寬度調整相當簡單哈。

下面簡單介紹下重繪系統滾動條的詳細步驟:

1.在項目中添加新項--用戶控件,我們命名為CustomScrollbar.cs

2.准備幾張圖片添加進項目資源作為滾動條重繪時要用的背景,我用的圖片如 下:

 uparrow.png資源名稱為uparrow   ,滾動條的上箭頭

 ThumbBottom.png資源名稱為ThumbBottom  ,滾動條中間 滑道的背景

ThumbMiddle.png資源名稱為ThumbMiddle  ,滾動條的中 間的拖動塊

downarrow.png資源名稱為downarrow   ,滾動條的下箭 頭

3.然後就是利用上面圖片做背景重畫滾動條背景了,直接給出 CustomScrollbar.cs的代碼吧

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,代碼如下:

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使之同步滾動

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);



        }

感謝博友Yellowyu在滾動控制方面給予的幫助

調整了一下滾動條重繪所用到的圖片的尺寸,看起來效果好多了!!!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved