熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

重繪的滾動條控制ListBox的滾動

2013-11-13 10:03:23  來源: .NET編程 

  查了很多資料都找不到直接重寫ListBox滾動條的方法只能曲線救國先自己重繪一個帶皮膚的滾動條然後讓它取代ListBox現有的滾動條
老習慣先傳個效果圖你覺得感興趣就繼續看下去不喜歡的話就此打住懶得耽誤你寶貴的時間嘿嘿

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

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

  在項目中添加新項用戶控件我們命名為CustomScrollbarcs

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

  uparrowpng資源名稱為uparrow   滾動條的上箭頭
 

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

  ThumbMiddlepng資源名稱為ThumbMiddle  滾動條的中間的拖動塊

  downarrowpng資源名稱為downarrow   滾動條的下箭頭

  然後就是利用上面圖片做背景重畫滾動條背景了直接給出CustomScrollbarcs的代碼吧
Code
using System;
using SystemCollectionsGeneric;
using SystemComponentModel;
using SystemDrawing;
using SystemData;
using SystemText;
using SystemWindowsForms;
using SystemWindowsFormsDesign;
using SystemDiagnostics;
namespace Winamp
{
    [Designer(typeof(ScrollbarControlDesigner))]
    public partial class CustomScrollbar : UserControl
    {

  protected Color moChannelColor = ColorEmpty;
        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 = ;
        protected int moSmallChange = ;
        protected int moMinimum = ;
        protected int moMaximum = ;
        protected int moValue = ;
        private int nClickPoint;

  protected int moThumbTop = ;

  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 = (thisHeight (UpArrowImageHeight + DownArrowImageHeight));
            float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
            int nThumbHeight = (int)fThumbHeight;

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

  return nThumbHeight;
        }

  public CustomScrollbar()
        {

  InitializeComponent();
            SetStyle(ControlStylesResizeRedraw true);
            SetStyle(ControlStylesAllPaintingInWmPaint true);
            SetStyle(ControlStylesDoubleBuffer true);

  moChannelColor = ColorFromArgb( );
            UpArrowImage = BASSSkinuparrow;//上箭頭
            DownArrowImage = BASSSkindownarrow;//下肩頭

  ThumbBottomImage = BASSSkinThumbBottom;

  ThumbMiddleImage = BASSSkinThumbMiddle;

  thisWidth = UpArrowImageWidth;//px
            baseMinimumSize = new Size(UpArrowImageWidth UpArrowImageHeight + DownArrowImageHeight + GetThumbHeight());
        }

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

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

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

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

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

