Subclassing the ListIconGadget: Questions

Just starting out? Need help? Post your questions and find answers here.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Hi,

I had to contend with these issues whilst writing the egrid control and they are far from trivial! :) Placing the controls is one thing, keeping them positioned whilst the user scrolls the list icon or drags columns or resizes a column is an entirely different matter!

Anyhow, I'll see if I can shed any light.

First thing to say is that these controls you wish to embed within the ListIcon should be made child's of the listicon. I'd say don't waste your time tyring to position controls which are not child controls of the list icon, this is asking for trouble!

1) Once the list icon has been created, it is not necessarily a good idea to change the row height. Is it not a better idea, when creating the child control, to size this accordingly - i.e. make it fit the dimensions of the cell which the user has clicked?

2)

Code: Select all

#LVM_SUBITEMHITTEST = #LVM_FIRST+57 

If OpenWindow(0, 100, 100, 300, 100, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   If CreateGadgetList(WindowID(0))
     ListIconGadget(0, 5, 5, 290, 90, "Name", 100, #PB_ListIcon_AlwaysShowSelection)
     AddGadgetColumn(0, 1, "Address", 250)
     AddGadgetItem(0, -1, "Harry Rannit"+Chr(10)+"12 Parliament Way, Battle Street, By the Bay")
     AddGadgetItem(0, -1, "Ginger Brokeit"+Chr(10)+"130 PureBasic Road, BigTown, CodeCity")
     Repeat
       Event = WaitWindowEvent()
        If event=#WM_LBUTTONDOWN
          Define PInfo.LVHITTESTINFO
          GetCursorPos_(rc.POINT)
          MapWindowPoints_(0, GadgetID(0),rc,1)
          PInfo\pt\x = rc\x
          PInfo\pt\y = rc\y 
          SendMessage_(GadgetID(0), #LVM_SUBITEMHITTEST, 0, PInfo) 
          Debug "("+Str(PInfo\iItem)+", "+Str(PInfo\iSubitem)+")"
        EndIf
     Until Event = #PB_Event_CloseWindow
   EndIf
 EndIf
I found early on in the development of egrid that the zero column of the underlying listicon could throw a spanner in the works. Just try the above code and click any non-text part of a cell in column 0 to see what I mean. For this reason (amongst many), I always blanked out the zero column, i.e. set it's width to zero. Of course this depends on your requirements whether you should follow suit.

Aligning the controls to exactly fit the cell in question is a royal pain in the a***! To avoid massive flicker you need to account for gridlines (if any are present?)
It seems that your program will need to place a child control when the user clicks a cell, i.e. the control is removed as soon as focus moves to another cell. This means that only one of each type of supported control needs to be created, which I think is the best way. In itself this is fine, except if you wish to align the text in the control perfectly with the text in the underlying cell. This took me days to get this right (but then I did have to account for the text justification etc.)

The following post might prove useful:

http://www.purebasic.fr/english/viewtop ... s+listicon

I'm not sure if all this helps.
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

To place your child controls on the ListIcon gadget, you need to know the location and size of the clicked item, right? At least that's what I took from your post. Here's an example that takes srod's work just a bit further so that you obtain those values so you can place your child. Note that I'm in agreement with srod on Column 0 (I hate it) so I'm factoring it the hell out of the example:

Code: Select all

#LVM_SUBITEMHITTEST = #LVM_FIRST + 57 
#LVM_GETSUBITEMRECT = #LVM_FIRST + 56

Global oldproc

Procedure SubClass_LV(hwnd, msg, wparam, lparam) 
  result = CallWindowProc_(oldproc, hwnd, msg, wparam, lparam) 
  If msg = #WM_RBUTTONDOWN or msg = #WM_LBUTTONDOWN
    GetCursorPos_(@cp.POINT)
    MapWindowPoints_(0,hwnd,@cp,1)
    HitInfo.LVHITTESTINFO 
    Hitinfo\pt\x = cp\x
    HitInfo\pt\y = cp\y
    SendMessage_(hwnd,#LVM_SUBITEMHITTEST ,0,@HitInfo)
    If hitinfo\isubitem > 0 And HitInfo\iItem >= 0
      RtlZeroMemory_(@itemrect.RECT,SizeOf(RECT))
      itemrect\top = hitinfo\iSubItem
      SendMessage_(hwnd,#LVM_GETSUBITEMRECT, hitinfo\iitem, @itemrect)
      Debug ""
      Debug "Item Left: " + Str(itemrect\left)
      Debug "Item Top: " + Str(itemrect\top)
      Debug "Item Width: " + Str(itemrect\right-itemrect\left)
      Debug "Item Height: " + Str(itemrect\bottom-itemrect\top)
    EndIf
  EndIf 
  ProcedureReturn result 
EndProcedure 

If OpenWindow(0, 100, 100, 400, 200, "ListIcon Example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
   If CreateGadgetList(WindowID(0)) 
     ListIconGadget(0, 5, 5, 355, 200, "", 0, #PB_ListIcon_AlwaysShowSelection) 
     oldproc = SetWindowLong_(GadgetID(0), #GWL_WNDPROC, @SubClass_LV())
     
     AddGadgetColumn(0, 1, "Name", 100)
     AddGadgetColumn(0, 2, "Address", 250) 
     AddGadgetItem(0, -1, Chr(10)+"Harry Rannit"+Chr(10)+"12 Parliament Way, Battle Street, By the Bay") 
     AddGadgetItem(0, -1, Chr(10)+"Ginger Brokeit"+Chr(10)+"130 PureBasic Road, BigTown, CodeCity") 
     AddGadgetItem(0, -1, Chr(10)+"srod Ateit"+Chr(10)+"34 API Road, BigTown, CodeCity")      
     AddGadgetItem(0, -1, Chr(10)+"fangbeast Drankit"+Chr(10)+"144 EasyStreet, BigTown, CodeCity")      
     Repeat 
       Event = WaitWindowEvent() 

     Until Event = #PB_Event_CloseWindow 
   EndIf 
 EndIf 
BERESHEIT
DARKGirl
User
User
Posts: 61
Joined: Wed Nov 10, 2004 10:32 pm

Post by DARKGirl »

well Srod, I first want to thank you for the lovely code snipplets that I shall add to my own, but unfortunately, the gadgets that I want to use have a minimum size, and cannot be sized to fit the listicongadget, therefore, I must size the cells to the minimul size of the gadget
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Sample provided, moved to Tips & Tricks:

http://www.purebasic.fr/english/viewtop ... 712#176712
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Nice example Netmaestro. :) I always tend to steer away from ownerdrawn methods with list view controls because of the requirement to paint all subitems in one go etc. but that is a very slick example.

@Darkgirl: If you're talking about different heights for different rows then I don't think it is possible as List View controls do not have a #LVS_OWNERDRAWVARIABLE style (unlike list box controls).

If you're talking about altering the height of all rows together then you either need to use the #LVS_OWNERDRAWFIXED style as Netmaestro's example shows (but which involves you taking charge of drawing all items within the control), or you adopt a 'dirty' little trick involving imagelists which allows you to alter the height of all rows dynamically and at any time. I can post an example if you wish. This latter method does not require custom draw or owner draw etc.
I may look like a mule, but I'm not a complete ass.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4789
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Post by Fangbeast »

"AddGadgetItem(0, -1, Chr(10)+"Harry Rannit"

Blimey, seems like years since I worked on the PureBasic docs (because it is) and I recognise that bit.

"AddGadgetItem(0, -1, Chr(10)+"fangbeast Drankit"+Chr(10)+"

If it's soy milk with milo and fresh hamsters, I probably did!!!
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
Post Reply