PB4 : create custom gadget

Share your advanced PureBasic knowledge/code with the community.
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

PB4 : create custom gadget

Post by eddy »

Updated version for PB4.20 - 4.30 [win]

- test custom events : OK
- test custom callback : OK
- test default commands : OK
- test default font : OK
- test FreeGadget : OK
- test IsGadget : OK
- test setgadgetdata : OK
- test unicode : OK
- test PB x64 : OK

Code: Select all

;EnableExplicit

CompilerIf Defined(CreateGadget, #PB_Procedure)=0
   ;{/// STRUCTURES
   CompilerIf Defined(GADGET_VT, #PB_Structure)=#False
      Structure GADGET_VT  ; PB_GadgetVT
         GadgetType.i      ; gadget type (used by GadgetType command)
         SizeOf.i          ; Size of structure
         
         *GadgetCallback
         *FreeGadget
         *GetGadgetState
         *SetGadgetState
         *GetGadgetText
         *SetGadgetText
         *AddGadgetItem2
         *AddGadgetItem3
         *RemoveGadgetItem
         *ClearGadgetItemList
         *ResizeGadget
         *CountGadgetItems
         *GetGadgetItemState
         *SetGadgetItemState
         *GetGadgetItemText
         *SetGadgetItemText
         *OpenGadgetList2
         *GadgetX
         *GadgetY
         *GadgetWidth
         *GadgetHeight
         *HideGadget
         *AddGadgetColumn
         *RemoveGadgetColumn
         *GetGadgetAttribute
         *SetGadgetAttribute
         *GetGadgetItemAttribute2
         *SetGadgetItemAttribute2
         *SetGadgetColor
         *GetGadgetColor
         *SetGadgetItemColor2
         *GetGadgetItemColor2
         *SetGadgetItemData
         *GetGadgetItemData
      EndStructure
   CompilerEndIf
   CompilerIf Defined(GADGET, #PB_Structure)=#False
      Structure GADGET     ; PB_Gadget
         hwnd.i            ; gadget window handle
         *VT.GADGET_VT     ; gadget commands
         *GadgetData       ; gadget data           (used by SetGadgetData command)
         *OldCallback      ; window CALLBACK       (used by purebasic CALLBACK)
         Dates.i[4]        ; .....
      EndStructure
   CompilerEndIf
   CompilerIf Defined(GADGET_PARAMS, #PB_Structure)=#False
      Structure GADGET_PARAMS
         ID.i              ; gadget ID
         NewType.i         ; gadget custom type
         *cmds.GADGET_VT   ; gadget custom commands
         *NewCallback      ; gadget custom CALLBACK
         *OldCallback      ; gadget purebasic CALLBACK (used by custom CALLBACK)
         *customFree       ; gadget custom FreeGadget (used by CleanupGadget procedure)
         
         Window_Style.i    ; For window creation
         Window_ExStyle.i  ; For window creation
         Window_ClassName.s; For window creation
         Window_Text.s     ; For window creation
      EndStructure
   CompilerEndIf
   ;}
   ;{/// IMPORTS
   Import ""
      CompilerIf Defined(*PB_GADGET_OBJECTS, #PB_Variable)=#False
         CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
            *PB_GADGET_OBJECTS As "PB_Gadget_Objects"
         CompilerElse
            *PB_GADGET_OBJECTS As "_PB_Gadget_Objects"
         CompilerEndIf
      CompilerEndIf
      
      CompilerIf Defined(*PB_GADGET_GLOBALS, #PB_Variable)=#False
         CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
            *PB_GADGET_GLOBALS As "PB_Gadget_Globals"
         CompilerElse
            *PB_GADGET_GLOBALS As "_PB_Gadget_Globals"
         CompilerEndIf
      CompilerEndIf
      
      CompilerIf Defined(PB_Object_GetThreadMemory, #PB_Procedure)=#False
         PB_Object_GetThreadMemory(*PB_Object)
      CompilerEndIf
      
      CompilerIf Defined(PB_Object_GetOrAllocateID, #PB_Procedure)=#False
         PB_Object_GetOrAllocateID(*PB_Object, ID)
      CompilerEndIf
      
      CompilerIf Defined(CreateGadgetWindow, #PB_Procedure)=#False
         CompilerIf #PB_Compiler_Unicode
            CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
               PB_Gadget_RegisterGadget(ID, *Gadget.GADGET_PARAMS, hwnd, *vt.GADGET_VT) As "PB_Gadget_RegisterGadget_UNICODE@16"
            CompilerElse
               PB_Gadget_RegisterGadget(ID, *Gadget.GADGET_PARAMS, hwnd, *vt.GADGET_VT) As "_PB_Gadget_RegisterGadget_UNICODE@16"
            CompilerEndIf
         CompilerElse
            PB_Gadget_RegisterGadget(ID, *Gadget.GADGET_PARAMS, hwnd, *vt.GADGET_VT)
         CompilerEndIf
      CompilerEndIf
      
      CompilerIf Defined(PB_Gadget_SendGadgetCommand, #PB_Procedure)=#False
         PB_Gadget_SendGadgetCommand(hwnd, EventType)
      CompilerEndIf
   EndImport
   ;}
   ;{/// MACROS
   Macro NewGadgetParams(params, GADGET_PARAMS_TYPE)
      Protected params.GADGET_PARAMS_TYPE=AllocateMemory(SizeOf(GADGET_PARAMS_TYPE))
      params\cmds=AllocateMemory(SizeOf(GADGET_VT))
   EndMacro
   Macro GetGadgetParams(params, GADGET_PARAMS_TYPE, hwnd)
      Protected params.GADGET_PARAMS_TYPE=GetProp_(hwnd, "GadgetInfo")
   EndMacro
   ;}
   ;{/// FUNCTIONS
   Procedure CleanupGadget(*gadget.GADGET)
      Protected *params.GADGET_PARAMS=GetProp_(*gadget\hwnd, "GadgetInfo")
      
      ;call custom command for FreeGadget
      If *params\customFree
         CallFunctionFast(*params\customFree, *gadget)
      EndIf
      
      ;cleanup memory
      RemoveProp_(*gadget\hwnd, "GadgetInfo")
      FreeMemory(*params\cmds)
      FreeMemory(*params)
   EndProcedure
   Procedure RegisterGadget(ID, hwnd, *params.GADGET_PARAMS)
      Protected *Gadget.GADGET
      Protected result
      
      With *params
         If hwnd=0 Or ID<#PB_Any : ProcedureReturn #False : EndIf
         If *params=0 Or \cmds=0 : ProcedureReturn #False : EndIf
         
         ;set custom command for FreeGadget
         \customFree=\cmds\FreeGadget
         \cmds\FreeGadget=@CleanupGadget()
         ;set gadget type
         \cmds\GadgetType=\NewType
         
         ;register gadget ID
         *Gadget=PB_Object_GetOrAllocateID(*PB_GADGET_OBJECTS, ID)
         result=PB_Gadget_RegisterGadget(ID, *Gadget, hwnd, \cmds)
         If Not result : ProcedureReturn #False : EndIf
         
         ;register gadget parameters
         If ID=#PB_Any
            \ID=result
         Else
            \ID=ID
         EndIf
         If \NewCallback
            \OldCallback=SetWindowLongPtr_(hwnd, #GWL_WNDPROC, \NewCallback)
         EndIf
         SetProp_(hwnd, "GadgetInfo", *params)
      EndWith
      ProcedureReturn result
   EndProcedure
   Procedure CreateGadget(ID, x, y, Width, Height, *params.GADGET_PARAMS)
      Protected hInstance=GetModuleHandle_(0)
      Protected hwnd
      Protected hwndParent
      Protected result
      
      ;get gadget parent
      CompilerIf #PB_Compiler_Version<430
         If 0 : CreateGadgetList(0) : EndIf
         hwndParent=PeekI(PB_Object_GetThreadMemory(*PB_GADGET_GLOBALS))
      CompilerElse
         DisableDebugger
         hwndParent=UseGadgetList(0)
         EnableDebugger
      CompilerEndIf
      
      ;create gadget window
      With *params
         hwnd=CreateWindowEx_(\Window_ExStyle, \Window_ClassName, \Window_Text, \Window_Style, x, y, Width, Height, hwndParent, 0, hInstance, 0)
         If Not hwnd : ProcedureReturn #False : EndIf
      EndWith
      
      ;set gadget ID and params
      result=RegisterGadget(ID, hwnd, *params)
      If Not result : ProcedureReturn #False : EndIf
      
      ;set gadget Font
      SendMessage_(hwnd, #WM_SETFONT, GetGadgetFont(#PB_Default), #True)
      ProcedureReturn result
   EndProcedure
   ;}
CompilerEndIf
Last edited by eddy on Mon Dec 01, 2008 10:38 am, edited 13 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

Example 1 : Simple Gadget
- SimpleGadget ( a custom button )
- support custom eventType = 10000
- enable UNICODE for this example
Last edited by eddy on Tue Nov 25, 2008 6:13 pm, edited 3 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

- ADDED : bulletproof compiler directives
- FIXED : unicode version for PB_Gadget_RegisterGadget

Example 2 : Rebar Gadget
- addgadgetitem
- setgadgetcolor
- source code : http://www.purebasic.fr/english/viewtopic.php?t=35329
Last edited by eddy on Tue Nov 25, 2008 2:15 am, edited 10 times in total.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
AND51
Addict
Addict
Posts: 1040
Joined: Sun Oct 15, 2006 8:56 pm
Location: Germany
Contact:

Post by AND51 »

I did just quick test with the code from the first post nunder Vista x64 at PB 4.30 BETA 4, and there were several errors:
Error wrote:POLINK: error: Unresolved external symbol '_PB_Gadget_Objects'.
POLINK: error: Unresolved external symbol '_PB_RegisterGadget_UNICODE@16'.
POLINK: error: Unresolved external symbol '_PB_Gadget_Globals'.
POLINK: fatal error: 3 unresolved external(s).
Currently, I don't know what this means or what I/you can do, because I'm too tired now... Good night!
PB 4.30

Code: Select all

onErrorGoto(?Fred)
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

I need some PB internal functions and variables.
But perhaps they are not named in the same way on x64 platform. :?
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post by Xombie »

I look forward to trying this out. Thanks, eddy!
User avatar
mback2k
Enthusiast
Enthusiast
Posts: 257
Joined: Sun Dec 02, 2007 12:11 pm
Location: Germany

Post by mback2k »

Nice code, maybe you want to use the naming conventions of the PBOSL Structures:

Code: Select all

Structure PB_Gadget
  Gadget.i
  *VT.PB_GadgetVT
  *UserData
  *OldCallback
  Daten.l[4]
EndStructure
Because otherwise I can't have it and installed and use this Include :)
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

AND51 wrote:I did just quick test with the code from the first post nunder Vista x64 at PB 4.30 BETA 4, and there were several errors:
I add x64 version. You can test it again.
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

Code: Select all

Nice code, maybe you want to use the naming conventions of the PBOSL Structures: 
I'll fix that
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
eddy
Addict
Addict
Posts: 1479
Joined: Mon May 26, 2003 3:07 pm
Location: Nantes

Post by eddy »

- x64 : SetWindowlongPtr
- rename structures :
  • PB_Gadget -> GADGET (no more confict with older PBOSL structures)
  • PB_GadgetVT -> GADGET_VT
Imagewin10 x64 5.72 | IDE | PB plugin | Tools | Sprite | JSON | visual tool
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Just discovered this. Top stuff eddy! 8)
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
Post Reply