  int nTrackHeight = (thisHeight (UpArrowImageHeight + DownArrowImageHeight));
                float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
                int nThumbHeight = (int)fThumbHeight;

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

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

  }

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

  Invalidate();
            }
        }

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

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

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

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

  [EditorBrowsable(EditorBrowsableStateAlways) 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)
        {

  eGraphicsInterpolationMode = SystemDrawingDrawingDInterpolationModeNearestNeighbor;

  if (UpArrowImage != null)
            {
                eGraphicsDrawImage(UpArrowImage new Rectangle(new Point( ) new Size(thisWidth UpArrowImageHeight)));
            }

  Brush oBrush = new SolidBrush(moChannelColor);
            Brush oWhiteBrush = new SolidBrush(ColorFromArgb( ));
            //          函數名: rectangle
            //功 能: 畫一個矩形
            //用 法: void far rectangle(int left int top int right int bottom);

  //draw channel left and right border colors
            eGraphicsFillRectangle(oWhiteBrush new Rectangle( UpArrowImageHeight (thisHeight DownArrowImageHeight)));
            eGraphicsFillRectangle(oWhiteBrush new Rectangle(thisWidth UpArrowImageHeight (thisHeight DownArrowImageHeight)));

  //draw channel
            //eGraphicsFillRectangle(oBrush new Rectangle( UpArrowImageHeight thisWidth (thisHeightDownArrowImageHeight)));
            eGraphicsDrawImage(ThumbBottomImage new Rectangle( UpArrowImageHeight thisWidth (thisHeight DownArrowImageHeight)));
            //draw thumb
            int nTrackHeight = (thisHeight (UpArrowImageHeight + DownArrowImageHeight));
            float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
            int nThumbHeight = (int)fThumbHeight;

  if (nThumbHeight > nTrackHeight)
            {
                nThumbHeight = nTrackHeight;
                fThumbHeight = nTrackHeight;
            }
            //MessageBoxShow(nThumbHeightToString());
            if (nThumbHeight < )
            {
                nThumbHeight = ;
                fThumbHeight = ;
            }

  //DebugWriteLine(nThumbHeightToString());

  //float fSpanHeight = (fThumbHeight (ThumbMiddleImageHeight + ThumbTopImageHeight + ThumbBottomImageHeight)) / f;
            //int nSpanHeight = (int)fSpanHeight;

  int nTop = moThumbTop;//
            nTop += UpArrowImageHeight;//px

  //draw top畫上面的按鈕
            //eGraphicsDrawImage(ThumbTopImage new Rectangle( nTop thisWidth ThumbTopImageHeight));

  //nTop += ThumbTopImageHeight;//px
            //draw top span
            //Rectangle rect = new Rectangle( nTop thisWidth nSpanHeight);

  //eGraphicsDrawImage(ThumbTopSpanImage f(float)nTop (float)thisWidthf (float) fSpanHeight*);

  // nTop += nSpanHeight;//px
            //draw middle
            eGraphicsDrawImage(ThumbMiddleImage new Rectangle( nTop thisWidth ThumbMiddleImageHeight));

  //nTop += ThumbMiddleImageHeight;
            //draw top span
            //rect = new Rectangle( nTop thisWidth nSpanHeight*);
            //eGraphicsDrawImage(ThumbBottomSpanImage rect);

  //nTop += nSpanHeight;
            //draw bottom
            //eGraphicsDrawImage(ThumbBottomImage new Rectangle( nTop thisWidth nSpanHeight));

  if (DownArrowImage != null)
            {
                eGraphicsDrawImage(DownArrowImage new Rectangle(new Point( (thisHeight DownArrowImageHeight)) new Size(thisWidth DownArrowImageHeight)));
            }

  }

  public override bool AutoSize
        {
            get
            {
                return baseAutoSize;
            }
            set
            {
                baseAutoSize = value;
                if (baseAutoSize)
                {
                    thisWidth = moUpArrowImageWidth;
                }
            }
        }

  private void InitializeComponent()
        {
            thisSuspendLayout();
            //
            // CustomScrollbar
            //
            thisName = CustomScrollbar;
            thisMouseDown += new SystemWindowsFormsMouseEventHandler(thisCustomScrollbar_MouseDown);
            thisMouseMove += new SystemWindowsFormsMouseEventHandler(thisCustomScrollbar_MouseMove);
            thisMouseUp += new SystemWindowsFormsMouseEventHandler(thisCustomScrollbar_MouseUp);
            thisResumeLayout(false);

  }

  private void CustomScrollbar_MouseDown(object sender MouseEventArgs e)
        {
            Point ptPoint = thisPointToClient(CursorPosition);
            int nTrackHeight = (thisHeight (UpArrowImageHeight + DownArrowImageHeight));
            float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
            int nThumbHeight = (int)fThumbHeight;

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

  int nTop = moThumbTop;
            nTop += UpArrowImageHeight;

  Rectangle thumbrect = new Rectangle(new Point( nTop) new Size(ThumbMiddleImageWidth nThumbHeight));
            if (thumbrectContains(ptPoint))
            {

  //hit the thumb
                nClickPoint = (ptPointY nTop);
                //MessageBoxShow(ConvertToString((ptPointY nTop)));
                thismoThumbDown = true;
            }

  Rectangle uparrowrect = new Rectangle(new Point( ) new Size(UpArrowImageWidth UpArrowImageHeight));
            if (uparrowrectContains(ptPoint))
            {

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

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

  moValue = (int)fValue;
                        DebugWriteLine(moValueToString());

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

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

  Invalidate();
                    }
                }
            }

  Rectangle downarrowrect = new Rectangle(new Point( UpArrowImageHeight + nTrackHeight) new Size(UpArrowImageWidth UpArrowImageHeight));
            if (downarrowrectContains(ptPoint))
            {
                int nRealRange = (Maximum Minimum) LargeChange;
                int nPixelRange = (nTrackHeight nThumbHeight);
                if (nRealRange > )
                {
                    if (nPixelRange > )
                    {
                        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;
                        DebugWriteLine(moValueToString());

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

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

  Invalidate();
                    }
                }
            }
        }

  private void CustomScrollbar_MouseUp(object sender MouseEventArgs e)
        {
            thismoThumbDown = false;
            thismoThumbDragging = false;
        }

  private void MoveThumb(int y)
        {
            int nRealRange = Maximum Minimum;
            int nTrackHeight = (thisHeight (UpArrowImageHeight + DownArrowImageHeight));
            float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
            int nThumbHeight = (int)fThumbHeight;

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

  int nSpot = nClickPoint;

  int nPixelRange = (nTrackHeight nThumbHeight);
            if (moThumbDown && nRealRange > )
            {
                if (nPixelRange > )
                {
                    int nNewThumbTop = y (UpArrowImageHeight + nSpot);

  if (nNewThumbTop < )
                    {
                        moThumbTop = nNewThumbTop = ;
                    }
                    else if (nNewThumbTop > nPixelRange)
                    {
                        moThumbTop = nNewThumbTop = nPixelRange;
                    }
                    else
                    {
                        moThumbTop = y (UpArrowImageHeight + nSpot);
                    }

  //figure out value
                    float fPerc = (float)moThumbTop / (float)nPixelRange;
                    float fValue = fPerc * (Maximum LargeChange);
                    moValue = (int)fValue;
                    DebugWriteLine(moValueToString());

  ApplicationDoEvents();

  Invalidate();
                }
            }
        }

  private void CustomScrollbar_MouseMove(object sender

  MouseEventArgs e)
        {
            if (moThumbDown == true)
            {
                thismoThumbDragging = true;
            }

  if (thismoThumbDragging)
            {

  MoveThumb(eY);
            }

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

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

  }

  internal class ScrollbarControlDesigner : SystemWindowsFormsDesignControlDesigner
    {

  public override SelectionRules SelectionRules
        {
            get
            {
                SelectionRules selectionRules = baseSelectionRules;
                PropertyDescriptor propDescriptor = TypeDescriptorGetProperties(thisComponent)[AutoSize];
                if (propDescriptor != null)
                {
                    bool autoSize = (bool)propDescriptorGetValue(thisComponent);
                    if (autoSize)
                    {
                        selectionRules = SelectionRulesVisible | SelectionRulesMoveable | SelectionRulesBottomSizeable | SelectionRulesTopSizeable;
                    }
                    else
                    {
                        selectionRules = SelectionRulesVisible | SelectionRulesAllSizeable | SelectionRulesMoveable;
                    }
                }
                return selectionRules;
            }
        }
    }
}
目前只想簡單實現滾動條中上箭頭/下箭頭/滑道/拖動塊的重寫所以以上代碼中OnPaint函數裡的部分內容被我注釋了好了這個滾動條控件已經做好了一個控件而已你應該會使用它我就不羅嗦了

  接下來就是怎麼用它來控制ListBox的內容滾動的問題了這需要調用API函數來實現同時又不能設置ListBox無滾動條因為ListBox沒有滾動條也就沒有滾動的事件可捕獲那就達不到滾動的效果了

  在你的窗體裡拖一個listbox控件和一個上邊我們制作好的用戶控件分明命名為listBox和customScrollbar

  然後往listBox中隨便多弄寫內容使之出現滾動條即可調整customScrollbar的位置使之覆蓋在listBox的滾動條上呵呵這方法不錯吧?

  然後我們定義一下WinAPI代碼如下

  Code
