Page 1 of 1

Right-click on a ComboBoxGadget

Posted: Sun Sep 14, 2025 10:27 pm
by RobertRioja
I hope someone can answer this. If I click on a ComboBoxGadget, its list will drop down so I can click on any item. That will trigger the #PB_EventType_Change event. However, I need to right-click on an item and I don't see a way of capturing that event.

Any ideas?

Thanks,
Rob

Re: Right-click on a ComboBoxGadget

Posted: Mon Sep 15, 2025 1:45 pm
by Axolotl
Which OS?

On windows maybe by doing the following:
1. Get the ListBox handle (GetComboBoxInfo),
2. subclass it (SetWindowSubclass)
3. look at WM_RBUTTONDOWN and LB_ITEMFROMPOINT

Re: Right-click on a ComboBoxGadget

Posted: Mon Sep 15, 2025 2:32 pm
by Axolotl
Here is an example of right-click on the dropdown-listbox ..... (Windows Only)

Code: Select all

EnableExplicit 

Import "Comctl32.lib"  ;{ <<< from (latest) Comctl32.dll  >>>
  ; use the PureBasic Syntax (Windows API procedures using trailing underscore) 
  ; 
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    SetWindowSubclass_(hWnd, *fnSubclass, uIdSubclass, dwRefData)  As "SetWindowSubclass" 
    GetWindowSubclass_(hWnd, *fnSubclass, uIdSubclass, *dwRefData) As "GetWindowSubclass"
    RemoveWindowSubclass_(hWnd, *fnSubclass, uIdSubclass)          As "RemoveWindowSubclass"
    DefSubclassProc_(hWnd, uMsg, wParam, lParam)                   As "DefSubclassProc"
  CompilerElse
    SetWindowSubclass_(hWnd, *fnSubclass, uIdSubclass, dwRefData)  As "_SetWindowSubclass@16" 
    GetWindowSubclass_(hWnd, *fnSubclass, uIdSubclass, *dwRefData) As "_GetWindowSubclass@16"
    RemoveWindowSubclass_(hWnd, *fnSubclass, uIdSubclass)          As "_RemoveWindowSubclass@12"
    DefSubclassProc_(hWnd, uMsg, wParam, lParam)                   As "_DefSubclassProc@16" 
  CompilerEndIf
EndImport 

; for simplicity's sake, constants (enums are even better)  
#WND_Main = 1 
#GDT_cbbTest = 2 

Structure COMBOBOXINFO 
  cbSize.l        ; DWORD 
  rcItem.RECT     ; RECT  
  rcButton.RECT   ; RECT  
  stateButton.l   ; DWORD 
  hwndCombo.i     ; HWND  
  hwndItem.i      ; HWND  
  hwndList.i      ; HWND  
EndStructure 

#LB_ITEMFROMPOINT = 425 

Procedure SubclassComboboxList(hWnd, uMsg, wParam, lParam, uIdSubclass, dwRefData) 
  Protected index, pt.POINT 

  Select uMsg 
    Case #WM_NCDESTROY                                                         : Debug "WM_NCDESTROY" 
      RemoveWindowSubclass_(hWnd, @SubclassComboboxList(), uIdSubclass) 

    Case #WM_LBUTTONDOWN                                                       : Debug "WM_LBUTTONDOWN" 

    Case #WM_RBUTTONDOWN                                                       : Debug "WM_RBUTTONDOWN" 
      GetCursorPos_(@pt) 
      ScreenToClient_(hWnd, @pt) 
      index = ((pt\y & $FFFF) << 16) + (pt\x + $FFFF) 
      index = SendMessage_(hWnd, #LB_ITEMFROMPOINT, 0, index) 
      If (index >> 16) & $FFFF  ; inside the listbox 
        index & $FFFF                                   : Debug "  index == " + index + "   outside " 
      Else 
        index & $FFFF                                   : Debug "  index == " + index + "   inside " 
      EndIf 

  EndSelect 
  ProcedureReturn DefSubclassProc_(hWnd, uMsg, wParam, lParam) 
EndProcedure

Procedure Main() 
  Protected ii, hList, cbi.COMBOBOXINFO 

  If OpenWindow(#WND_Main, 0, 0, 256, 200, "Something with Combobox ... ", #PB_Window_ScreenCentered|#PB_Window_SystemMenu) 
    StickyWindow(#WND_Main, 1) ; always on top :) 

    ComboBoxGadget(#GDT_cbbTest, 8, 8, 240, 24) 
      For ii = 1 To 9 
        AddGadgetItem(#GDT_cbbTest, -1, "Test Text Item "+ii) 
      Next 
      SetGadgetState(#GDT_cbbTest, 1) 


    cbi\cbSize = SizeOf(COMBOBOXINFO) 
    If GetComboBoxInfo_(GadgetID(#GDT_cbbTest), @cbi)
      hList = cbi\hwndList                                  : Debug "Combobox List hwnd == " + hList 
      SetWindowSubclass_(hList, @SubclassComboboxList(), #GDT_cbbTest, 0)  ; 
    EndIf 

    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow 
          Break ; say good bye. 
      EndSelect
    ForEver
  EndIf 
EndProcedure 

End Main() 

Re: Right-click on a ComboBoxGadget

Posted: Mon Sep 15, 2025 11:42 pm
by RobertRioja
Hello Axolotl,

Thank you very much. This is exactly what I needed.

Rob

Re: Right-click on a ComboBoxGadget

Posted: Tue Sep 16, 2025 3:05 am
by BarryG

Code: Select all

If OpenWindow(0, 0, 0, 270, 80, "ComboBoxGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  ComboBoxGadget(0, 10, 10, 250, 21)
  For a = 1 To 5
    AddGadgetItem(0, -1,"ComboBox item " + Str(a))
  Next
  
  Repeat
  
    ev=WaitWindowEvent()
    
    If ev=#WM_RBUTTONDOWN
      Debug "Right-clicked on "+Str(GetGadgetState(0))
    EndIf
    
  Until ev = #PB_Event_CloseWindow
  
EndIf

Re: Right-click on a ComboBoxGadget

Posted: Tue Sep 16, 2025 2:00 pm
by Axolotl
Works well, with one limitation: If the mouse is outside the list box when clicked, it is not recognized.