snoopy_Spy
asked on
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)
ASKER
But how can i get the x and y - positions of the progress bar ? (for example column 3 and row 6 )
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.RepositionProgressB ar(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].Positio n;
//Work out the row height
RowHeight := ListView1.Items[1].Positio n.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].Wi dth);
//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].Widt h;
rc.Bottom := rc.Top + RowHeight;
ProgressBar1.BoundsRect := rc;
end;
Cheers,
Phil.
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.RepositionProgressB
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].Positio
//Work out the row height
RowHeight := ListView1.Items[1].Positio
//Work out the left edge of the specified column
ColLeft := 0;
for Index := 0 to Col - 1 do
Inc(ColLeft, ListView1.Column[Index].Wi
//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].Widt
rc.Bottom := rc.Top + RowHeight;
ProgressBar1.BoundsRect := rc;
end;
Cheers,
Phil.
BTW, it needs to have at least two items in the list view (otherwise it can't workout the rowheight).
Cheers,
Phil.
Cheers,
Phil.
Hey snoopy,
Have you had a chance to try this out?
Cheers,
Phil.
Have you had a chance to try this out?
Cheers,
Phil.
ASKER
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 !
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 !
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.
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.
ASKER
What do you mean with the lParam (address of an NMHDR) ?
What is a NMHDR ?
What is a NMHDR ?
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.Han dle) then
Good luck,
Phil.
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.Han
Good luck,
Phil.
ASKER
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 !
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 !
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.
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.
ASKER
Ups ...
thanxs
Post an answer !
thanxs
Post an answer !
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
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.
ASKER
Thanxs
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(Canva
Cheers,
Phil.