Click here to Skip to main content
15,883,901 members
Articles / Programming Languages / C#
Article

seekBar with Limiters

Rate me:
Please Sign up or sign in to vote.
4.75/5 (5 votes)
27 Apr 2011GPL33 min read 23K   1.3K   18   4
seekBar enables user to track media playing progress and limit playing to a section
Sample Image - maximum width is 600 pixels

Introduction

seekBar is used to track progress. It has left and right limiters that can be used to play a certain region of media. It is useful in media playing applications.

Background

I created this control as part of a much larger project because I needed a control that will display progress of video playing, but allow user to limit the region that is needed to be previewed. I have not searched very thoroughly, but in my preliminaries, I have not found anything that would satisfy my requirement so I decided to make it.

Concept and Implementation

The idea behind this control is to be simple to use and to have minimalistic look, so basically I wanted it to just do its job without unnecessary graphics images, etc.

But if need be, it can be easily adapted to have for example some image instead of a diamond marker or any other area.

The concept is rather simple. Basically, you have three track bars and only one is moving. The other two are left and right limiters. They all use the same code for calculation of value, percent, etc. The only difference is that left and right limiters never move by themselves as they are intended to be dragged by user to the desired location. So when you have this, it's rather simple to imagine how it all works.

The most work is drawing the control. Basically, I override the onPaint method that calls three other methods that do all the drawing.

1. createMainBar

C#
private void createMainBar(Graphics g)
{
    Pen p = new Pen(c_mainOutline);
    g.DrawRectangle(p, mainBar);
}

This method only draws the main frame of seekBar.

2. createTracker

C#
private void createTracker(Graphics g, int Xloc)
{
    Point[] points = {
	new Point(mainBar.X + Xloc, mainBar.Y -  3),
	new Point(mainBar.X + Xloc + SEEK_WIDTH, mainBar.Y + (mainBar.Height/2)),
	new Point(mainBar.X + Xloc, mainBar.Y + mainBar.Height + 3),
	new Point(mainBar.X + Xloc - SEEK_WIDTH, mainBar.Y + (mainBar.Height /2))
                             };
    Point[] outerPoints = {
	new Point(mainBar.X + Xloc, mainBar.Y -  3),
	new Point(mainBar.X + Xloc + SEEK_WIDTH + 1, mainBar.Y + (mainBar.Height/2)),
	new Point(mainBar.X + Xloc, mainBar.Y + mainBar.Height + 3),
	new Point(mainBar.X + Xloc - SEEK_WIDTH - 1, mainBar.Y + (mainBar.Height /2))
                             };
    LinearGradientBrush lgb =
    new LinearGradientBrush(new Point(mainBar.X + Xloc, mainBar.Y - 3),
	new Point(mainBar.X + Xloc, mainBar.Y + mainBar.Height + 3),
	c_seekerColorOne, c_seekerColorTwo);

    g.FillPolygon(lgb, points);

    Pen p = new Pen(c_seekerOutline, 1.0f);
    g.DrawPolygon(p, outerPoints);
}

This method creates a diamond shape that is used as a marker.

3. createFill

