Placing a TProgressBar into a TListView
来源:互联网 发布:年月日时与五行算法 编辑:程序博客网 时间:2024/05/11 04:17
Here's how to add a progress bar (or any other Delphi component) to a ListView control. Plus: full source code to the TListViewEx component (TListView descendant) with ColumnResize events!
DOWNLOAD: • Sample Project
• TListViewEx with Source
Join the Discussion "Post your views, comments, questions and doubts to this article."
Discuss!
Related Resources • ProgressBar in StatusBar
• Building custom components
• Using VCL components
• Free Source components
Most download managers use a list view type of component to provide visual feedback of the amount of remaining download per item. Delphi's TListView component displays a list of items in various ways.
A TProgressBar displays a simple progress bar. Progress bars provide users with visual feedback about the progress of a procedure within an application.
Here's how to place a progress bar into a column of a list view box...
ProgressBar in ListView
When the ViewStyle property of a ListView control is set to vsReport, each item appears on its own line with information arranged in columns. The leftmost column contains the small icon and label, and subsequent columns contain subitems as specified by the application.
You are probably looking at this every day ... when using Windows Explorer in Details view.
Suppose you have a ListView on a form with ViewStyle set to vsReport. Two columns are defined using the Columns property: the first column holds the name of the item, the second column should store a progress indicator.
When the "AddItem" button is clicked a new item should be added to the list with a progress bar:
procedure TForm1.AddItemButtonClick( Sender: TObject);const pbColumnIndex = 1; pbMax = 100;var li : TListItem; lv : TListView; pb : TProgressBar; pbRect : TRect;begin lv := ListViewEx1; //create new ListItem (for the lv) li := lv.Items.Add; li.Caption := 'Item ' + IntToStr(lv.Items.Count); //create a ProgressBar, place it in the second column pb := TProgressBar.Create(nil); pb.Parent := lv; li.Data := pb; pbRect := li.DisplayRect(drBounds); pbRect.Left := pbRect.Left + lv.Columns[-1 + pbColumnIndex].Width; pbRect.Right := pbRect.Left + lv.Columns[pbColumnIndex].Width; pb.BoundsRect := pbRect;end; //AddItemButtonClick
When the AddItemButton is clicked a new list item (TListItem) is added to the ListView control (named ListViewEx1). A progress bar is created, a reference to the progress bar is added into the Data property of the list item, and finally, progress bar is placed in the column specified by the pbColumnIndex. Some calculations are used to make the progress bar appear at the right place.
When you want to remove an item from the list, you need to make sure the "attached" progress bar's memory is freed, and all the progress bars below the selected one are moved one position to the top (as this is what happens to all the remaining items of a ListView):
procedure TForm1.RemoveItemButtonClick( Sender: TObject);var lv : TListView; li : TListItem; i, idx : integer; pb : TProgressBar;begin lv := ListViewEx1; li := lv.Selected; if li <> nil then begin idx := li.Index; TProgressBar(li.Data).Free; lv.Items.Delete(idx); //move bars up for i := idx to -1 + lv.Items.Count do begin li := lv.Items.Item[i]; pb := TProgressBar(li.Data); pb.Top := pb.Top - (pb.BoundsRect.Bottom - pb.BoundsRect.Top); end; end;end; //RemoveItemButtonClick
Just for testing, we'll add some dummy code inside a TTimer's OnTime event to have some progress in bars (drop a TTimer component on a form, and use the next code for the OnTime event). Obviously, in real applications you would update the progress bar of an item based on some criteria - you only need to locate "its" progress bar ("stored" in the Data property of an item):
procedure TForm1.Timer1Timer( Sender: TObject);var idx : integer; pb: TProgressbar; lv : TListView;begin lv := ListViewEx1; if lv.Items.Count = 0 then Exit; //randomly pick an item and //increment it's progress position idx := Random(lv.Items.Count); pb := TProgressBar(lv.Items[idx].Data); if pb.Position < pb.Max then pb.StepIt else pb.Position := 0;end;//Timer1Timer
Run the appication, hit the "AddItem" button several times, and watch the progress going on :)
Now, try to resize any of the columns ... :( uuoopps!
When you resize the columns you need to reposition the progress bars, but TListView does not provide any event to handle resizing of columns!
TListViewEx - ListView with column resize events
You solution to handling the "column resizing" situation is in using a TListView derived control: TListViewEx. The TListViewEx is a TListView descendant with BeginColumnResize, ColumnResize and EndColumnResize events published.
I've located the source to TListViewEx control somewhere on news:borland.*. The code was provided by Peter Below (a TeamB member).
Now, with the power of TListViewEx, you can easily handle the user_is_resizing_columns situation. Here's how to handle the OnEndColumnResize event to adjust the width and left bounds of the progress bars:
procedure TForm1.ListViewEx1EndColumnResize( sender: TCustomListView; columnIndex, columnWidth: Integer);var lv : TListViewEx; idx : integer; pb : TProgressBar;begin lv := ListViewEx1; //first column if columnIndex = 0 then begin for idx := 0 to -1 + lv.Items.Count do begin pb := TProgressBar(lv.Items[idx].Data); pb.Left := columnWidth; end; end; //progress bar column if columnIndex = 1 then begin for idx := 0 to -1 + lv.Items.Count do begin pb := TProgressBar(lv.Items[idx].Data); pb.Width := columnWidth; end; end;end;
TListViewEx - Source
First, download the component. The TListViewEx comes as a single unit file (.pas extension). You'll need to add the component into an existing package. Here's "How to Install Custom Component in Delphi (into Existing Package)"
Questions? Comments? Extensions? Exceptions?!
That's it. As always if there are any questions or comments please post them on the Delphi Programming Forum.
- Placing a TProgressBar into a TListView
- Placing a TProgressBar into a TStatusBar
- JTAPI Placing a Telephone Call
- Placing Global Variables in a Register
- A Crash into VPN
- Reading a File into a Byte Array
- Turn a graph into a selector?
- Storing Images into a Database
- Migrating a Database into ASM
- (codes)a program convert a dec into a hex
- 简易沙箱原理 ——Placing Restrictions on a Job's Processes
- Inkscape Tutorial Effects: Placing an Image Inside a Shape – Part 2
- Put it into a Context!(写作中)
- convert an int into a byte array
- Put it into a Context!(写作中)
- Put it into a Context!(写作中)
- Put it into a Context!(写作中)
- Put it into a Context!(写作中)
- Placing a TProgressBar into a TStatusBar
- 区别CALL SCREEN/SET SCREEN/LEAVE TO SCREEN
- 真的好想你们!
- pragma指令简介
- DataGridView取出当前行中的值
- Placing a TProgressBar into a TListView
- C++笔记——c++编程思想(下)第二三四章防御性编程及输入输出流
- 关于Visual C++ 的ATL.MFC.CLR对比
- 各位认为现在Windows 2008能进入实用阶段了么?
- 使用SQL Server维护计划实现数据库定时自动备份
- C++笔记——c++编程思想(下)通用算法和运行时类型识别
- Flex给服务器端传送对象
- 找到一款不错的网站压力测试工具webbench
- TRANSLATE