GadgetID() not recognized

Just starting out? Need help? Post your questions and find answers here.
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

GadgetID() not recognized

Post by BarryG »

Why does this code crash the program when the window is closed? The gadget exists and is defined before the callback, and this is proven by changing the gadget's items inside the callback.

Code: Select all

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

ComboBoxGadget(0, 10, 10, 250, 21)
AddGadgetItem(0, -1, "Click to select")
SetGadgetState(0, 0)

Procedure WindowCallback(WindowHandle.I, Message.I, WParam.I, LParam.I)
  If LParam = GadgetID(0) ; CRASHES PROGRAM WHEN WINDOW CLOSES!
    If Message = #WM_COMMAND
      Select WParam >> 16 & $FFFF
        Case #CBN_DROPDOWN
          ClearGadgetItems(0)
          AddGadgetItem(0, -1, "Click to select")
          For a = 1 To 5
            AddGadgetItem(0, -1, Str(Random(100)))
          Next
      EndSelect
    EndIf
  EndIf 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

SetWindowCallback(@WindowCallback(), 0)

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
I just noticed this version does not crash:

Code: Select all

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

Global NoCrash = ComboBoxGadget(0, 10, 10, 250, 21)
AddGadgetItem(0, -1, "Click to select")
SetGadgetState(0, 0)

Procedure WindowCallback(WindowHandle.I, Message.I, WParam.I, LParam.I)
  If LParam = NoCrash
    If Message = #WM_COMMAND
      Select WParam >> 16 & $FFFF
        Case #CBN_DROPDOWN
          ClearGadgetItems(0)
          AddGadgetItem(0, -1, "Click to select")
          For a = 1 To 5
            AddGadgetItem(0, -1, Str(Random(100)))
          Next
      EndSelect
    EndIf
  EndIf 
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

SetWindowCallback(@WindowCallback(), 0)

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
So is it a bug in PureBasic?
Last edited by BarryG on Tue May 14, 2019 12:32 pm, edited 1 time in total.
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GadgetID() not recognized

Post by infratec »

Hi,

the problem is that the window including the gadgets are already desroyed when you reach your callback.

Fix:

Code: Select all

Procedure WindowCallback(WindowHandle.I, Message.I, WParam.I, LParam.I)
  If IsGadget(0)
    If LParam = GadgetID(0) ; CRASHES PROGRAM WHEN WINDOW CLOSES!
      If Message = #WM_COMMAND
        Select WParam >> 16 & $FFFF
          Case #CBN_DROPDOWN
            ClearGadgetItems(0)
            AddGadgetItem(0, -1, "Click to select")
            For a = 1 To 5
              AddGadgetItem(0, -1, Str(Random(100)))
            Next
        EndSelect
      EndIf
    EndIf
  EndIf
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
User avatar
Bisonte
Addict
Addict
Posts: 1232
Joined: Tue Oct 09, 2007 2:15 am

Re: GadgetID() not recognized

Post by Bisonte »

Because gadget number 0 is not exists anymore...

Use a global variable to do this, or IsGadget()

Edit: Ups too late ;)
PureBasic 6.10 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
English is not my native language... (I often use DeepL to translate my texts.)
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: GadgetID() not recognized

Post by BarryG »

I understand now. The gadget is destroyed, so the callback can't reference it. But with the global variable, it tries to reference the variable instead (which fails), but no crash occurs because the If/EndIf loop doesn't get executed. Thank you all for the lesson.

Also: is this the best way to re-build a ComboBox on the fly when you click to open it? I want it to populate with the most current data but only when the user clicks to see the list, as the data could change at any time and I don't want my program to constantly re-populate it. Only populate on demand, as it were.
Last edited by BarryG on Tue May 14, 2019 12:39 pm, edited 1 time in total.
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GadgetID() not recognized

Post by infratec »

You're working example is not correct :wink:

Because you don't access the gadget with your NoCrash Variable.

