ProgressBar in ListView

How can i (the easiest way) show a Progress bar (like the TProgressBar) in a Column of a ListView (with Re-Moving and Re-Sizeing)
snoopy_SpyAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

philipleighsCommented:
Hi,

The easiest way would be to position a progress bar over the top of the listview's column.
Change the position/column at run time.

....but the approach I would take is:

Create a descendant of TListView. Inside, create a contained progressbar. Override the Paint method, implement the function with a call to inherited, then FProgressBar.PaintTo(Canvas, X, Y);

Cheers,
Phil.
0
snoopy_SpyAuthor Commented:
But how can i get the x and y - positions of the progress bar ? (for example column 3 and row 6 )
0
philipleighsCommented:
Hi again,

Try this. Make sure that Col and Row are not outside your range, or you'll get a range error.
Also, it assumes that the ListView is in vsReport mode.
ShowColumnHeaders can be true or false.

procedure TForm1.RepositionProgressBar(Col, Row: Integer);
var pt: TPoint;
    RowHeight: Integer;
    ColLeft: Integer;
    Index: Integer;
    rc: TRect;
  begin
    //Work out the top left position of the first list item
    pt := ListView1.Items[0].Position;

    //Work out the row height
    RowHeight := ListView1.Items[1].Position.Y - pt.Y;

    //Work out the left edge of the specified column
    ColLeft := 0;
    for Index := 0 to Col - 1 do
      Inc(ColLeft, ListView1.Column[Index].Width);

    //Build the bounding rectangle, and reposition the progress bar
    rc.Left := ListView1.Left + ColLeft + pt.X;
    rc.Top := ListView1.Top + RowHeight * Row + pt.Y;
    rc.Right := rc.Left + ListView1.Column[Col].Width;
    rc.Bottom := rc.Top + RowHeight;
    ProgressBar1.BoundsRect := rc;
  end;

Cheers,
Phil.
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

philipleighsCommented:
BTW, it needs to have at least two items in the list view (otherwise it can't workout the rowheight).

Cheers,
Phil.
0
philipleighsCommented:
Hey snoopy,

Have you had a chance to try this out?

Cheers,
Phil.
0
snoopy_SpyAuthor Commented:
I have 2 problems with your solution :
1.) I can't change the Background auf the TProgressBar to the Background of the Listview (not so important)
but 2.)
I can't write a event where i can change the position and size of the ProgressBar when i move or resize the column !
0
philipleighsCommented:
The parent form gets a WM_NOTIFY while a column's width is changing.

Each time your form gets a WMNotify message, look at the idCtrl parameter (wParam).

If it equals the handle of the listview, then recalculate the bounds of the progress bar. (you could narrow down the number of times you check by examining the contents of lParam (address of an NMHDR).

If the rectangle is different from the progress bar's position, then use BoundsRect to change it.

Hmm, I don't know about the background of the progress bar.

Cheers,
Phil.
0
snoopy_SpyAuthor Commented:
What do you mean with the lParam (address of an NMHDR) ?
What is a NMHDR ?
0
philipleighsCommented:
It's a windows type. It is described in the Win32 API help. TWMNotify exposes it so you don't have to do any typecasting.

Basically, declare a message handler in the form.

TForm1 = class(TForm)
....
protected
  procedure WMNotify(var Msg: TWMNotify); message WM_NOTIFY;

....

implementation

....

procedure TForm1.WMNotify(var Msg: TWMNotify);
begin
  inherited;
  if Msg.idCtrl = ListView1.Handle then
    if Msg.NMHdr.code = xxxx {some magic number} then
      begin
        ResizeProgressBar;
      end;
end;


if you omit this line:
    if Msg.NMHdr.code = xxxx {some magic number} then

you'll resize the progress bar everytime something happens to the listview which would be overkill. My guess is that NMHdr.code will contain a particular value when you resize a column. Work out that value and hard code it.

I haven't actually done this, but it's an approach that I'd take.

One other thing, this line:
  if Msg.idCtrl = ListView1.Handle then

might need to be changed to:
  if Msg.idCtrl = GetDlgCtrlID(ListView1.Handle) then

Good luck,
Phil.
0
snoopy_SpyAuthor Commented:
I have tried this :
procedure TForm1.WMNotify(var Msg: TWMNotify);
begin
    inherited;
    if Msg.idCtrl = ListView1.Handle then
        Edit2.Text := 'YES'
    else Edit2.Text := 'NO';

But i only get YES when i click the column header or on a item not when i change the column width !
0
philipleighsCommented:
Hmm, when I looked in Spy++ it showed me that WM_NOTIFY was being sent repeatedly when the mouse was down and moving over the column.

BTW, how you you know that it is only sent when you click? You could be setting Edit2.Text to 'YES' 50 times.

A method I use for this kind of thing is:

if Msg.idCtrl = ListView1.Handle then
begin
  Caption := Caption + 'x';
  if Length(Caption) > 50 then
    Caption := '';
end;

That way it is more obvious when a message has come through.
0
snoopy_SpyAuthor Commented:
Ups ...

thanxs

Post an answer !
0
philipleighsCommented:
Great! I'm glad you got it working.

Cheers,
Phil.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
philipleighsCommented:
BTW, you can change the background colour of the ProgressBar by putting it inside a panel. ProgressBar uses the background colour of it's parent.

So drop a TPanel on your form, set Color to clWindow, and Visible to false.
Now cut and paste the ProgressBar into the TPanel!

Cheers,
Phil.
0
snoopy_SpyAuthor Commented:
Thanxs
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.