Button in List View

Just starting out? Need help? Post your questions and find answers here.
michaeled314
Enthusiast
Enthusiast
Posts: 340
Joined: Tue Apr 24, 2007 11:14 pm

Button in List View

Post by michaeled314 »

In my application I want to create a button in one column of the list icon gadget (Win API treats it like a list view when in report mode)... It is an image button. However, I am not able to do this, even with research... Can anybody help... I am in detailed view (report style set)... Any Win API suggestions

- Michael
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Button in List View

Post by netmaestro »

This task, while certainly doable, is not exactly trivial. You must solve for the case where columns are moved or resized and it is advisable to employ a method of controlling the line height of your ListIcon to accomodate image sizes. At the "standard" height, by the time you get button edges in there, there's only a handful of pixels left for your image height. Height is managed here with ownerdraw. Also, resizing of the column containing the button should be disallowed.

Disclaimer: Fair warning, this code is venturing into unsupported Purebasic territory; Overlapping gadgets are not supported at all in Purebasic. This code works fine on 4.60 RC1 but there is no guarantee that the team won't change the way ListIcon events and/or drawing get handled in the future and throw a monkey wrench into this.

Code: Select all


Procedure MainWindowCallBack(hwnd, msg, wparam, lparam) 
  result = #PB_ProcessPureBasicEvents 
  
  Select msg 
    Case #WM_DRAWITEM 
      *lpdis.DRAWITEMSTRUCT = lparam 
      Dim itemrect.RECT(3) 
      For i = 1 To 3 
        FillMemory(@itemrect(i),SizeOf(RECT)) 
        itemrect(i)\top = i 
        SendMessage_(*lpdis\hwndItem, #LVM_GETSUBITEMRECT, *lpdis\itemid, @itemrect(i)) 
        text$ = GetGadgetItemText(GetDlgCtrlID_(*lpdis\hwndItem), *lpdis\itemid, i) 
        SelectObject_(*lpdis\hDC, GetStockObject_(#NULL_PEN)) 
        WhiteBrush = CreateSolidBrush_(#White) 
        SelectObject_(*lpdis\hDC, WhiteBrush) 
        Rectangle_(*lpdis\hDC, itemrect(i)\left+4, itemrect(i)\top+4, itemrect(i)\right, itemrect(i)\bottom) 
        TextOut_(*lpdis\hDC, itemrect(i)\left+4, itemrect(i)\top+4, text$, Len(text$)) 
        DeleteObject_(WhiteBrush) 
      Next 
      
    Case #WM_MEASUREITEM 
      *lpmis.MEASUREITEMSTRUCT = lparam 
      *lpmis\itemheight = 20 
      
  EndSelect 
  
  ProcedureReturn result 
  
EndProcedure 

Procedure Reposition_Buttons()
  Static firstcall = #True
  Static topline=0
  
  If firstcall
    header = SendMessage_(GadgetID(0), #LVM_GETHEADER,0,0)
    SendMessage_(header, #HDM_GETITEMRECT, 0, @hr.RECT)
    topline   = hr\bottom
    firstcall = #False
  EndIf
  
  For i=1 To 3
    FillMemory(itemrect.RECT, SizeOf(RECT))
    itemrect\top = 3
    itemrect\left = #LVIR_BOUNDS
    SendMessage_(GadgetID(0), #LVM_GETSUBITEMRECT, i-1, @itemrect.RECT) 
    If itemrect\top >= topline
      ResizeGadget(i, itemrect\left+1, itemrect\top+1, #PB_Ignore, #PB_Ignore)
      HideGadget(i,0)
    Else
      HideGadget(i,1)
    EndIf
  Next
EndProcedure

Procedure SubClass_LV(hwnd, msg, wparam, lparam) 
  
  oldproc = GetProp_(hwnd, "oldproc")
  
  Select msg
    Case #WM_NCDESTROY
      RemoveProp_(hwnd, "oldproc")
      
    Case #WM_HSCROLL, #WM_VSCROLL
      Reposition_Buttons()
      
    Case #WM_NOTIFY 
      *nmHEADER.HD_NOTIFY = lParam 
      Select *nmHEADER\hdr\code 
        Case #HDN_ITEMCHANGINGA, #HDN_ITEMCHANGINGW
          If *nmHEADER\iItem=3
            SetCursor_(LoadCursor_(0, #IDC_NO))
            ProcedureReturn #True
          EndIf
          Reposition_Buttons()
      EndSelect
      
  EndSelect 
  
  ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)  
  
EndProcedure 

OpenWindow(0,0,0,320,240,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) 
SetWindowCallback(@MainWindowCallBack()) 

ListIconGadget(0,0,0,320,240,"",0,#LVS_OWNERDRAWFIXED|#PB_ListIcon_GridLines) 
SetWindowLong_(GadgetID(0),#GWL_STYLE,GetWindowLong_(GadgetID(0),#GWL_STYLE)|#WS_CLIPCHILDREN)
SetProp_(GadgetID(0), "oldproc", SetWindowLong_(GadgetID(0), #GWL_WNDPROC, @SubClass_LV()))

AddGadgetColumn(0,1,"Column 1",100) 
AddGadgetColumn(0,2,"Column 2",100) 
AddGadgetColumn(0,3,"Column 3",90) 
AddGadgetItem(0, -1, Chr(10) + "Line 0 Col 1" + Chr(10) +  "Line 0  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 1 Col 1" + Chr(10) +  "Line 1  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 2 Col 1" + Chr(10) +  "Line 2  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 3 Col 1" + Chr(10) +  "Line 3  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 4 Col 1" + Chr(10) +  "Line 4  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 5 Col 1" + Chr(10) +  "Line 5  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 6 Col 1" + Chr(10) +  "Line 6  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 7 Col 1" + Chr(10) +  "Line 7  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 8 Col 1" + Chr(10) +  "Line 8  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 9 Col 1" + Chr(10) +  "Line 9  Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 10 Col 1" + Chr(10) + "Line 10 Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 11 Col 1" + Chr(10) + "Line 11 Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 12 Col 1" + Chr(10) + "Line 12 Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 13 Col 1" + Chr(10) + "Line 13 Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 14 Col 1" + Chr(10) + "Line 14 Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 15 Col 1" + Chr(10) + "Line 15 Col 2" + Chr(10) ) 
AddGadgetItem(0, -1, Chr(10) + "Line 16 Col 1" + Chr(10) + "Line 16 Col 2" + Chr(10) ) 

CreateImage(0, 80,12)
StartDrawing(ImageOutput(0))
  Box(0,0,80,16,#Red)
StopDrawing()

UseGadgetList(GadgetID(0))
For i=1 To 3
  FillMemory(itemrect.RECT, SizeOf(RECT))
  itemrect\top = 3
  itemrect\left = #LVIR_BOUNDS
  SendMessage_(GadgetID(0),#LVM_GETSUBITEMRECT, i-1, @itemrect) 
  ResizeImage(0, itemrect\right-itemrect\left, itemrect\bottom-itemrect\top)
  ContainerGadget(i, itemrect\left+1, itemrect\top+1, itemrect\right-itemrect\left-2, itemrect\bottom-itemrect\top-2) 
  ButtonImageGadget(i+3, 0,0, itemrect\right-itemrect\left-2, itemrect\bottom-itemrect\top-2, ImageID(0))
  CloseGadgetList()
Next
UseGadgetList(WindowID(0))

Repeat 
  EventID = WaitWindowEvent() 
  Select EventID 
    Case #PB_Event_Gadget 
      Select GadgetType(EventGadget())
        Case #PB_GadgetType_ButtonImage
          Debug "Button "+Str(EventGadget())+" pressed"
      EndSelect 
  EndSelect 
Until EventID = #WM_CLOSE 
Last edited by netmaestro on Sat Oct 08, 2011 3:30 pm, edited 2 times in total.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Button in List View

Post by srod »

Nice. I'd probably hide the buttons when vertical scrolling though else the header gets in the way. :)
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Button in List View

Post by netmaestro »

Thanks srod! There is always something I didn't think of. Very great to have you here again backstopping me :mrgreen:

Code edited with the fix.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: Button in List View

Post by srod »

:D
I may look like a mule, but I'm not a complete ass.
Psych
Enthusiast
Enthusiast
Posts: 239
Joined: Thu Dec 18, 2008 3:35 pm
Location: Wales, UK

Re: Button in List View

Post by Psych »

Nice code indeed.

I did notice the list doesnt update properly on scroll track, drag the slider down 1 and the list moves but the buttons remain. Shouldnt take too much to sort that out though.

This is also a solution to putting progressbars in columns too :)
----------------------------------------------------------------------------
Commenting your own code is admitting you don't understand it.
----------------------------------------------------------------------------
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Button in List View

Post by netmaestro »

This is because of line-by-line scrolling, nothing will change it.
BERESHEIT
michaeled314
Enthusiast
Enthusiast
Posts: 340
Joined: Tue Apr 24, 2007 11:14 pm

Re: Button in List View

Post by michaeled314 »

Thanks for the code

As you can see in the Tips and Tricks section, I like to make my list icon report view columns non resizable
This makes it much easier


- Michael
User avatar
electrochrisso
Addict
Addict
Posts: 989
Joined: Mon May 14, 2007 2:13 am
Location: Darling River

Re: Button in List View

Post by electrochrisso »

8) NM, So it is best to use your code for fixed sized grid stuff then. :?:
PureBasic! Purely the best 8)
Post Reply