With GadgetID(0) you want to access it and this fail.
With your NoCrash variable you come not into the if.
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: GadgetID() not recognized

Post by BarryG »

Still on this subject: if the window that has a callback is closed, shouldn't the callback just exit silently or do nothing, instead of blindly trying to reference the destroyed window and/or its gadgets? Should this be a feature request?
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: GadgetID() not recognized

Post by IdeasVacuum »

Nooo, because the CallBack can be used for more than one Window.

So, in the Callback, check if the Window exists before executing code:

Code: Select all

If(IsWindow(#MyWindow))

                   ;do something to scare the living daylights out of the User
EndIf
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4663
Joined: Sun Apr 12, 2009 6:27 am

Re: GadgetID() not recognized

Post by RASHAD »

No crash

Code: Select all

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

ComboBoxGadget(0, 10, 10, 250, 21)
AddGadgetItem(0, -1, "Click to select")
SetGadgetState(0, 0)

Procedure WindowCallback(WindowHandle.I, Message.I, WParam.I, LParam.I)
  If IsGadget(0) And lParam = GadgetID(0) ; CRASHES PROGRAM WHEN WINDOW CLOSES!
    If Message = #WM_COMMAND
      Select WParam >> 16 & $FFFF
        Case #CBN_DROPDOWN
          ClearGadgetItems(0)
          AddGadgetItem(0, -1, "Click to select")
          For a = 1 To 5
            AddGadgetItem(0, -1, Str(Random(100)))
          Next
      EndSelect
    EndIf
  EndIf
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

SetWindowCallback(@WindowCallback(), 0)

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
OR

Code: Select all

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

ComboBoxGadget(0, 10, 10, 250, 21)
AddGadgetItem(0, -1, "Click to select")
SetGadgetState(0, 0)

Procedure WindowCallback(WindowHandle.I, Message.I, WParam.I, LParam.I)
  If lParam = GadgetID(0) ; CRASHES PROGRAM WHEN WINDOW CLOSES!
    If Message = #WM_COMMAND
      Select WParam >> 16 & $FFFF
        Case #CBN_DROPDOWN
          ClearGadgetItems(0)
          AddGadgetItem(0, -1, "Click to select")
          For a = 1 To 5
            AddGadgetItem(0, -1, Str(Random(100)))
          Next
      EndSelect
    EndIf
  EndIf
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

SetWindowCallback(@WindowCallback(),0)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      SetWindowCallback(0,0)
      Quit = 1
  EndSelect
Until Quit = 1
Egypt my love
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: GadgetID() not recognized

Post by BarryG »

IdeasVacuum wrote:the CallBack can be used for more than one Window.
I was not aware of that. Thanks for explaining.
User avatar
VB6_to_PBx
Enthusiast
Enthusiast
Posts: 625
Joined: Mon May 09, 2011 9:36 am

Re: GadgetID() not recognized

Post by VB6_to_PBx »

is it OK to use :
GetDlgCtrlID_(LParam)
???

Code: Select all

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

ComboBoxGadget(2, 10, 10, 250, 21)
AddGadgetItem(2, -1, "Click to select")
SetGadgetState(2, 0)

Procedure WindowCallback(WindowHandle.I, Message.I, WParam.I, LParam.I)
  If GetDlgCtrlID_(LParam) = 2 ; CRASHES PROGRAM WHEN WINDOW CLOSES!
    If Message = #WM_COMMAND
      Select WParam >> 16 & $FFFF
        Case #CBN_DROPDOWN
          ClearGadgetItems(2)
          AddGadgetItem(2, -1, "Click to select")
          For a = 1 To 5
            AddGadgetItem(2, -1, Str(Random(100)))
          Next
      EndSelect
    EndIf
  EndIf
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

SetWindowCallback(@WindowCallback(),0)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      SetWindowCallback(0,0)
      Quit = 1
  EndSelect
Until Quit = 1

 
PureBasic .... making tiny electrons do what you want !

"With every mistake we must surely be learning" - George Harrison
Post Reply