public class WinAPI
        {
            [StructLayout(LayoutKindSequential)]
            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 =
                SB_VERT =
                SB_CTL =
            }
            public enum fMask
            {
                SIF_ALL
                SIF_DISABLENOSCROLL = X
                SIF_PAGE = X
                SIF_POS = X
                SIF_RANGE = X
                SIF_TRACKPOS = X
            }

  public static int MakeLong(short lowPart short highPart)
            {
                return (int)(((ushort)lowPart) | (uint)(highPart << ));
            }
            public const int SB_THUMBTRACK = ;
            public const int WM_HSCROLL = x;
            public const int WM_VSCROLL = x;
            [DllImport(userdll EntryPoint = GetScrollInfo)]
            public static extern bool GetScrollInfo(IntPtr hwnd int fnBar ref SCROLLINFO lpsi);
         [DllImport(userdll EntryPoint = SetScrollInfo)]
        public static extern int SetScrollInfo(IntPtr hwnd int fnBar [In] ref SCROLLINFO  lpsi bool fRedraw);

  [DllImport(Userdll CharSet = CharSetAuto EntryPoint = SendMessage)]
        static extern IntPtr SendMessage(IntPtr hWnd uint Msg IntPtr wParam IntPtr lParam);
        [DllImport(userdll SetLastError = true)]
        public static extern bool PostMessage(IntPtr hWnd uint Msg long wParamint 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 = x
            SIF_PAGE = x
            SIF_POS = x
            SIF_DISABLENOSCROLL = x
            SIF_TRACKPOS = x
            SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS
        }
         enum ScrollBarDirection
        {
            SB_HORZ =
            SB_VERT =
            SB_CTL =
            SB_BOTH =
        }

  public SCROLLINFO tvImageListScrollInfo
        {

  get
            {

  SCROLLINFO si = new SCROLLINFO();

  sicbSize = (uint)MarshalSizeOf(si);

  sifMask = (int)(ScrollInfoMaskSIF_DISABLENOSCROLL | ScrollInfoMaskSIF_ALL);

  WinAPIGetScrollInfo(listBoxHandle (int)ScrollBarDirectionSB_VERT ref si);

  return si;

  }

  }
        //當鼠標滾動時設置該滾動條

  private void SetImageListScroll()

  {

  SCROLLINFO info = tvImageListScrollInfo;

  if (infonMax > )

  {

  int pos = infonPos ;

  if (pos >= )

  {

  customScrollbarValue = pos;

  }

  }

  }
定義customScrollbar的滾動事件函數customScrollbar_Scroll實現在滾動條滾動的同時發消息給listBox使之同步滾動

  Code
private void customScrollbar_Scroll(object sender EventArgs m)
        {
            //當滾動條滾動時通知控件也跟著滾動吧

  SCROLLINFO info = tvImageListScrollInfo;

  infonPos = customScrollbarValue;

  WinAPISetScrollInfo(listBoxHandle (int)ScrollBarDirectionSB_VERT ref info true);

  WinAPIPostMessage(listBoxHandle WinAPIWM_VSCROLL WinAPIMakeLong((short)WinAPISB_THUMBTRACK (short)(infonPos)) );

  }


From:http://tw.wingwit.com/Article/program/net/201311/12416.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.