TimePicker Control

Share your advanced PureBasic knowledge/code with the community.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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
Last edited by netmaestro on Sat Feb 17, 2007 7:12 pm, edited 6 times in total.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post 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.
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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!
BERESHEIT
r_hyde
Enthusiast
Enthusiast
Posts: 155
Joined: Wed Jul 05, 2006 12:40 am

Post 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!
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post 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)
;)
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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.
BERESHEIT
Post Reply