Universal 4 State ImageButton

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Bisonte
Beiträge: 2470
Registriert: 01.04.2007 20:18

Universal 4 State ImageButton

Beitrag 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 !
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Universal 4 State ImageButton

Beitrag von ts-soft »

:allright:
Funktioniert einwandfrei, auch x64 :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Universal 4 State ImageButton

Beitrag von RSBasic »

:allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Antworten