[Module] MouseEvents für Gadgets (all OS)

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
Thorsten1867
Beiträge: 1359
Registriert: 04.02.2005 15:40
Computerausstattung: [Windows 10 x64] [PB V5.7x]
Wohnort: Kaufbeuren
Kontaktdaten:

[Module] MouseEvents für Gadgets (all OS)

Beitrag von Thorsten1867 »

MouseEvents for Gadgets (all OS / 64Bit / DPI)

Code: Alles auswählen

;/ ===============================
;/ =    MouseEventsModule.pbi    =
;/ ===============================
;/
;/ [ PB V5.7x / 64Bit / All OS / DPI ]
;/
;/ MouseEvents - Module (MouseEnter, MouseLeave, MouseMove)
;/
;/ based on 'MyEvents' by mk-soft
;/
;/ adapted from Thorsten Hoeppner (07/2019)
;/

; Last Update:

;{ ===== MIT License =====
;
; Copyright (c) 2015 - 2017 mk-soft
; Copyright (c) 2019 Thorsten Hoeppner
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.
;}

DeclareModule MouseEvent
  
  Enumeration 1
    #MouseX
    #MouseY
    #Gadget
  EndEnumeration

  EnumerationBinary
    #MouseEnter
    #MouseLeave
    #MouseMove
  EndEnumeration
  
  #MouseEvents = #MouseEnter|#MouseLeave|#MouseMove
  
  ;- ===========================================================================
  ;-   DeclareModule
  ;- ===========================================================================
  
  Declare.i Add(Window.i, Gadget.i=#PB_Default, Flags.i=#MouseEvents)
  Declare.i GetAttribute(Window.i, Attribute.i, Gadget.i=#PB_Default)
  
EndDeclareModule

Module MouseEvent
  
  EnableExplicit
  
  #MouseEventTimer = 20000
  
  ;- ============================================================================
  ;-   Module - Structures
  ;- ============================================================================
  
  Structure Window_Structure     ;{ MouseEvent()\Window\...
    Num.i
    MouseX.i
    MouseY.i
  EndStructure ;}
  
  Structure Gadget_Structure     ;{ MouseEvent()\Gadget\...
    Num.i
    MouseX.i
    MouseY.i
    Last.i
  EndStructure ;}
  
  Structure MouseEvent_Structure ;{ MouseEvent('Window')\...
    Gadget.Gadget_Structure
    Window.Window_Structure
    lastHandle.i
    Flags.i
  EndStructure ;}
  Global NewMap MouseEvent.MouseEvent_Structure()
  
  ;- ============================================================================
  ;-   Module - Internal
  ;- ============================================================================

  ;- _____ Import internal function _____
  
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    ; Code by mk-soft
    
    Import ""
      PB_Object_EnumerateStart( PB_Objects )
      PB_Object_EnumerateNext( PB_Objects, *ID.Integer )
      PB_Object_EnumerateAbort( PB_Objects )
      PB_Gadget_Objects.i
    EndImport
    
  CompilerElse
    
    ImportC ""
      PB_Object_EnumerateStart( PB_Objects )
      PB_Object_EnumerateNext( PB_Objects, *ID.Integer )
      PB_Object_EnumerateAbort( PB_Objects )
      PB_Gadget_Objects.i
    EndImport
    
  CompilerEndIf
  
  ;- _____ Events _____
  
  Procedure _MouseEventHandler()
    Define.i X, Y, Handle, Window, Gadget
    
    Window = GetActiveWindow()
    If FindMapElement(MouseEvent(), Str(Window))
    
      X = WindowMouseX(Window)
      Y = WindowMouseY(Window)
      
      If X <> MouseEvent()\Window\MouseX Or Y <> MouseEvent()\Window\MouseY
        
        MouseEvent()\Window\MouseX = X
        MouseEvent()\Window\MouseY = Y
        
        ; Get Handle under mouse (mk-soft)
        CompilerSelect #PB_Compiler_OS
          CompilerCase #PB_OS_Windows ;{ Windows
            Protected.i DesktopX, DesktopY
            
            DesktopX = DesktopMouseX()
            Desktopy = DesktopMouseY()
            Handle   = WindowFromPoint_(DesktopY << 32 | DesktopX)
            ;}
          CompilerCase #PB_OS_MacOS   ;{ MacOS
            Protected WinID.i, WinCV.i, pt.NSPoint
            
            WinID = WindowID(Window)
            WinCV = CocoaMessage(0, WinID, "contentView")
            CocoaMessage(@pt, WinID, "mouseLocationOutsideOfEventStream")
            Handle = CocoaMessage(0, WinCV, "hitTest:@", @pt)
            ;}
          CompilerCase #PB_OS_Linux   ;{ Linux
            Protected DesktopX.i, DesktopY.i, *GdkWindow.GdkWindowObject
            
            *GdkWindow.GdkWindowObject = gdk_window_at_pointer_(@DesktopX,@Desktopy)
            If *GdkWindow
              gdk_window_get_user_data_(*GdkWindow, @Handle)
            Else
              Handle = #False
            EndIf
            ;} 
        CompilerEndSelect
        
        If Handle <> MouseEvent()\lastHandle
          
          ;{ ___ Event: MouseLeave ___ (mk-soft)
          If IsGadget(MouseEvent()\Gadget\Last)
          
            If MouseEvent()\Flags & #MouseLeave
              If GadgetType(MouseEvent()\Gadget\Last) <> #PB_GadgetType_Canvas
                If MouseEvent()\Gadget\Num = #PB_Default Or MouseEvent()\Gadget\Last = MouseEvent()\Gadget\Num
                  PostEvent(#PB_Event_Gadget, MouseEvent()\Window\Num, MouseEvent()\Gadget\Last, #PB_EventType_MouseLeave)
                EndIf
              EndIf
            EndIf
            
            MouseEvent()\Gadget\Last = #PB_Default
            
          EndIf ;}
          
          ; Find GadgetID over Handle (mk-soft)
          PB_Object_EnumerateStart(PB_Gadget_Objects)
          
          While PB_Object_EnumerateNext(PB_Gadget_Objects, @Gadget)
            
            If Handle = GadgetID(Gadget)
              
              MouseEvent()\Gadget\Last = Gadget
              
              ;{ ___ Event: MouseEnter ___ (mk-soft)
              If MouseEvent()\Flags & #MouseEnter
                If GadgetType(MouseEvent()\Gadget\Last) <> #PB_GadgetType_Canvas
                  If MouseEvent()\Gadget\Num = #PB_Default Or MouseEvent()\Gadget\Last = MouseEvent()\Gadget\Num
                    PostEvent(#PB_Event_Gadget, MouseEvent()\Window\Num, MouseEvent()\Gadget\Last, #PB_EventType_MouseEnter)
                  EndIf  
                EndIf
              EndIf ;}
              
              PB_Object_EnumerateAbort(PB_Gadget_Objects)
              Break
            EndIf
            
          Wend
          
          MouseEvent()\lastHandle = Handle
        EndIf
        
        ;{ ___ Event: MouseMove ___ (mk-soft)
        If MouseEvent()\Flags & #MouseMove
          
          If IsGadget(MouseEvent()\Gadget\Last)
            If GadgetType(MouseEvent()\Gadget\Last) <> #PB_GadgetType_Canvas
              If MouseEvent()\Gadget\Num = #PB_Default Or MouseEvent()\Gadget\Last = MouseEvent()\Gadget\Num
                MouseEvent()\Gadget\MouseX = MouseEvent()\Window\MouseX - GadgetX(MouseEvent()\Gadget\Last)
                MouseEvent()\Gadget\MouseY = MouseEvent()\Window\MouseY - GadgetY(MouseEvent()\Gadget\Last)
                PostEvent(#PB_Event_Gadget, MouseEvent()\Window\Num, MouseEvent()\Gadget\Last, #PB_EventType_MouseMove)
              EndIf  
            EndIf
          EndIf
          
        EndIf ;}
        
      EndIf
      
    EndIf

  EndProcedure
  
  ;- ==========================================================================
  ;-   Module - Declared Procedures
  ;- ==========================================================================
  
  Procedure.i Add(Window.i, Gadget.i=#PB_Default, Flags.i=#MouseEvents)
    
    If IsWindow(Window)
      
      If AddMapElement(MouseEvent(), Str(Window))
        
        MouseEvent()\Window\Num = Window
        
        If IsGadget(Gadget)
          MouseEvent()\Gadget\Num = Gadget
        Else
          MouseEvent()\Gadget\Num = #PB_Default
        EndIf
        
        MouseEvent()\Flags = Flags
        
        ; Code by mk-soft
        AddWindowTimer(MouseEvent()\Window\Num, #MouseEventTimer, 100)
        BindEvent(#PB_Event_Timer, @_MouseEventHandler())
        
        ProcedureReturn #True
      EndIf

    EndIf
    
  EndProcedure
  
  Procedure.i GetAttribute(Window.i, Attribute.i, Gadget.i=#PB_Default)
    
    If FindMapElement(MouseEvent(), Str(Window))
      
      If Gadget = #PB_Default Or MouseEvent()\Gadget\Last = Gadget
        
        Select Attribute
          Case #MouseX
            ProcedureReturn MouseEvent()\Gadget\MouseX
          Case #MouseY
            ProcedureReturn MouseEvent()\Gadget\MouseY
          Case #Gadget
            ProcedureReturn MouseEvent()\Gadget\Last
        EndSelect

      EndIf  
      
    EndIf
    
    ProcedureReturn #PB_Default
  EndProcedure
  
EndModule

;- ========  Module - Example ========

CompilerIf #PB_Compiler_IsMainFile
  
  Enumeration 
    #Window
    #Button
    #CheckBox
  EndEnumeration
  
  If OpenWindow(#Window, 0, 0, 140, 100, "Example", #PB_Window_SystemMenu|#PB_Window_Tool|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)
    
    ButtonGadget(#Button, 20, 20, 100, 30, "Button")
    CheckBoxGadget(#CheckBox, 20, 65, 100, 20, "CheckBoxGadget")
    
    MouseEvent::Add(#Window)

    quitWindow = #False
    
    Repeat
      Select WaitWindowEvent() 
        Case #PB_Event_CloseWindow
          quitWindow = #True
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #Button
              Select EventType()
                Case #PB_EventType_MouseEnter
                  Debug "MouseEnter: #Button"
                Case #PB_EventType_MouseLeave
                  Debug "MouseLeave: #Button"
                Case #PB_EventType_MouseMove
                  Debug "MouseMove (#Button): " +  Str(MouseEvent::GetAttribute(#Window, MouseEvent::#MouseX)) + " / " + Str(MouseEvent::GetAttribute(#Window, MouseEvent::#MouseY))
              EndSelect  
            Case #CheckBox
              Select EventType()
                Case #PB_EventType_MouseEnter
                  Debug "MouseEnter: #CheckBox"
                Case #PB_EventType_MouseLeave
                  Debug "MouseLeave: #CheckBox"
                Case #PB_EventType_MouseMove
                  Debug "MouseMove (#CheckBox): " +  Str(MouseEvent::GetAttribute(#Window, MouseEvent::#MouseX)) + " / " + Str(MouseEvent::GetAttribute(#Window, MouseEvent::#MouseY))
              EndSelect
          EndSelect
      EndSelect  
    Until quitWindow
    
    CloseWindow(#Window)
  EndIf 
  
CompilerEndIf
Download of PureBasic - Module
Download of PureBasic - Programmes

[Windows 11 x64] [PB V6]

Bild