Subclassing the ListIconGadget: Questions

Just starting out? Need help? Post your questions and find answers here.
DARKGirl
User
User
Posts: 61
Joined: Wed Nov 10, 2004 10:32 pm

Subclassing the ListIconGadget: Questions

Post by DARKGirl »

Hello everyone. It seems that I can't seem be in the IRC channel when someone is actually in there to get some answers so I thought I would ask here. I am attempting to take over the ListIconGadget and make it into something more. I will call it a ListPropertyGadget, because in the end I wish to make this a standalone dll for other people to use. I tire of opening a visual designer and throwing a GUI together that takes up more space than it should so here is my idea:

Image

When it is inactive (not clicked on) the gadget looks just like any old ListIconGadget, but when you click on a cell to the right, a gadget (depending on what type you chose when you set it up) appears over it so you can edit the values just like that. When you leave focus, it will update itself in the actual gadget. The extra gadgets that you see are just for show, and does not actually reflect how the entire thing should look.

My questions are:

1. How does one change the height/width of the cell so that when a gadget pops up over it, it is seamless.

2. How does one tell which cell is selected? This is important if I am to make the correct gadget appear over the right cell when it is supposed to.

3. I do have some questions about turning this entire project into a standalone dll, but that will come later. I want to get the thing working first before I do any of that.

Thanks for the help!

DG :)
Last edited by DARKGirl on Sun Jan 07, 2007 2:33 am, edited 5 times in total.
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