Capturing item selection in ComboBox gadgets

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Capturing item selection in ComboBox gadgets

Post by BackupUser »

Code updated for 5.20+

Restored from previous forum. Originally posted by El_Choni.

Hi,

UPDATE: modified for PB 3.20, added example with editable ComboBox gadget.

This solves a problem in PB which doesn't handle correctly ComboBox selection changing events:

Using editable ComboBox gadget:

Code: Select all

#MainWndFlags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget

#WindowWidth = 480

Global CB_hWnd.l, lpch.l

Procedure Error(errorstring.s)
  MessageRequester("Error", errorstring, #MB_ICONERROR)
  End
EndProcedure

Main_hWnd = OpenWindow(0, #CW_USEDEFAULT, #CW_USEDEFAULT, #WindowWidth, 110, "Editable ComboBox item selection event catching example:", #MainWndFlags)
If Main_hWnd
  CB_hWnd = ComboBoxGadget(0, 5, 5, #WindowWidth-10, 25, #PB_ComboBox_Editable)
  If CB_hWnd
    cchTextMax = 256
    lpch = AllocateMemory(cchTextMax)
    Dim item.s(7)
    item(0) = "Spaghetti"
    item(1) = "Great sole"
    item(2) = "Potato omelette"
    item(3) = "Fondue chinoise"
    item(4) = "Tapioca soup"
    item(5) = "Duck liver"
    item(6) = "Kebap"
    For i = 0 To 6
      AddGadgetItem(0, -1, item(i))
    Next i
    ButtonGadget(1, 5, 40, (#WindowWidth/2)-15, 32, "Add")
    TextGadget(2, (#WindowWidth/2)+5, 40, (#WindowWidth/2)-15, 32, "Capturing the item-selected event")
    
    Repeat
      EventID = WaitWindowEvent()
      
      Select EventID
        Case #PB_Event_Gadget
          EventGadgetID = EventGadget()
          Select EventGadgetID
            Case 0
              Select EventType()
                Case #PB_EventType_RightClick
                  MessageRequester("Selection changed to:", GetGadgetText(0), 0)
              EndSelect
            Case 1
              SendMessage_(CB_hWnd, #WM_GETTEXT, cchTextMax, lpch)
              AddGadgetItem(0, -1, PeekS(lpch))
          EndSelect
      EndSelect
      
    Until EventID = #PB_Event_CloseWindow
  Else
    Error("Could not create editable ComboBox gadget.")
  EndIf
Else
  Error("Could not open main window.")
EndIf

End
And using API editable ComboBox control:

Code: Select all

#EDITCOMBOBOX = #WS_CHILD|#WS_VISIBLE|#CBS_DROPDOWN|#CBS_AUTOHSCROLL|#WS_VSCROLL  ; for the combobox pull-down
#MainWndFlags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget

#WindowWidth = 480

Global CB_hWnd.l, lpch.l

Procedure Error(errorstring.s)
  MessageRequester("Error", errorstring, #MB_ICONERROR)
  End
EndProcedure

Procedure SelectCallback(WindowID, uMsg, wParam, lParam)
  result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_COMMAND
      wNotifyCode = wParam>>16
      wID = wParam & $ffff
      If wNotifyCode = #CBN_SELCHANGE And lParam = CB_hWnd And wID = 0
        SendMessage_(CB_hWnd, #CB_GETLBTEXT, SendMessage_(CB_hWnd, #CB_GETCURSEL, 0, 0), lpch)
        MessageRequester("Selection changed to:", PeekS(lpch), 0)
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure

hInstance = GetModuleHandle_(#Null)

Main_hWnd = OpenWindow(0, #CW_USEDEFAULT, #CW_USEDEFAULT, #WindowWidth, 110, "Editable ComboBox item selection event catching example:", #MainWndFlags)
If Main_hWnd
  CB_hWnd = CreateWindowEx_(#WS_EX_CLIENTEDGE, "COMBOBOX", "ComboBoxGadget", #EDITCOMBOBOX, 5, 5, #WindowWidth-10, 100, Main_hWnd, 0, hInstance, #Null)
  If CB_hWnd
    ; select Windows variable-pitch (proportional space) system font and  apply font to the combobox
    SendMessage_(CB_hWnd, #WM_SETFONT, GetStockObject_(#ANSI_VAR_FONT), #False)
    cchTextMax = 256
    lpch = AllocateMemory(cchTextMax)
    
    Dim item.s(7)
    item(0) = "Spaghetti"
    item(1) = "Great sole"
    item(2) = "Potato omelette"
    item(3) = "Fondue chinoise"
    item(4) = "Tapioca soup"
    item(5) = "Duck liver"
    item(6) = "Kebap"
    
    For i = 0 To 6
      SendMessage_(CB_hWnd, #CB_INSERTSTRING, -1, @item(i))
    Next i
    
    ButtonGadget(1, 5, 40, (#WindowWidth/2)-15, 32, "Add")
    TextGadget(2, (#WindowWidth/2)+5, 40, (#WindowWidth/2)-15, 32, "Capturing the item-selected event")
    
    SetWindowCallback(@SelectCallback())
    
    Repeat
      EventID = WaitWindowEvent()
      
      Select EventID
        Case #PB_Event_Gadget
          EventGadgetID = EventGadget()
          Select EventGadgetID
            Case 1
              SendMessage_(CB_hWnd, #WM_GETTEXT, cchTextMax, lpch)
              SendMessage_(CB_hWnd, #CB_INSERTSTRING, -1, lpch)
          EndSelect
      EndSelect
      
    Until EventID = #PB_Event_CloseWindow
  Else
    Error("Could not create editable combobox control.")
  EndIf
Else 
  Error("Could not open main window.")
EndIf

End
Bye,

El_Choni


Edited by - El_Choni on 04 July 2002 12:47:03
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.

Nice work El_Choni
but:
This fixes a bug in PB which doesn't handle correctly ComboBox selection changing events.
is wrong.

I tested the original PureBasic ComboBoxGadget command and the bug is still there...
Conclusion: your code doesn't fix a bug in PB.

It's a REPLACEMENT for the buggy gadget!

BTW: Is your nice SelectCallback procedure able to replace the WaitWindowEvent command?
Because IMO this is also buggy. If you press the right mouse button and you want an action with 'EventMouseButton()' because of this MouseEvent you get nothing if your Cursor is on a Gadget.
You get only an Event if your Cursor is on the 'Main Window'...


Have a nice day...
Franco

Sometimes you have to go a lonely way to accomplish genius things.

Edited by - franco on 22 February 2002 00:27:34
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.
Conclusion: your code doesn't fix a bug in PB.
It's a REPLACEMENT for the buggy gadget!
True, sorry for my triumphalist english.
BTW: Is your nice SelectCallback procedure able to replace the WaitWindowEvent command?
It is not able, nor it intends to. It's only reason of existing is getting around what I consider a bug or misfeature, that is, that you can capture "select" events in a combo box if you don't doubleclick or something like that.
Because IMO this is also buggy. If you press the right mouse button and you want an action with 'EventMouseButton()' because of this MouseEvent you get nothing if your Cursor is on a Gadget. You get only an Event if your Cursor is on the 'Main Window'...
AFAIK, this is a PB bug independent of the code I've posted. There are at least one or two topics on the matter.

I've been trying for some days to catch the 'select' event. When I got it, I posted the code, that's all. You're right, it doesn't fix nothing, it just takes advantage of PB's features so it's easy for anybody to use the event, at least while the thing is not really fixed (I'm not the only one who missed this).

Have a nice day, too,

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.

3:30 in the morning (GMT) and (if I recall it right -1 hour in Spain).
Now I believe it: you cannot sleep.
I'm sorry for you man - but this is good for us

Happy coding in the night...


Have a nice day...
Franco

Sometimes you have to go a lonely way to accomplish genius things.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

Hi,

I've realized I've mixed the editable ComboBox code (from the Browser snippet) and the select event capturing code, so things can appear a bit messed up.

This is the skeleton code, free of API functions. It doesn't mean it's portable, since it uses Windows messaging system for the callback and Windows API constants. Anyway, maybe this bug is not present in other OSes.

Added a workaround for the ComboBox right-click bug.

Code: Select all

#MainWndFlags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget
#WindowWidth = 512
#ComboBoxGadget = 0
#AddGadget = 1
#TextGadget = 2
Global CB_hWnd.l, lpch.l
Procedure Error(errorstring.s)
  MessageRequester("Error", errorstring, #MB_ICONERROR)
  End
EndProcedure
Procedure SelectCallback(hWnd, uMsg, wParam, lParam)
  result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_CONTEXTMENU
      If wParam=CB_hWnd
        MessageRequester("You right-clicked", "in the ComboBox gadget.", 0)
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure
hInstance = GetModuleHandle_(#NULL)
Main_hWnd = OpenWindow(0, #CW_USEDEFAULT, #CW_USEDEFAULT, #WindowWidth, 80, #MainWndFlags, "Editable ComboBox item selection event catching example:")
If Main_hWnd
  If CreateGadgetList(Main_hWnd)
    CB_hWnd = ComboBoxGadget(#ComboBoxGadget, 5, 5, #WindowWidth-10, 100) ; #PB_ComboBox_Editable: with this flag, right click defaults to edit context menu
    If CB_hWnd
      cchTextMax = 256
      lpch = AllocateMemory(0, cchTextMax, 0)
      Dim item.s(7)
      item(0) = "Spaghetti"
      item(1) = "Great sole"
      item(2) = "Potato omelette"
      item(3) = "Fondue chinoise"
      item(4) = "Tapioca soup"
      item(5) = "Duck liver"
      item(6) = "Kebap"
      For i = 0 To 6
        AddGadgetItem(#ComboBoxGadget, -1, item(i))
      Next i
      ButtonGadget(#AddGadget, 5, 40, (#WindowWidth/2)-15, 32, "Add")
      TextGadget(#TextGadget, (#WindowWidth/2)+5, 40, (#WindowWidth/2)-15, 32, "Capturing the item-selected event")
      SetWindowCallback(@SelectCallback())
      Repeat
        EventID = WaitWindowEvent()
        Select EventID
          Case #PB_EventGadget
            Select EventGadgetID()
              Case #ComboBoxGadget
                Select EventType()
                  Case #PB_EventType_RightClick
                    MessageRequester("Selection changed to:", GetGadgetText(#ComboBoxGadget), 0)
                EndSelect
              Case #AddGadget
                SendMessage_(CB_hWnd, #WM_GETTEXT, cchTextMax, lpch)
                AddGadgetItem(#ComboBoxGadget, -1, PeekS(lpch))
            EndSelect
          Case #PB_EventCloseWindow
            Quit = 1
        EndSelect
      Until Quit
    Else
      Error("Could not create ComboBox gadget.")
    EndIf
  Else
      Error("Could not create gadget list.")
  EndIf
Else 
  Error("Could not open main window.")
EndIf

End
Bye,

El_Choni


Edited by - El_Choni on 04 July 2002 12:48:29
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Rings.

thx El_choni for this workaround.works fine here.

Its a long way to the top if you wanna .....CodeGuru
Post Reply