PDA

Click to See Complete Forum and Search --> : Basic Progress Bar Control


Mxjerrett
Jun 10th, 2008, 01:20 AM
EDIT:
Ok guys, the next version has been released and is available from the same download link as before. I am looking for an actual name to call this rather than just progress bar. So go ahead and feed them to me. :)
END EDIT

I whipped this up late last night, so it isn't perfect. I am sure there are many ways to shorten the code and I bet it can be made better, but for now I'll leave it as is. I am going to add the ability to change the font of the percentage, but that will come later.

I've never even so much as drawn with an API before so this was completely new to me. Also I've never made a usercontrol, but this was some good experience.


Version: 1.0.1

Features:
Able to set the background color (using 2 colors)
Able to set the fill color (using 2 colors)
Able to enable, disable gradients
Able to change font color
Able to disable percentage
Able to add a drop shadow
Able to set border color
Min and Max values.

Update Log:

'||||||||||||||||||||||||||||||||||||||||||||||||
'| UPDATE LOG |
'| times are all central time (GMT -6) |
'| |
'| June 8, 2008 - 11:30PM |
'| - Work Begins |
'| |
'| June 10, 2008 - 11:10PM |
'| - stream-lined code |
'| removed many unnecessary |
'| calculations and calls. |
'| - added Min and Max value |
'| |
'||||||||||||||||||||||||||||||||||||||||||||||||

Benchmark Tests

Tested at 10000 loops
Microsoft Common Controls: 812ms
ProgressBar Control V 1.0.0: 5250ms | 84.5% less efficient at 10000 loops
ProgressBar Control V 1.0.1: 4688ms | 82.7% less efficient at 10000 loops



Pictures:
http://img517.imageshack.us/img517/9996/progressbarsstv5.jpg

Merri
Jun 10th, 2008, 08:55 AM
Back in the days I also started off by making a progress bar control as my first usercontrol. It was also one of the first things that got me interested on the speed side of things, because I noticed a progress bar could sometimes slow down a loop by a great deal. The progress bar in the Common Controls OCX is a great example of this.

Some of mine if you want to take a peek: 1.8 (http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=41267&lngWId=1) and 2.0 (http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=48153&lngWId=1)

si_the_geek
Jun 10th, 2008, 10:10 AM
That looks like an impressive first attempt. :thumb:

There are a few things that slow it down, mainly due to repeating work.

A good example of this is the Red/Green/Blue functions, which each repeat the code to fill strHexColour. As they are all used only once, by the same routine, what you could do is put them all into that routine (and thus only have the strHexColour code once).. you could also remove the need for strings (which are slow), and find the values using maths instead (for an example, see the "Convert colour number to colour name" link in my signature, lines 9 to 12).

There are several other examples in the Redraw routine (which is run frequently, thus has a big effect), such as repeated calls to the RGB function with the same parameters (when you could call it once, and store the result to a variable), and repeating things like UserControl.ScaleHeight / 2 (which again could be stored - and could even be moved to the Resize event). Also the .Right property of Rectangles(2) and (3) does not need to be calculated each time, only when the .Value changes, or the control is resized.


I haven't checked Merri's versions, but suspect you could get more ideas from them.

Mxjerrett
Jun 10th, 2008, 04:18 PM
Hmm thanks for the tips SI. I'll correct them now. Also I am going to make a couple modifications to allow for min and max values. Do you know how to change the font when you use drawtext?

si_the_geek
Jun 10th, 2008, 04:42 PM
I can't remember how you change the font, as I don't tend to use API's for text (I normally use Me.Print instead). A forum search should find examples tho.

Merri
Jun 10th, 2008, 06:22 PM
You can find extensive tips for DrawText by taking a look into UniLabel control I've created. In the other hand the control is also very complex as it includes all the features that are related to labels, but atleast you should get a hint on how to handle fonts. It has a procedure Private_SetFont that changes the current font in use. UserControl_Terminate removes the font. Private_WndProcContainer and Private_WndProcUserControl both have WM_PAINT messages that handle drawing the text. From there you can see that I change the font while I'm drawing, but also restore the original font right after I've drawn.

With progress bar you can simplify things quite a bit, but there is enough stuff that I'm not collecting it nicely into one code block example :P (Working on yet another Unicode control atm.)

You can find UniLabel in UniControls thread (http://www.vbforums.com/showthread.php?p=3084062#post3084062).

Mxjerrett
Jun 11th, 2008, 01:57 AM
Hey guys I made some updates, tell me what you think now? Better or worse?

si_the_geek
Jun 11th, 2008, 04:33 AM
I can't run it at the moment unfortunately, but the code looks better. :thumb:

Did you use a compiled version to test the speed? It can make a big difference.

Mxjerrett
Jun 11th, 2008, 11:52 AM
hmm, no I just used the control, but I'll compile and test it now.

Merri
Jun 11th, 2008, 01:39 PM
You need a bit more error checking, if I just add it to the form and run without setting anything, I get an immediate divizion by zero:

PercentWidth = IIf(m_Value > m_MinVal, UserControl.ScaleWidth - (((UserControl.ScaleWidth / m_MaxVal)) * (m_MaxVal - Value + m_MinVal)) - 1, 1)

The problem here is that you're using IIf, which is really one of the worst implementations in VB. It is a simple and super slow function, so all parameters you give it will be executed. A regular If works much better :)

You also want to give default values for Min and Max in InitProperties.


When control is added to the form:

Initialize -> InitProperties -> Show

In any other case:

Initialize -> ReadProperties -> Show

Mxjerrett
Jun 11th, 2008, 01:47 PM
Hmm, I did exactly what you just said, and I didn't get any problem.

Also I already have:
m_MinVal = m_def_MinVal
m_MaxVal = m_def_MaxVal
m_Value = m_def_Value

Under InitProperties

Merri
Jun 11th, 2008, 02:00 PM
Here is exactly what I do to get the error:
Download the control, I let it open up directly to VB.
I add a form.
I insert the progress bar to the form.
I resize the progress bar.
I hit run.
VB complains that there is no startup form. I put it in place.
I get the divizion by zero error.

Mxjerrett
Jun 11th, 2008, 02:33 PM
I tried and I could not reproduce the error sorry.

si_the_geek
Jun 11th, 2008, 03:38 PM
I couldn't either.. but would still recommend changing IIF to a regular IF, and not just in this situation.

An IIF is not only slow, but is also prone to the kind of errors Merri got. This is because it always calculates both the True and False results, whereas a normal If only calculates what is needed.

Mxjerrett
Jun 11th, 2008, 03:42 PM
I did fix it, and on my next version it will be part of it.