Page 2 of 2

Posted: Sat Feb 17, 2007 6:40 pm
by netmaestro
You're most welcome, thanks for the kind words. I like to use window properties to associate all the vars and handles with the current instance of the gadget. It is much cleaner and simpler than using structured lists, you just have to remember that you are responsible for removing the properties at WM_DESTROY, as Windows won't do it for you. Using this method, no globals or shared vars are needed at all:

Code: Select all

Procedure SubClass(hwnd, msg, wparam, lparam) 
  oldproc = GetProp_(hwnd, "oldproc") 
  gadget2 = GetProp_(hwnd, "gadget2") 
  var1    = GetProp_(hwnd, "var1")
  
  ; Now all the vars are known and specific to this instance only 
  
  Select msg 
    Case .. 
    Case .. 
    Case #WM_DESTROY 
      RemoveProp_(hwnd, "oldproc") 
      RemoveProp_(hwnd, "var1") 
      RemoveProp_(hwnd, "gadget2") 
  EndSelect    
EndProcedure 

Procedure MyGadget(GadgetNumber, x, y, etc..) 
  gadget1 = StringGadget(GadgetNumber, ... etc) 
  gadget2 = CreateWindowEx_( arguments etc..) 
  var1 = animportantvalue  
  
  oldproc = SetWindowLong_( set up the subclass) 
  
  ; associate all vars and handles with the instance 
  SetProp_(gadget1, "oldproc", oldproc) 
  SetProp_(gadget1, "gadget2", gadget2) 
  SetProp_(gadget1, "var1", var1) 
  
  ProcedureReturn GadgetNumber 
EndProcedure 
 
Another way is to use:

Code: Select all

*this = AllocateMemory(SizeOf(MyStruct))
; write your vars
SetWindowLong_(hwnd, #GWL_USERDATA, *this)
and now all the vars are available with:

Code: Select all

*this.MyStruct = GetWindowLong_(hwnd, #GWL_USERDATA)
var1 = *this\var1
And you don't have to iterate a list looking for your instance-specific data.

PureBasic in v4 leaves this field open for us to use for all gadgets except the WebGadget, see here:

http://www.purebasic.fr/english/viewtopic.php?t=23354

Posted: Sat Feb 17, 2007 6:54 pm
by srod
I've found that you're sometimes better off removing the properties in the #WM_NCDESTROY handler as, otherwise, calling the old window proc (obtained by GetProp_()) in response to 'Default' can cause an invalid memory access since the Windows property will have been removed too early.

Posted: Sat Feb 17, 2007 7:01 pm
by netmaestro
Good point, as WM_NCDESTROY happens a step later than WM_DESTROY, it's that much safer. After WM_DESTROY has already occurred there should definitely be no problem. Thanks for the tip!

Posted: Thu Mar 01, 2007 5:35 am
by r_hyde
Thanks for the replies, and sorry I haven't checked in for a while. I'm not sure I follow 100% your suggestion about using window properties to associate handles/vars with gadget instances. <snip!> (I didn't read well enough!) </snip> I must study your example!

Anyway, the workaround I hacked up is behaving just fine for me so far, so I doubt I'll go and rework any of the stuff I've written based around it. It would just be nice to know a more elegant way than using linkedlists for the next time around.

Thanks again!

Posted: Wed Dec 12, 2007 9:16 pm
by PB
> CreateWindowEx_(0,"SysDateTimePick32","",#WS_CHILD|#WS_VISIBLE|#DTS_TIMEFORMAT,100,100,100,22,WindowID(0),99,GetModuleHandle_(0),0)

@netmaestro: You can just use the #DTS_TIMEFORMAT flag with a DateGadget:

Code: Select all

DateGadget(0,20,20,100,20,"",0,#DTS_TIMEFORMAT)
;)

Posted: Thu Dec 13, 2007 12:21 am
by netmaestro
I believe that came up in pm at the time, but now that I have the job done I prefer my version to the MS one and this is nice and short:

Code: Select all

gadget = TimePickerGadget(#PB_Any, 90, 100)
The version I'm using is modified from the posted code to use window properties for the vars, allowing multiple gadgets on multiple windows without conflict.