[Windows] Outsmart the ListIconGadget?

Just starting out? Need help? Post your questions and find answers here.
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

[Windows] Outsmart the ListIconGadget?

Post by Little John »

At least on Windows, the ListIconGadget shows some built-in behaviour when the user presses certain keys, see <https://www.purebasic.fr/english/viewtopic.php?t=86328>.
Does any of our experts know how to switch that behaviour off? In my current project, I want to implement my own “mechanism” for a ListIconGadget how to react on certain key presses.
User avatar
idle
Always Here
Always Here
Posts: 5835
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: [Windows] Outsmart the ListIconGadget?

Post by idle »

you might have to resort to a LL keyboard hook and eat the keys or perhaps it can be done via a subclass of the gadget and callback.

you can try this but maybe someone will come up with a subclass method

Code: Select all

Structure akey
  ks.a[256]
EndStructure 

Global keyhook, keys.akey,listicon 

#WH_MOUSE_LL = 14 

Procedure.i KeyProc(nCode.i,wParam.i,lParam.i)
  
  Protected *keyInput.KBDLLHOOKSTRUCT 
  
  Static pos,len  
  
  Protected ret.i, hwnd.i,beat.i 
        
  *keyInput = lParam 
  
  If nCode = #HC_ACTION 
    
    hwnd = GetActiveWindow_() 
    
    If hwnd = WindowID(0) 
      
      Select wParam  
          
        Case #WM_KEYUP 
          keys\ks[*keyInput\vkCode] = 0 
        Case #WM_KEYDOWN
          
          keys\ks[*keyInput\vkCode]= $fe
          
          If (GetAsyncKeyState_(#VK_SHIFT) & $8000)  
            keys\ks[#VK_SHIFT]=$fe
          Else 
            keys\ks[#VK_SHIFT]=0
          EndIf 
          
          If (GetAsyncKeyState_(#VK_CONTROL) & $8000)  
            keys\ks[#VK_CONTROL]=$fe
          Else 
            keys\ks[#VK_CONTROL]=0
          EndIf 
          
          If (GetAsyncKeyState_(#VK_LMENU) & $8000)  
            keys\ks[#VK_LMENU]=$fe
          Else
            keys\ks[#VK_LMENU]=0 
          EndIf 
          
          If (GetAsyncKeyState_(#VK_RMENU) & $8000)  
            keys\ks[#VK_RMENU]=$fe
          Else 
            keys\ks[#VK_RMENU]=0
          EndIf 
          
          If keys\ks[#VK_SHIFT] And keys\ks[#VK_A]    ;<-----------block the keys  
            Debug "blocked shift + A" 
            beat = 1 
          EndIf 
                   
      EndSelect
    EndIf 
  EndIf    
  
  If Not beat 
     ret = CallNextHookEx_(Keyhook, nCode, wParam, lParam) 
  Else 
     ret = 1 
  EndIf  
  
  ProcedureReturn ret
  
EndProcedure 

Procedure SetHooks()
  Protected hInstance = GetModuleHandle_(0)
  If hInstance 
    Keyhook = SetWindowsHookEx_(#WH_KEYBOARD_LL, @KeyProc(),hInstance,0) 
  Else 
    MessageRequester("hook", "can't get module handle")
  EndIf       
  
  If (Keyhook = 0)  
    MessageRequester("hook", "can't get module handle")
  EndIf       
  
EndProcedure 

Procedure KillHooks()
  UnhookWindowsHookEx_(Keyhook)
  KeyHook = 0  
EndProcedure  


If OpenWindow(0, 0, 0, 700, 300, "ListIconGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  SetHooks()
  
    ; left column
    TextGadget    (6,  10,  10, 330, 20, "ListIcon Standard", #PB_Text_Center)
    ListIconGadget(0,  10,  25, 330, 70, "Column 1", 100)
    TextGadget    (7,  10, 105, 330, 20, "ListIcon with Checkbox", #PB_Text_Center)
    ListIconGadget(1,  10, 120, 330, 70, "Column 1", 100, #PB_ListIcon_CheckBoxes)  ; ListIcon with checkbox
    TextGadget    (8,  10, 200, 330, 20, "ListIcon with Multi-Selection", #PB_Text_Center)
    ListIconGadget(2,  10, 215, 330, 70, "Column 1", 100, #PB_ListIcon_MultiSelect) ; ListIcon with multi-selection
    ; right column
    TextGadget    (9, 360,  10, 330, 20, "ListIcon with separator lines",#PB_Text_Center)
    ListIconGadget(3, 360,  25, 330, 70, "Column 1", 100, #PB_ListIcon_GridLines)
    TextGadget   (10, 360, 105, 330, 20, "ListIcon with FullRowSelect and AlwaysShowSelection",#PB_Text_Center)
    ListIconGadget(4, 360, 120, 330, 70, "Column 1", 100, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
    TextGadget   (11, 360, 200, 330, 20, "ListIcon Standard with large icons",#PB_Text_Center)
    ListIconGadget(5, 360, 220, 330, 65, "", 200,#PB_ListIcon_GridLines)
    For a = 0 To 4            ; add columns to each of the first 5 listicons
      For b = 2 To 4          ; add 3 more columns to each listicon
         AddGadgetColumn(a, b, "Column " + Str(b), 65)
      Next
      For b = 0 To 2          ; add 4 items to each line of the listicons
        AddGadgetItem(a, b, "Item 1"+Chr(10)+"Item 2"+Chr(10)+"Item 3"+Chr(10)+"Item 4")
      Next
    Next
    ; Here we change the ListIcon display to large icons and show an image
    If LoadImage(0, #PB_Compiler_Home+"examples/sources/Data/File.bmp")     ; change path/filename to your own 32x32 pixel image
      SetGadgetAttribute(5, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
      AddGadgetItem(5, 0, "Picture 1", ImageID(0))
      AddGadgetItem(5, 1, "Picture 2", ImageID(0))
    EndIf
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf
  
   KillHooks()
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: [Windows] Outsmart the ListIconGadget?

Post by Little John »

Many thanks, idle!
User avatar
idle
Always Here
Always Here
Posts: 5835
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: [Windows] Outsmart the ListIconGadget?

Post by idle »

Little John wrote: Tue Feb 18, 2025 10:16 pm Many thanks, idle!
better with subclass dug out of forum

EDited

Code: Select all

Global oldListIconCallback

Procedure SubclassedListIcon(hwnd, msg, wparam, lparam)
     
  Select msg
      
    Case #WM_KEYUP 
    Case #WM_KEYDOWN
      
     Debug  GetKeyState_(#VK_A) 
      
     If ((GetAsyncKeyState_(#VK_SHIFT) & $8000)  And GetKeyState_(#VK_A) > 1)
       Debug "blocked shift + A" 
       beat = 1  
     EndIf    
      
  EndSelect
   
  If Not beat 
    result = CallWindowProc_(oldListIconCallback, hwnd, msg, wparam, lparam)
  Else 
    result = 1 
  EndIf 
  
  ProcedureReturn result
EndProcedure

If OpenWindow(0, 100, 100, 415, 100, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0, 5, 5, 405, 80, "col 0", 50, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)

  oldListIconCallback = SetWindowLongPtr_(GadgetID(0), #GWL_WNDPROC, @SubclassedListIcon())
  For i = 1 To 10
    AddGadgetColumn(0, i, "col " + Str(i), 50)
  Next
  For b = 0 To 5
    AddGadgetItem(0, -1, "")
  Next
  For i = 0 To 5
    For j = 0 To 50
      SetGadgetItemText(0, i, Str(i + j), j)
    Next j
  Next i           
  
  Repeat
    EventID = WaitWindowEvent()
  Until EventID = #PB_Event_CloseWindow
 
EndIf
End 



RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: [Windows] Outsmart the ListIconGadget?

Post by RASHAD »

idle pointed to the right direction indeed but with his complicated mind :mrgreen:
Just simple task need simple and free mind like me

Subclassing any Keyboard action

Code: Select all

Global oldCallback

Procedure liconCB(hwnd, uMsg, wParam, lParam)
  Select uMsg
    Case #WM_CHAR                                        ;Char & Ctrl + Char
      Select wParam 
        Case 65,97,66,98
          ProcedureReturn 1
      EndSelect
      
    Case #WM_KEYDOWN                                      
      Debug "#KEYDOWN: " + Chr(wParam)
      
    Case #WM_KEYUP                                       ;F1.....F12
      Debug "#KEYUP:   " + Chr(wParam) 
      
    Case #WM_DEADCHAR 
      Debug "#DEADCHAR:   " + Chr(wParam)
      
    Case #WM_SYSCHAR                                      ;Alt + Char                                         
      Debug "#SYSCHAR:   " + Chr(wParam)  
      
    Case #WM_SYSKEYDOWN 
      Debug "#SYSKEYDOWN:   " + Chr(wParam) 
      
    Case #WM_SYSKEYUP 
      Debug "#SYSKEYUP:   " + Chr(wParam)             
  EndSelect   
  ProcedureReturn CallWindowProc_(oldCallback, hWnd, uMsg, wParam, lParam)
EndProcedure

If OpenWindow(0, 100, 100, 300, 130, "ListIcon demo", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) = 0
  MessageRequester("Fatal error", "Can't open main window.")
  End
EndIf

ListIconGadget(0, 5, 5, 280, 110, "Name", 100, #PB_ListIcon_FullRowSelect)
AddGadgetColumn(0, 1, "Address", 170)
AddGadgetItem(0, -1, "ax" + #LF$ + "Here")
AddGadgetItem(0, -1, "bx" + #LF$ + "There")
AddGadgetItem(0, -1, "ay" + #LF$ + "By the Bay")
AddGadgetItem(0, -1, "by" + #LF$ + "CodeCity")
SetActiveGadget(0)
SetGadgetState(0, 0)

oldCallback = SetWindowLongPtr_(GadgetID(0), #GWL_WNDPROC, @liconCB())

Repeat
  event = WaitWindowEvent()
Until event = #PB_Event_CloseWindow
Egypt my love
User avatar
idle
Always Here
Always Here
Posts: 5835
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: [Windows] Outsmart the ListIconGadget?

Post by idle »

RASHAD wrote: Wed Feb 19, 2025 12:47 am idle pointed to the right direction indeed but with his complicated mind :mrgreen:
Just simple task need simple and free mind like me
Subclassing any Keyboard action
You've got me there :lol:
Ever heard of a flustered post heap sort? That's complicated!
I first came across it Data Structures and Algorithms as demonstrated by the delightful Ms Post who dropped all her overheads on the floor, then proceeded to pick them up and sort them in place only to drop them on the floor again and so the algorithm was born flustered post heap sort!
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: [Windows] Outsmart the ListIconGadget?

Post by Axolotl »

If it comes to subclassing I like to recommend this. Subclassing Controls with ComCtl32.dll version 6 (win only)
BTW: Maybe AddKeyboardShortcut() will do as well (Just thought simple and not tested.)
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Little John
Addict
Addict
Posts: 4777
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: [Windows] Outsmart the ListIconGadget?

Post by Little John »

Yes, subclassing is more precisely tailored to this problem. The solution is simple if you know it. ;-) Thanks to idle and Rashad!
Also thanks to Axolotl for the link to interesting information about subclassing!
Post Reply