Recent

Author Topic: Graphical List / Draw List  (Read 2326 times)

TRon

  • Hero Member
  • *****
  • Posts: 3930
Re: Graphical List / Draw List
« Reply #15 on: October 25, 2024, 07:22:30 am »
As I understood @TRon is that the virtual mode just means the component doesn't store any cell/list data.
True, but you still would need to retrieve the data somehow. That is what the ondatahint, ondata and onfinddata events are for when property OwnerData of the listview is set to true (also known as virtual mode).

But.... depending on your situation you could probably also do without (just checked and as long as the index from the item matches with an index to your list of ports you should be good to go)

Quote
As said, drawing worked all right, the issue with ListView "only" was that I couldn't set the height of the rows. Neither individually nor one height for all rows.
I am going to suggest something completely illogical here (it works for me tm )

I placed a listview on a form of a new project (e.g. no other events or properties set), added the formcreate event using the object inspector and added the following code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   // create connections list and add items to it (intentionally left blank)
  4.  
  5.   // create imagelist
  6.   ImageList := TImageList.Create(Self);
  7.   ImageList.Width  := 1;
  8.   ImageList.Height := 64; // <- more or less the height in pixels of your item (it actually has a few more pixels to separate the items)
  9.  
  10.   // prepare listview
  11.   ListView1.SmallImages := ImageList;
  12.   ListView1.Columns.Add;
  13.   ListView1.ViewStyle := vsList;
  14.  
  15.   // use ownerdraw
  16.   ListView1.OnCustomDrawItem:= @ListView1CustomDrawItem;
  17.   // the illogical: _DON'T_ set OwnerDraw
  18.   //  ListView1.OwnerDraw  := true;
  19.  
  20.   // fire up the engine (because not knowing how you store/obtain the data I took my own example)
  21.   ListView1.Items.Count := Connections.Count; // Connections is a TFPGObjectList<TConnection> where each item contains the necessary information
  22. end;
  23.  

Then I manually added the ListView1CustomDrawItem implementation. For me that looked something like:

Code: Pascal  [Select][+][-]
  1.  
  2. procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView; Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
  3. var
  4.   ARect : TRect;
  5. begin
  6.   DefaultDraw := false;
  7.   ARect := Item.DisplayRect(drBounds);
  8.  
  9.   // actually draw the item (very dumb and naive)
  10.   case Connections[Item.Index].strings[0] of
  11.    'COM' :
  12.    begin
  13.      Sender.Canvas.TextOut(ARect.Left, ARect.Top + 12, 'COM');
  14.      Sender.Canvas.TextOut(ARect.Left + 48, ARect.Top, 'Serial port');
  15.      etc, etc.
  16.    end;
  17.    'TCP' :
  18.    begin
  19.      Sender.Canvas.TextOut(ARect.Left, ARect.Top + 12, 'TCP');
  20.      Sender.Canvas.TextOut(ARect.Left + 48, ARect.Top, 'IP/TCP Connection');
  21.      etc, etc.
  22.    end;
  23.    'UDP' :
  24.    begin
  25.      Sender.Canvas.TextOut(ARect.Left, ARect.Top + 12, 'UDP');
  26.      Sender.Canvas.TextOut(ARect.Left + 48, ARect.Top, 'IP/UDP Connection');
  27.      etc, etc.
  28.    end;
  29.   end;
  30. end;
  31.  

edit: picture is of a more progressed doodle using a listview
« Last Edit: October 25, 2024, 01:25:03 pm by TRon »
I do not have to remember anything anymore thanks to total-recall.

kupferstecher

  • Hero Member
  • *****
  • Posts: 603
Re: Graphical List / Draw List
« Reply #16 on: October 26, 2024, 01:03:36 am »
Thanks for the example! So the key part is the ImageList with the height, I think. I'm not sure yet, if I want to go with such a hack. I hoped there is a better way to define the height. But if it works...

True, but you still would need to retrieve the data somehow. That is what the ondatahint, ondata and onfinddata events are for when property OwnerData of the listview is set to true (also known as virtual mode).
OnData and so on I don't understand, yet. My way would have been to organise the data in a list on my own and use it in OnCustomDrawItem just like you did in the example. Perhaps OnData is needed for sorting or similar things? (In my current use case I won't need any sorting).

Thanks again, the screenshot is nice!

TRon

  • Hero Member
  • *****
  • Posts: 3930
Re: Graphical List / Draw List
« Reply #17 on: October 26, 2024, 07:16:20 am »
Thanks for the example!
You're welcome.

Though, I did forgot do do something crucial in that example and that is to set the ownerdata to true (it was left out during copy-paste/cleanup).

Quote
So the key part is the ImageList with the height, I think.
You are correct.

The problem with classes that originate from (and now bound to) Windows is that all the Windows specific stuff can't be added by the LCL because the functionality might be missing for other backends.

This is one of them because Windows allows for a itemheight message to be send to the control that allows to set the height of/for an item. Adding a item or subitem that actually uses an icon with a specific width and height would usually (e.g. without using customdraw) draw that icon in the list and thus has to reserve the height and weight to be able to draw that icon. The code as shown was the quickest solution I was able to find that doesn't actually requires for the icon to be drawn but still reserves height and width (to be able to draw the icon, which is actually not drawn at all).

Quote
I'm not sure yet, if I want to go with such a hack. I hoped there is a better way to define the height. But if it works...
If you do not like such a workaround (I can imagine) then forget using any component that originates from windows and go the custom-drawn route. Though having said that, I tried to make sense out of the TCDListView component but am completely clueless as to me that component seems unfinished ?).

There might be better solutions out there as also suggested by others.

Personally I never managed to have found a list that is able to contain (a virtual amount of) custom data (it always seems to boil down to some sort of tree) except for one and that was for databases (Delphi came shipped with a panel that could be used to placed other components on top and a list that contained as many of these panels that where visible and which replicated the panel with all it contained components (and the contents of these components could be mapped to underlying database fields)). I believe it was simply named TDBPanelList (or something to that extend).

Quote
OnData and so on I don't understand, yet. My way would have been to organise the data in a list on my own and use it in OnCustomDrawItem just like you did in the example. Perhaps OnData is needed for sorting or similar things? (In my current use case I won't need any sorting).
That is why I said you probably are able to get away without using them. It is a bit complicated to implement because you 'virtually' fill a listitem with all the data that you want to have displayed and doing so by retrieving the data form your list. Using the methods allows for the data to be obtained 'on the fly' and customized any which way you want.

The example (indeed) simply maps the index from the listitem to the index of the list that contains all the data, and in our example that works perfectly. There are many circumstances in which this is not possible and you actually have to obtain the data 'on the fly'.

Quote
Thanks again, the screenshot is nice!
You're most welcome and even though I am not sure if this trick works for every widgetset (please do try and test) feell free to ask more in case you have questions.

fwiw: I am still looking for an example that properly shows how to use the ondataXXX events (as there doesn't even seem to be an example anywhere in the source-tree nor the wiki) but I'm afraid the best I would be able to come up with is the documentation from (old) Delphi that explained these kind of things into details.
« Last Edit: October 26, 2024, 07:20:59 am by TRon »
I do not have to remember anything anymore thanks to total-recall.

wp

  • Hero Member
  • *****
  • Posts: 12585
Re: Graphical List / Draw List
« Reply #18 on: October 26, 2024, 10:56:19 am »
I am still looking for an example that properly shows how to use the ondataXXX events
Here is an example showing a Listview in virtual mode using the OnData event

 

TinyPortal © 2005-2018