Seite 1 von 1

Universal 4 State ImageButton

Verfasst: 01.08.2012 17:05
von Bisonte
Hallo zusammen.

Ich hab da mal (um API-, und Pointerkenntnisse zu erlangen) ein Gadget auf Basis eines ImageGadgets gebastelt.

Es ist auch möglich, durch auskommentieren der #CompileAsUserlib bei Tailbite die IDE-Debug Funktion zu erhalten.
Ich hoffe mal das funktioniert im Einsatz ;)

Der HauptTeil : "U4IB.pb"

Code: Alles auswählen

;@____________________________________________________________________________
; »»» Projekt : Universal 4-State ImageButtonGadget
; »»» Author  : George Bisonte (mit Hilfe von netmaestro (Maustracking)
; »»» Date    : 01 Aug, 2012
; »»» OS      : WindowsOnly
; »»» PB      : V4.61 (tested x86)
; »»» CPU     : x86 (getestet, sollte eigentlich auch mit x64 laufen)
; »»» Unicode : Ja, sollte eigentlich, da keine Strings genutzt werden 
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
EnableExplicit
;
; Wenn diese Include als oder in eine(r) Userlib genutzt werden soll,
; folgende Zeile auskommentieren um DEBUG Funktionen zu erhalten (Nur TailBite)
; #CompileAsUserlib = #True
;
CompilerIf Defined(CompileAsUserlib, #PB_Constant) = #True
  CompilerIf #CompileAsUserlib = #True
    XIncludeFile #PB_Compiler_Home+"TailBite/Helper Libraries/TB_Debugger.pb"
  CompilerEndIf
CompilerEndIf
; ____________________________________________________________________________
; »»» Externe Ressourcen
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Enumeration 0 ; Die 4 Zustands Images als Konstante (für ChangeImage)
  #PB_U4IButton_Normal
  #PB_U4IButton_Hoover
  #PB_U4IButton_Selected
  #PB_U4IButton_Disabled
EndEnumeration
; ____________________________________________________________________________
; »»» Intern
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
#PROP_UNIVERSAL4STATE_IMAGEBUTTONGADGET = "UNIVERSAL4STATE_IMAGEBUTTONGADGET"
;
Structure struct_universal_imagebuttongadget
  Gadget.i     ; »»» PB Gadget Objektnummer
  OldProc.i    ; »»» Alter Callback des ImageGadgets
  State.i      ; »»» Welchen Zustand hat das Gadget
  Disabled.i   ; »»» Ist das Gadget Disabled ?
  Tracking.i   ; »»» Für die Mausüberwachung (thx Netmaestro)
  Image.i[4]   ; »»» Die 4 Images
EndStructure
Procedure priv_callback_universal_imagebuttongadget(hWnd, uMsg, wParam, lParam)
  
  Protected OldProc, i
  Protected *p.struct_universal_imagebuttongadget
  Protected tm.TRACKMOUSEEVENT
  
  *p = GetProp_(hWnd, #PROP_UNIVERSAL4STATE_IMAGEBUTTONGADGET)
  If *p
    OldProc = *p\OldProc
  Else
    ProcedureReturn 0
  EndIf
  
  Select uMsg
      
    Case #WM_NCDESTROY ; FreeGadget() wurde aufgerufen
      FreeMemory(*p) ; den erstellten Speicher freigeben
      
    Case #WM_ENABLE ; DisableGadget() wurde aufgerufen
      If wParam = 0
        *p\Disabled = #True
        *p\State = 3
      Else
        *p\Disabled = #False
        *p\State = 0
      EndIf
      If IsGadget(*p\Gadget) And IsImage(*p\Image[*p\State])
        SetGadgetState(*p\Gadget, ImageID(*p\Image[*p\State]))
      EndIf
      
    Case #WM_MOUSEMOVE ; Mouse wurde bewegt
      If Not *p\tracking ; Mousetracking starten
        *p\tracking = #True
        With tm.TRACKMOUSEEVENT
          \cbSize = SizeOf(TRACKMOUSEEVENT)
          \dwFlags = #TME_LEAVE 
          \hwndTrack = hWnd
        EndWith
        TrackMouseEvent_(@tm)
        CallWindowProc_(OldProc, hWnd, uMsg, wParam, lParam)
        If *p\State = 0
          *p\State = 1
           SetGadgetState(*p\Gadget, ImageID(*p\Image[*p\State]))
        EndIf
        ProcedureReturn 0
      Else ; Mousetracking läuft bereits
        If *p\State = 0
          *p\State = 1
          SetGadgetState(*p\Gadget, ImageID(*p\Image[*p\State]))
        EndIf
     EndIf        
      
    Case #WM_MOUSELEAVE ; Maus verlässt Gadget
      *p\tracking = #False
      If *p\State >0 And *p\State < 3
        *p\State = 0
        SetGadgetState(*p\Gadget, ImageID(*p\Image[*p\State]))
      EndIf
      ProcedureReturn 0
      
    Case #WM_LBUTTONDOWN ; Nur auf Linken Mauskopf reagieren wenn Maus auch über Gadget ist
      If *p\State = 1
        *p\State = 2
      EndIf
      SetGadgetState(*p\Gadget, ImageID(*p\Image[*p\State]))
      
    Case #WM_LBUTTONUP ; Linker Mausknopf hoch stellt Hoover Image wieder her wenn selected ist
      If *p\State = 2
        If *p\tracking = #True
          *p\State = 1
        EndIf        
      EndIf
      SetGadgetState(*p\Gadget, ImageID(*p\Image[*p\State]))      
      
  EndSelect
    
  If OldProc
    ProcedureReturn CallWindowProc_(OldProc, hWnd, uMsg, wParam, lParam)
  Else
    ProcedureReturn 0
  EndIf
  
EndProcedure  
; ____________________________________________________________________________
; »»» 
; »»» Externe Funktionen
; »»» 
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
ProcedureDLL U4I_ButtonGadget(Gadget, x, y, ImageNormal, ImageHoover, ImageSelected, ImageDisabled) ; Erstellt ein ButtonGadget mit den 4 Images
  
  Protected *p.struct_universal_imagebuttongadget
  Protected ID = #False, Error = #False
  
  If Not IsImage(ImageNormal) Or Not IsImage(ImageHoover) Or Not IsImage(ImageSelected) Or Not IsImage(ImageDisabled)
    ProcedureReturn #False
  EndIf
  
  *p = AllocateMemory(SizeOf(struct_universal_imagebuttongadget))
  If Not *p : ProcedureReturn #False : EndIf  
  
  *p\Image[0] = ImageNormal
  *p\Image[1] = ImageHoover
  *p\Image[2] = ImageSelected
  *p\Image[3] = ImageDisabled
  
  *p\State = 0
  *p\tracking = #False
  *p\Disabled = #False
  
  ID = ImageGadget(Gadget, x, y, ImageWidth(ImageNormal), ImageHeight(ImageNormal), ImageID(ImageNormal))
  If Gadget = #PB_Any : Gadget = ID : EndIf
  *p\Gadget = Gadget
  *p\OldProc = SetWindowLongPtr_(GadgetID(Gadget), #GWLP_WNDPROC, @priv_callback_universal_imagebuttongadget())
  
  SetProp_(GadgetID(Gadget), #PROP_UNIVERSAL4STATE_IMAGEBUTTONGADGET, *p)
  
  ProcedureReturn ID
  
EndProcedure
ProcedureDLL U4I_ChangeButtonImage(Gadget, ImageType, Image) ; Aendert ein Image in der Imageliste des Gadgets
  
  Protected *p.struct_universal_imagebuttongadget
  
  If Not IsImage(Image) : ProcedureReturn #False : EndIf
  If Not IsGadget(Gadget) : ProcedureReturn #False : EndIf
  
  *p = GetProp_(GadgetID(Gadget), #PROP_UNIVERSAL4STATE_IMAGEBUTTONGADGET)
  
  If *p
    If ImageType >= 0 And ImageType <= 3
      *p\Image[ImageType] = Image
      SetGadgetState(Gadget, ImageID(*p\Image[*p\State]))
      ProcedureReturn #True
    EndIf
  Else
    ProcedureReturn #False
  EndIf
      
EndProcedure
; ____________________________________________________________________________
; »»» Debug Funktionen
; ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
CompilerIf Defined(CompileAsUserlib, #PB_Constant) = #True
  CompilerIf #CompileAsUserlib = #True
    ProcedureCDLL U4IButtonGadget_DEBUG(Gadget, x, y, ImageNormal, ImageHoover, ImageSelected, ImageDisabled)
      
      If Not IsImage(ImageNormal)
        TB_DebugError("#ImageNormal is not initialized")
      EndIf
      If Not IsImage(ImageHoover)
        TB_DebugError("#ImageHoover is not initialized")
      EndIf
      If Not IsImage(ImageSelected)
        TB_DebugError("#ImageSelected is not initialized")
      EndIf
      If Not IsImage(ImageDisabled)
        TB_DebugError("#ImageDisabled is not initialized") 
      EndIf
      
    EndProcedure
    ProcedureCDLL U4I_ChangeButtonImage_DEBUG(Gadget, ImageType, Image)
      
      If Not IsGadget(Gadget)
        TB_DebugError("#Gadget is not initialized")
      EndIf
      If Not IsImage(Image)
        TB_DebugError("#Image is not initialized")
      EndIf
      If ImageType < #PB_U4IButton_Normal And ImageType > #PB_U4IButton_Disabled 
        TB_DebugError("ImageType is out of range (0-3) , hint : use for example #PB_U4IButton_Hoover")
      EndIf
      
    EndProcedure  
  CompilerEndIf
CompilerEndIf
;
DisableExplicit
Die Resident Datei falls man das als Userlib kompilieren möchte : "U4IB_residents.pb"

Code: Alles auswählen

Enumeration 0 ; Die 4 Zustands Images als Konstante (für ChangeImage)
  #PB_U4IButton_Normal
  #PB_U4IButton_Hoover
  #PB_U4IButton_Selected
  #PB_U4IButton_Disabled
EndEnumeration
und am Schluss noch eine "Demo", der es egal ist ob als Userlib oder Include ...
Man sollte nur über 4 Images verfügen und dann die Pfade anpassen...

Code: Alles auswählen

CompilerIf Defined(U4I_ButtonGadget, #PB_Function) = #False
  XIncludeFile "U4IB.pb"
CompilerEndIf

UsePNGImageDecoder()

; PFADE DER BILDER ANPASSEN (ALLE SOLLTEN GLEICH GROSS SEIN)
Im1 = LoadImage(#PB_Any, "ImageNormal.png")
Im2 = LoadImage(#PB_Any, "ImageHoover.png")
Im3 = LoadImage(#PB_Any, "ImageSelected.png")
Im4 = LoadImage(#PB_Any, "ImageDisabled.png")

OpenWindow(0,200,300,800,600,"TestWindow")

U4I_ButtonGadget(1,10,10,im1,im2,im3,im4)
U4I_ButtonGadget(2,70,10,im1,im2,im3,im4)

DisableGadget(1,1)

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 2
          Debug "Gadget 2"
      EndSelect
      
    Case #PB_Event_CloseWindow
      Quit = 1
      
  EndSelect
  
Until Quit > 0


Verbesserungsvorschläge sind sehr willkommen !

Re: Universal 4 State ImageButton

Verfasst: 01.08.2012 17:40
von ts-soft
:allright:
Funktioniert einwandfrei, auch x64 :wink:

Re: Universal 4 State ImageButton

Verfasst: 01.08.2012 18:23
von RSBasic
:allright: