[Module] MouseEvents for Gadgets (all OS)

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
User avatar
Thorsten1867
Addict
Addict
Posts: 1366
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

[Module] MouseEvents for Gadgets (all OS)

Post by Thorsten1867 »

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

Code: Select all

;/ ===============================
;/ =    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
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: [Module] MouseEvents for Gadgets (all OS)

Post by RSBasic »

Thank you Image
Image
Image
Post Reply