C#
private void createFill(Graphics g, int width)
{
    fillBar = new System.Drawing.Rectangle(mainBar.X + 1,
    	mainBar.Y + 1, width, ((mainBar.Height - 1) / 2));
    fillBarTwo = new System.Drawing.Rectangle(mainBar.X + 1,
    mainBar.Y + ((mainBar.Height - 1) / 2), width, ((mainBar.Height) / 2) + 1);
    backgroundBar = new System.Drawing.Rectangle(mainBar.X + 1,
    	mainBar.Y + 1, mainBar.Width - 1, mainBar.Height - 1);
    topLimiter = new System.Drawing.Rectangle
    	(mainBar.X, mainBar.Y - 9, mainBar.Width + 1, 7);
    leftLimiter = new System.Drawing.Rectangle
    	(mainBar.X + leftLimiterLocation, mainBar.Y - 10, 5, 9);

    if (rightLimiterLocation > 0)
    {
        rightLimiter = new System.Drawing.Rectangle(mainBar.Right -
        (mainBar.Right - rightLimiterLocation), mainBar.Y - 10, 5, 9);
    }
    else
    {
        rightLimiter = new System.Drawing.Rectangle
	(mainBar.Right, mainBar.Y - 10, 5, 9);
    }

    LinearGradientBrush lb = new LinearGradientBrush(new Point(0, 0),
    new Point(0, fillBar.Height), c_fillBarOne, c_fillBarTwo);
    LinearGradientBrush lbTwo = new LinearGradientBrush(new Point(0, 0),
    new Point(0, fillBar.Height + 2), c_fillBarTwo, c_fillBarOne);

    SolidBrush b = new SolidBrush(c_backgroundFill);

    g.FillRectangle(b, backgroundBar);
    g.FillRectangle(lb, fillBar);
    g.FillRectangle(lbTwo, fillBarTwo);
    b.Color = c_topLimiterBackground;
    g.FillRectangle(b, topLimiter);
    g.DrawRectangle(new Pen(System.Drawing.Color.Black), topLimiter);
    g.DrawLine(new Pen(c_topLimiterForeground, 6),
    	new Point(leftLimiter.X, leftLimiter.Y + 5),
    	new Point(rightLimiter.X, rightLimiter.Y + 5));
    b.Color = System.Drawing.Color.Gray;
    g.FillRectangle(b, leftLimiter);
    g.FillRectangle(b, rightLimiter);
    g.DrawRectangle(new Pen(System.Drawing.Color.Black), leftLimiter);
    g.DrawRectangle(new Pen(System.Drawing.Color.Black), rightLimiter);

    if (drawRightInfoText)
    {
        System.Drawing.Font fnt = new System.Drawing.Font
        	("Verdana", 6, System.Drawing.FontStyle.Bold);
        b.Color = System.Drawing.Color.Black;
        g.DrawString(rightLimiterText, fnt, b,
        	new Point(rightLimiter.X + 7, rightLimiter.Y - 9));
    }
    if (drawLeftInfoText)
    {
        System.Drawing.Font fnt = new System.Drawing.Font
        	("Verdana", 6, System.Drawing.FontStyle.Bold);
        b.Color = System.Drawing.Color.Black;
        g.DrawString(leftLimiterText, fnt, b,
        	new Point(leftLimiter.X + 7, leftLimiter.Y - 9));
    }
} 

This method basically creates everything else, background of main frame, the fill bar, top bar where limiters are located, limiter squares...

So in total, these three methods are the core parts of the control. They create the control and draw it during its lifetime using the variables that change according to the position of the diamond, size of the control, etc.

One of the main parts of the control are mouse events. They are called whenever the mouse is clicked inside the controls' space to check if the user has clicked on the diamond shape and if the mouse moves and user has not raised button, the dragging of diamond occurs.

C#
private void checkRegion(Point p)
{
    if (m_leftButtonDown)
    {
        Xlocation = p.X - 7;

        if (m_leftButtonDown && !m_leftButtonDownAndMoving)
        {
            if (p.X < mainBar.Left || p.X > mainBar.Right)
            {
                return;
            }
        }
        else if (m_leftButtonDownAndMoving)
        {
            if (p.X < mainBar.Left)
            {
                Xlocation = 0;
            }
            else if (p.X >= mainBar.Right)
            {
                Xlocation = mainBar.Right - 5;
            }
        }
        else
        {
            return;
        }

        calculatePercentage();
        calculateDivisions();
        this.Invalidate();

        if (ValueChanged != null)
        {
            ValueChanged(this, new ValueChangedEventArgs(seekValue));
        }
    }

This method checks if the mouse is in region when the button is down. If it is, it changes parameter Xlocation that has an influence on the diamond's position, and also calls some other methods just to make additional calculations. This will be more clear when you go through the code.

This same method is repeated for the left and the right limiters, as I saw basically they are three track bars so the code is the same.

The rest of the methods are the ones that do the calculation of seeking value. Those use rather basic math that I am sure you are going to catch as soon as you look at the control code.

Everything else is code blocks that handle coloring of different parts of the control, some that handle different value aspects, as in current value, value of left and right limiters setting and getting them.

I tried to be as brief as I could. I did not say anything about events, diamond mark and also left and right limiter trigger events when moved (ValueChanged events).

As I was rather brief in this article, I will be more than happy to answer any questions that may arise.

Thank you for your patience.

History

  • 24th April, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Founder TripleClaim Game Collective
Bosnia and Herzegovina Bosnia and Herzegovina
CEO and Co-Founder of TripleClaim Game Collective http://www.tripleclaim.com

Comments and Discussions

 
QuestionDisable Limiters Pin
Member 118964365-Jun-16 9:00
Member 118964365-Jun-16 9:00 
AnswerRe: Disable Limiters Pin
Dejan Omasta5-Jun-16 9:12
Dejan Omasta5-Jun-16 9:12 
GeneralRe: Disable Limiters Pin
Member 118964367-Jun-16 7:15
Member 118964367-Jun-16 7:15 
Thanks for your reply.
After looking through your code, I was able to recreate my own minimal seekbar in just 20 to 25 lines of code.
Thanks again
QuestionIts Not working for vb.net Axmediaplayer Component Pin
Sanjaya Harasana5-Feb-13 23:25
Sanjaya Harasana5-Feb-13 23:25 

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

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