How can I numbering items in ListView (vsReport)? Now I have something like that:
Item := ListView1.Items.Add;
Item.Caption :=inttostr(Item.Index+1);
but it only works if items are not sorted. If I sort everything is mixed.
Whenever the list is sorted you need to loop through the items and update the caption.
for i := 0 to ListView1.Items.Count-1 do
ListView1.Items[i].Caption := IntToStr(i+1);
Personally I would switch to using the list view in virtual mode which makes adding an index column trivial. As you have it at present you need to work hard to keep the list's contents in sync with the underlying data. With a virtual list view that problem dissolves.
Try moving the logic of numbering to a procedure, and call this method after of sort the listview.
try this sample
procedure SetNumbering(ListView : TListView);
var
i : integer;
begin
ListView.Items.BeginUpdate;
try
for i := 0 to ListView.Items.Count-1 do
ListView.Items.Item[i].Caption:=IntToStr(i+1);
finally
ListView.Items.EndUpdate;
end;
end;
I would take an approach more like doing some custom drawing. About 1/4 of the time I ever use list controls, I wind up using its custom drawing capabilities to accommodate for things like this. Refer to This Article which goes into some detail on how to accomplish custom drawing. You can check the index of the item as it's being drawn, and draw your number to the left of each item. I can put together a sample if you would like, but it is quite a bit of coding to do. But not only do you accomplish the numbering you want, but you can also do many other things like implement your own styles, draw images, draw other controls, etc.
Related
I'm currently trying to create a combobox that has a "caption". By caption I mean the text that you see when you haven't clicked on it yet or if you are choosing an option.
Before I added the csExDropDownList it worked fine, but I wanted it to be ReadOnly. Now when I edit the Text property, it instantly gets deleted. I thought about using a TLabel in front of the combobox and making it dissapear the moment I chose a dropdown, but the TLabel is always in the background. I also tried with the TStaticText component, but that leaves a different colored background in front of the combobox which looks bad.
If I was unable to explain with words what I'm trying to edit/wanted to add a text to, this is what I mean:
I've found a workaround to my problem. I added a third dropdown with the index of 0. Now in properties I put the ItemIndex to 0 which means that it will be displayed similar to the Text property. When I interact with either QuickSort or InsertSort I delete Index 0.
My code looks like this:
procedure TSorterForm.AlgorithmCbxChange(Sender: TObject);
begin
if (AlgorithmCbx.Text <> 'Choose Algorithm...') and not IsAlgorithmSelected then begin
AlgorithmCbx.Items.Delete(0);
IsAlgorithmSelected:= true;
end;
end;
Obviously not perfect so it'd be great if you could tell me how to improve this.
I'm doing a mobile application with Delphi Seattle 10, and emerged me a doubt in the style of the ListView.
When a Listview is empty, it looks like this,without filling all horizontal separators lines, like this :
and I wonder if its possible, I dont know, changing the style in some way so that it could look like this:
It's posible?
Each seperator line will be added when you add a new TListViewItem. If you really want to make this, you can do it only one way. That is:
Creating a TListViewItem
var
aItem: TListViewItem;
Adding an action to your TForm which including TListView like onCreate
for I:= 0 to 10 do
begin
aItem := TListView1.Items.Add;
aItem.Text := '';
end;
This is just a little trick. Or maybe you should try to use Canvas but I don't suggest you to use Canvas for this.
I've got a TListView to which I may add anything from none to several hundred items depending on the day the user has selected from the log file. I use this code to prevent unnecessary refreshes:
listEvents.Items.BeginUpdate();
listEvents.Items.Clear();
// Add events
listEvents.Items.EndUpdate();
Even so, on my fast development PC I can see a few fast flickers of the list. On the (much slower) production PCs, the flicker is noticeable and rather ugly. My question is there any way to count the number of refreshes to the TListView by hooking into an event? I could then increment a variable and display the value of the variable on a label while I debug this. I tried the TListView::OnDrawItem event but that wasn't called at all.
I suspect you are not using the virtual listview. Use the virtual listview approach to display data. Set OwnerData property to true and handle your display in OnData event. That should prevent the flicker. Pseudo code for this would be:
procedure TForm1.ListView1Data(Sender: TObject; Item: TListItem);
begin
Item.Caption := FloatToStr(Item.Index + 1);
Item.SubItems.Add('Your data here');
end;
Try something like this to avoid flicker:
// Disable
SendMessage(listEvents.Handle, WM_SETREDRAW, Integer(False), 0);
try
listEvents.Items.BeginUpdate();
listEvents.Items.Clear();
// Add events
listEvents.Items.EndUpdate();
finally
// enable
SendMessage(listEvents.Handle, WM_SETREDRAW, Integer(True), 0);
end;
You may no longer be necessary to use BeginUpdate and EndUpdate.
Regards.
I have a TListView (actually, a custom descendant) display in ViewStyle vsReport. One row is selected. I would like to get the screen coordinates of that row (or a cell within that row). Is there any way for me to do this?
(My goal is to display a small form over the list view giving the effect that it dropped down from the selected row).
I am using Delphi 2010 for this particular application.
For a list view in vsReport style I believe the best approach is to use the LVM_GETITEMRECT and LVM_GETSUBITEMRECT messages.
The VCL does not wrap this functionality up for you but it should not be too difficult to work it out from the MSDN docs.
Whilst it is very simple to use the TListItem.Position property exposed by the VCL, as far as I can tell this does not help you obtain the row height or indeed the coordinates of sub items.
Update
As NGLN very helpfully points out, the CommCtrl unit does expose ListView_GetItemRect and ListView_GetSubItemRect which are more convenient to use than the equivalent Windows messages above.
var
sel: TListItem;
pnt: TPoint;
begin
sel := ListView1.Selected;
if not Assigned(sel) then Exit;
pnt := ListView1.ClientToScreen(Sel.Position);
In Delphi 2010, I need to display a grid that has a horizontal scroll bar with about 15 columns x 5 rows.
I chose to use a StringGrid.
However, while the mouse button is down dragging the horizontal scroll bar, I want the grid to scroll live.
The StringGrid component, it appears, does not scroll live. It waits until the mouse button is released before updating the column and scrolling if necessary.
Also, the horizontal scroll bar button (is that what it's called) is not proportional to the number of columns. And for a down-arrow when on the bottom row to move to the top of the next column to the right...
These seem like common needs, so I was surprised not to find them in TStringGrid.
Any suggestions on a way around these two problems? I can use a DbGrid or other standard component, but my preference is to not use a commercial grid if I can avoid it. And I'm not going to use shareware or freeware...
TIA
For the first question, you can set goThumbTracking in the StringGrid's Options at design-time, or at run-time: StringGrid1.Options := StringGrid1.Options + [goThumbTracking];
For the third question, you can provide the functionality you need by using keyboard event handlers of the control. An example;
procedure TForm1.StringGrid1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
StringGrid: TStringGrid;
begin
StringGrid := Sender as TStringGrid;
case Key of
VK_DOWN:
if StringGrid.Row = StringGrid.RowCount - 1 then begin
Key := 0;
StringGrid.Row := StringGrid.FixedRows;
if StringGrid.Col = StringGrid.ColCount - 1 then
StringGrid.Col := StringGrid.FixedCols
else
StringGrid.Col := StringGrid.Col + 1;
end;
VK_UP: //...;
VK_RIGHT: //;
VK_LEFT: //;
end;
end;
For the second question, the scrolling code seems to be buried in private methods of TCustomGrid. I have no clue how to achieve that..
If noticed you are not interested in third party components - Freeware, I am not fond of these either, but we all must make sacrifices sometimes if we want to get the problems solved. This is one of these sacrifices! This component is to good to be ignored. You will not create something like it yourself if you don't have a couple of years of free time.
Either write a new component based on TStringGrid (I would not - it is not the best tool in the box to begin with)
But take some time and learn TVirtualStringTree. The component is years ahead of TStrignGrid. The source is available and there are many who uses it.
And there are events already implemented to react on scrollbar changes
OnScroll, OnShowScrollbar
http://www.delphi-gems.com/index.php?option=com_content&task=view&id=12&Itemid=38
Search on stackoverflow and you can read much more about tvirtualstringtree
Second the suggestion to use TVirtualStringTree. Working with the TStringGrid component is like stabbing yourself in the belly with a rusty scissor.