Click here to Skip to main content
Click here to Skip to main content

Custom Drawn Scrollbar

, 28 Aug 2009
Rate this:
Please Sign up or sign in to vote.
An article about creating a custom scrollbar control

Introduction 

I was working (in my free time) on a calendar control which looks similar to the one in Outlook 2007 and I encountered, among other problems, that the standard scrollbar doesn't fit nicely with the look of my calendar control. So I searched the Web and CodeProject for custom drawn scrollbars.

Among others, I found the article from Greg Ellis. Although it pointed me in the right direction, I missed some things the system scrollbar is capable of. As a last resort, I searched in the help of Visual Studio and found a simple example of a custom drawn scrollbar which I took as a starting point.

Some Remarks

This control is mostly useful for developers who build their own custom drawn controls and need a scrollbar.

The scrollbar has one major shortcoming - the width is fixed. I didn't need this feature and the drawing would be more complex, so I left it out.
Because I used collection initializers, the project builds only with a C# 3.0 compiler and upwards, but that can easily be fixed.
To enable the scrollbar to scroll when pressing and holding the mouse button, I used a timer - didn't find another way.
The drawing is realized with GDI+ (in a separate renderer class) with two exceptions: the little arrow in the arrow buttons and the grip in the thumb are images - there, shame on me, I was a bit lazy.

Layout of the Control

As it is said, a picture says more than thousand words, here is a diagram with the essential classes: 

Please note that the property Opacity sets the opacity of the context menu, not of the control itself.
I left out the control designer class because it's not really necessary, only when using Visual Studio. 

Let's Start 

When drawing a control from scratch, it's necessary to override the OnPaint method and also, in my humble opinion, to set some control styles in the constructor:

public ScrollBarEx()
{
   // sets the control styles of the control
   SetStyle(
     ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw
     | ControlStyles.Selectable | ControlStyles.AllPaintingInWmPaint
     | ControlStyles.UserPaint, true);

     ....
}

After that, some thoughts have to go to the logic of the control, among them methods to calculate the thumb size and position.
As an example, here is the method that calculates the thumb size: 

private int GetThumbSize()
{
    // get the size of the track the thumb can occupy
    int trackSize =
       this.orientation == ScrollBarOrientation.Vertical ?
       this.Height - (2 * this.arrowHeight) : this.Width - (2 * this.arrowWidth);

    if (this.maximum == 0 || this.largeChange == 0)
    {
       return trackSize;
    }

    float newThumbSize = ((float)this.largeChange * (float)trackSize) /
      (float)this.maximum;

    return Convert.ToInt32(Math.Min((float)trackSize, Math.Max(newThumbSize, 10f)));
}

The second step was to think about mouse handling, so one needs to override the OnMouseDown, OnMouseUp and OnMouseMove methods to interact with the mouse.

There are three main areas where mouse handling is done:

  • arrow buttons
  • thumb
  • track above and under the thumb

As an addition, I've also overridden OnMouseEnter and OnMouseLeave to get a visual indication whether the mouse is over the scrollbar or not.

The third step was the interaction with the keyboard and can be done in several ways - one way is to override the ProcessDialogKey method which captures also the arrow keys that will be needed to navigate the scrollbar.

The last step was to implement the drawing functionality which I put in a renderer class to separate logic and drawing of the control.

To prevent the painting but still be able to update the scrollbar, two methods were added to the control: 

  • BeginUpdate
  • EndUpdate

These methods send a message via the SendMessage API switching the painting on or off.

Some Last Words

This is my first article here on CodeProject (or elsewhere), so please bear with me. I know this isn't a very good article, but I hope with time and experience future articles will be better. Feel free to point out what I should have done better.

History

  • 28th August, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Thomas Duwe

Germany Germany
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 PinmemberWonderwhy113-Oct-12 2:19 
AnswerRe: My vote of 5 PinmemberThomas Duwe14-Oct-12 21:36 
GeneralMy vote of 5 PinmemberTinhiuvanoinho23-Jul-11 6:16 
GeneralRe: My vote of 5 PinmemberThomas Duwe25-Aug-11 23:04 
GeneralAttaching the scrollbar to panel Pinmemberroopan18-Dec-09 4:05 
GeneralRe: Attaching the scrollbar to panel PinmemberThomas Duwe19-Dec-09 15:51 
GeneralRe: Attaching the scrollbar to panel Pinmemberroopan19-Dec-09 18:30 
GeneralRe: Attaching the scrollbar to panel PinmemberThomas Duwe29-Dec-09 5:14 
GeneralGreat job 5! PinmemberV# Guy31-Aug-09 16:11 
GeneralRe: Great job 5! PinmemberThomas Duwe1-Sep-09 22:14 
GeneralThanks PinmemberPaul Selormey28-Aug-09 16:16 
GeneralRe: Thanks PinmemberThomas Duwe28-Aug-09 17:28 
GeneralCool - Voted 5 PinmemberAnt210028-Aug-09 8:18 
GeneralRe: Cool - Voted 5 PinmemberThomas Duwe28-Aug-09 13:51 
GeneralRe: Cool - Voted 5 PinmemberAnt210029-Aug-09 0:13 
GeneralRe: Cool - Voted 5 Pinmemberqingpoqiu1-May-13 16:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 28 Aug 2009
Article Copyright 2009 by Thomas Duwe
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid