Thanks for your insight. I obviously have a lot to learn still. I used DrawEdge instead of DrawFrameControl because it allows customizing of the border style. The RGB values were used to draw the border color and a etched look when the control was disabled. I could have used hex values instead of RGB function, but I dont always think about those things. The sunken text is based on a TLabel and my prefered "disabled" look; however, I'm using DrawState function to do that now.
----- Original Message ----- From: "Rob Kennedy" <[EMAIL PROTECTED]> To: "Delphi-Talk Discussion List" <delphi-talk@elists.org> Sent: Sunday, December 18, 2005 1:10 PM Subject: Re: custom progress bar > Richard R wrote: >> Hello. I recently made a custom progress bar, but it's kinda slow and I >> figure I'd need to use assembly to speed it up. Even if assembly is used >> i'm >> not sure if it'd do any good, what slows it down is the drawing of the >> progress bar and the caption on it. During the increment phase, it has to >> redraw all the graphics on the control. I had to turn on double buffering >> to >> reduce flicker. > > That's because the Repaint function invalidates the entire control > before painting it. A better way to go would be to use the setter for > the Position property to determine how much of the control actually > needs to be repainted. Then use InvalidateRect to invalidate only that > portion. When the window next needs repainting, the OS will only accept > commands that modify that small portion -- it silently ignores commands > that affect areas outside the window's update region. To tell the window > to paint itself, use update instead of Repaint. Update won't do anything > if the current update region is still empty. > >> I did a bench mark with a TProgressBar and my >> TtsxProgressBar and the timing ratio is 2:27 / 2:43 so mine was 16 >> seconds >> slower, at other tests it would be over a minute slower. But I think the >> trade off is having a visual on the progress bar which works very well >> for >> my project (the user can turn it off). Do you have any suggestions on how >> I >> can increase performance? In my SetPos and StepIt code I call Repaint >> after >> i do the calculation. > > At the very most, your control should only call Invalidate, not Repaint. > Repaint forces the control to repaint everything, even if the program > was just about to set the Position property to something else right > away. Let the application be in charge of when its forms get painted. > >> Here is my Paint code. the Gradient function DrawImage paints a gradient >> effect if turned on. It's rather fast since it uses math but I havnt >> noticed >> any performance degrade between turning gradient on and off. >> >> procedure TtsxProgressBar.Paint; >> var >> cx, cy, p: integer; >> r: TRect; >> t: string; >> begin >> Inherited Paint; > > Does the painting code below leave any part of the window unpainted? If > not, then you don't need the inherited call since you're just going to > paint over everything anyway. > >> with Canvas do begin >> // draw outer border >> Pen.Color:= RGB(150, 107, 48); > > What are these magic numbers for the color? > > If you're trying to draw a sunken 3D border, you can call the > DrawFrameControl API function. It will automatically use the system's > configured highlight and shadow colors. You can then skip all the > line-drawing routines below. > >> MoveTo(0, Height - 2); >> LineTo(0, 0); >> LineTo(Width - 2, 0); >> Pen.Color:= RGB(245, 241, 224); >> MoveTo(Width - 1, 0); > > You leave one pixel uncolored. The LineTo function does not paint the > last pixel in the range. Why? Because it's leaving it for the next > LineTo call to handle. > > If you want to paint the inside border of a rectangle, then the > coordinates to use are (0,0), (Width-1,0), (Width-1,Height-1), > (0,Height-1). > >> LineTo(Width - 1, Height - 1); >> LineTo(0, Height - 1); >> // draw progress >> p:= 0; > > What's p? > >> r.Left:= 3; >> r.Top:= 2; >> r.Right:= Width - 3; >> r.Bottom:= Height - 3; >> case FOrientation of >> pbHorizontal: >> p:= Round((FPos - FMin) / (FMax - FMin) * (r.Right - r.Left) + >> r.Left); >> pbVertical: >> p:= Round((FPos - FMax) / (FMin - FMax) * (r.Bottom - r.Top) + >> r.Top); >> end; >> if Gradient.Apply then >> Gradient.DrawImage(Canvas, r) > > Since r is a rectangle based on the size of the control, r will not > change unless the entire control is resized. Since the gradient is > always drawn in the full dimensions of the control, you can just draw > the gradient once to a bitmap of your own. Then, when it comes time to > paint the control, just use Canvas.Draw to copy that bitmap to the > canvas instead of recalculating the gradient image each time. > > You can calculate r and the gradient bitmap in your control's Resize > method. You can also update it in the property setter for > Gradient.Apply, so when the property is False, you just paint an > FPColor-colored rectangle into your bitmap. > >> else begin >> Brush.Color:= FPColor; >> FillRect(r); >> end; >> case FOrientation of >> pbHorizontal: r.Left:= p; >> pbVertical: r.Bottom:= p; >> end; >> Brush.Color:= Self.Color; >> FillRect(r); > > According to this, it appears as though you draw the entire "progress" > portion of the control, and then you "unpaint" the part that shouldn't > have been painted at all. > >> // draw caption >> t:= Caption; >> if FShowValue then >> t:= t + ' : ' + Format('%d / %d', [FPos, FMax]); > > Include the " : " part of the string in your format string. There's no > use having a Format call *and* two string concatenations. > > t := t + Format(' : %d / %d', [FPos, FMax]); > >> Brush.Style:= bsClear; >> cx:= Width div 2 - TextWidth(t) div 2; >> cy:= Height div 2 - TextHeight(t) div 2; > > The TextWidth and TextHeight functions both call the TextSize function > internally, which returns both the height and the width of the given > text. If you use that function directly, you can cut the work in half. > > Better yet, you can use the DrawText API function. It can draw text that > is horizontally and vertically centered in a given rectangle, so you > don't need to do any calculations yourself. > >> if (not Enabled) then begin >> Font.Color:= RGB(245, 241, 244); > > More magic numbers for the colors? > > Is disabled text still drawn sunken these days? > >> cx:= cx + 1; >> cy:= cy + 1; >> end >> else >> Font.Color:= Self.Font.Color; >> TextOut(cx, cy, t); >> if (not Enabled) then begin >> cx:= cx - 1; >> cy:= cy - 1; >> Font.Color:= RGB(150, 107, 48); >> TextOut(cx, cy, t); >> end; >> Brush.Style:= bsSolid; >> end; >> end; > > > -- > Rob > __________________________________________________ > Delphi-Talk mailing list -> Delphi-Talk@elists.org > http://www.elists.org/mailman/listinfo/delphi-talk > __________________________________________________ Delphi-Talk mailing list -> Delphi-Talk@elists.org http://www.elists.org/mailman/listinfo/delphi-talk