Page 1 of 1

[Windows] MouseEvent

Posted: Fri Mar 25, 2011 8:47 pm
by atomo
Hi :)

This is a small file to include in your projects, it can intercept mouse events on gadgets.

List of handled events:
  • - #MouseEvent_EventType_Click
    - #MouseEvent_EventType_DoubleClick
    - #MouseEvent_EventType_Push
    - #MouseEvent_EventType_Release
    - #MouseEvent_EventType_Hover
    - #MouseEvent_EventType_Leave
    - #MouseEvent_EventType_Drag
    - #MouseEvent_EventType_DragStart
    - #MouseEvent_EventType_DragStop
    - #MouseEvent_EventType_Move
    - #MouseEvent_EventType_WheelUp
    - #MouseEvent_EventType_WheelDown
Include file:

Code: Select all

Enumeration
  #MouseEvent_EventType_Click
  #MouseEvent_EventType_DoubleClick
  #MouseEvent_EventType_Push
  #MouseEvent_EventType_Release
  #MouseEvent_EventType_Hover
  #MouseEvent_EventType_Leave
  #MouseEvent_EventType_Drag
  #MouseEvent_EventType_DragStart
  #MouseEvent_EventType_DragStop
  #MouseEvent_EventType_Move
  #MouseEvent_EventType_WheelUp
  #MouseEvent_EventType_WheelDown
EndEnumeration

Structure MouseEvent_MouseButton
  Button.b
  Key.i
  isPushed.b
  isDragged.b
  Timestamp.i
EndStructure

Structure MouseEvent_Gadget
  Gadget.i
  GadgetID.i
  MouseHover.b
  List MouseButton.MouseEvent_MouseButton()
EndStructure

Structure MouseEvent_EventStack
  Gadget.i
  EventType.b
  Button.b
EndStructure

Threaded NewList MouseEvent_Gadget.MouseEvent_Gadget()
Threaded NewList MouseEvent_EventStack.MouseEvent_EventStack()

Threaded MouseEvent_MouseX, MouseEvent_MouseY
Threaded MouseEventGadget, MouseEventType, MouseEventButton

Procedure isMouseButton(Button)
  If GetAsyncKeyState_(Button) & 32768
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure SendMouseEvent(Gadget, EventType, Button)
  LastElement(MouseEvent_EventStack())
  AddElement(MouseEvent_EventStack())
  MouseEvent_EventStack()\Gadget = Gadget
  MouseEvent_EventStack()\EventType = EventType
  MouseEvent_EventStack()\Button = Button
EndProcedure

Procedure MouseEvent(WindowEvent)
  If DesktopMouseX() <> MouseEvent_MouseX Or DesktopMouseY() <> MouseEvent_MouseY
    MouseEvent_MouseX = DesktopMouseX() : MouseEvent_MouseY = DesktopMouseY()
    isMouseMoved = #True
  EndIf
  Window = WindowFromPoint_(MouseEvent_MouseY<<32|MouseEvent_MouseX)
  
  ForEach MouseEvent_Gadget()
    ;{ MouseHover
    If MouseEvent_Gadget()\GadgetID = Window
      If MouseEvent_Gadget()\MouseHover = #False
        SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_Hover, 0)
        MouseEvent_Gadget()\MouseHover = #True
        ForEach MouseEvent_Gadget()\MouseButton()
          If MouseEvent_Gadget()\MouseButton()\isPushed = #False
            MouseEvent_Gadget()\MouseButton()\isPushed = -1
          EndIf
        Next
      EndIf
    Else
      If MouseEvent_Gadget()\MouseHover = #True
        SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_Leave, 0)
        MouseEvent_Gadget()\MouseHover = #False
      EndIf
    EndIf
    ;}
    ;{ MouseButton
    ForEach MouseEvent_Gadget()\MouseButton()
      If isMouseButton(MouseEvent_Gadget()\MouseButton()\Key) = #True
        If MouseEvent_Gadget()\MouseHover = #True
          If MouseEvent_Gadget()\MouseButton()\isPushed = #False
            SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_Push, MouseEvent_Gadget()\MouseButton()\Button)
            MouseEvent_Gadget()\MouseButton()\isPushed = #True
          EndIf
        EndIf
      Else
        If MouseEvent_Gadget()\MouseButton()\isPushed = #True
          If MouseEvent_Gadget()\MouseButton()\isDragged = #False
            If MouseEvent_Gadget()\MouseHover = #True
              If ElapsedMilliseconds()-MouseEvent_Gadget()\MouseButton()\Timestamp <= 500
                SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_DoubleClick, MouseEvent_Gadget()\MouseButton()\Button)
                MouseEvent_Gadget()\MouseButton()\Timestamp = 0
              Else
                SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_Click, MouseEvent_Gadget()\MouseButton()\Button)
                MouseEvent_Gadget()\MouseButton()\Timestamp = ElapsedMilliseconds()
              EndIf
            EndIf
          Else
            SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_DragStop, MouseEvent_Gadget()\MouseButton()\Button)
            MouseEvent_Gadget()\MouseButton()\isDragged = #False
          EndIf
          SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_Release, MouseEvent_Gadget()\MouseButton()\Button)
        EndIf
        MouseEvent_Gadget()\MouseButton()\isPushed = #False
      EndIf
    Next
    ;}
    ;{ MouseWheel
    If WindowEvent = #WM_MOUSEWHEEL
      If MouseEvent_Gadget()\MouseHover = #True
        If EventwParam() > 0
          SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_WheelUp, 0)
        Else
          SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_WheelDown, 0)
        EndIf
      EndIf
    EndIf
    ;}
    ;{ MouseMovement
    If isMouseMoved = #True
      ForEach MouseEvent_Gadget()\MouseButton()
        If MouseEvent_Gadget()\MouseButton()\isPushed = #True
          If MouseEvent_Gadget()\MouseButton()\isDragged = #False
            SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_DragStart, MouseEvent_Gadget()\MouseButton()\Button)
            MouseEvent_Gadget()\MouseButton()\isDragged = #True
          EndIf
          SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_Drag, MouseEvent_Gadget()\MouseButton()\Button)
        EndIf
      Next
      If MouseEvent_Gadget()\MouseHover = #True
        SendMouseEvent(MouseEvent_Gadget()\Gadget, #MouseEvent_EventType_Move, 0)
      EndIf
    EndIf
    ;}
  Next
  
  ;Return Event
  If ListSize(MouseEvent_EventStack())
    FirstElement(MouseEvent_EventStack())
    MouseEventGadget = MouseEvent_EventStack()\Gadget
    MouseEventType = MouseEvent_EventStack()\EventType
    MouseEventButton = MouseEvent_EventStack()\Button
    DeleteElement(MouseEvent_EventStack())
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure MouseEventGadget()
  ProcedureReturn MouseEventGadget
EndProcedure

Procedure MouseEventType()
  ProcedureReturn MouseEventType
EndProcedure

Procedure MouseEventButton()
  ProcedureReturn MouseEventButton
EndProcedure

Procedure isMouseEventGadget(Gadget)
  ForEach MouseEvent_Gadget()
    If MouseEvent_Gadget()\Gadget = Gadget
      ProcedureReturn #True
    EndIf
  Next
EndProcedure

Macro MouseEvent_AddMouseButton(_Button, _Key)
  AddElement(MouseEvent_Gadget()\MouseButton())
  MouseEvent_Gadget()\MouseButton()\Button = _Button
  MouseEvent_Gadget()\MouseButton()\Key = _Key
EndMacro

Procedure AddMouseEventGadget(Gadget)
  If isMouseEventGadget(Gadget) = #False
    AddElement(MouseEvent_Gadget())
    MouseEvent_Gadget()\Gadget = Gadget
    MouseEvent_Gadget()\GadgetID = GadgetID(Gadget)
    MouseEvent_AddMouseButton(#PB_MouseButton_Left, #VK_LBUTTON)
    MouseEvent_AddMouseButton(#PB_MouseButton_Middle, #VK_MBUTTON)
    MouseEvent_AddMouseButton(#PB_MouseButton_Right, #VK_RBUTTON)
  EndIf
EndProcedure

Procedure RemoveMouseEventGadget(Gadget)
  ForEach MouseEvent_Gadget()
    If MouseEvent_Gadget()\Gadget = Gadget
      DeleteElement(MouseEvent_Gadget())
      Break
    EndIf
  Next
EndProcedure
A small snippet:

Code: Select all

IncludeFile "MouseEvent.pbi"

Window = OpenWindow(#PB_Any, 0, 0, 200, 200, "Window", #PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered)
If Window
  
  ContainerGadget = ContainerGadget(#PB_Any, 50, 50, 100, 100, #PB_Container_Flat)
    SetGadgetColor(ContainerGadget, #PB_Gadget_BackColor, #White)
    AddMouseEventGadget(ContainerGadget)
  CloseGadgetList()

  Repeat
    Event = WaitWindowEvent(1)
    If MouseEvent(Event)
      Select MouseEventGadget()
        Case ContainerGadget
          Select MouseEventType()
            Case #MouseEvent_EventType_Click
              Debug "Click : B"+Str(MouseEventButton())
            Case #MouseEvent_EventType_DoubleClick
              Debug "DoubleClick : B"+Str(MouseEventButton())
            Case #MouseEvent_EventType_Push
              Debug "Push : B"+Str(MouseEventButton())
            Case #MouseEvent_EventType_Release
              Debug "Release : B"+Str(MouseEventButton())
            Case #MouseEvent_EventType_Hover
              Debug "Hover"
            Case #MouseEvent_EventType_Leave
              Debug "Leave"
            Case #MouseEvent_EventType_Drag
              Debug "Drag : B"+Str(MouseEventButton())
            Case #MouseEvent_EventType_DragStart
              Debug "DragStart : B"+Str(MouseEventButton())
            Case #MouseEvent_EventType_DragStop
              Debug "DragStop : B"+Str(MouseEventButton())
            Case #MouseEvent_EventType_Move
              Debug "Move"
            Case #MouseEvent_EventType_WheelUp
              Debug "WheelUp"
            Case #MouseEvent_EventType_WheelDown
              Debug "WheelDown"
          EndSelect
      EndSelect
    EndIf
  Until Event = #PB_Event_CloseWindow
EndIf

Re: [Windows] MouseEvent

Posted: Sat Mar 26, 2011 12:51 am
by TomS
NICE! :shock:
Sorry for shouting, but this is really nice.
Thank you very much for sharing.
This is really appreciated. :D

Re: [Windows] MouseEvent

Posted: Sat Mar 26, 2011 12:55 am
by IdeasVacuum
Nice work, very concise and fast.

A couple of notes:

PB has GetMouseX() and GetMouseY() so those procedures need different names.

Most rodents have at least 3 buttons.......

Re: [Windows] MouseEvent

Posted: Sat Mar 26, 2011 1:13 am
by TomS
IdeasVacuum wrote:PB has GetMouseX() and GetMouseY() so those procedures need different names.
Hm? Which version are talking about?
No such command in my PB. Also PB would've warned him if there was any dublicate names. E.g. "A Procedure can't have the same name as an external command"

The only applicatation where I use the 3rd button is Firefox, to open a link in a new tab.
Any other buttons (4th to whatever, there are mice with 10 and more oO) would be handled by the driver that comes with the mouse, I think.

Re: [Windows] MouseEvent

Posted: Sat Mar 26, 2011 1:23 am
by IdeasVacuum
whoops! My mistake, they are in Droopy's Library. :oops:

I think a lot of people use the middle button, at least for scrolling, but in many apps it's the confirmation button - left for select, right for context menu, middle for 'done'.

Re: [Windows] MouseEvent

Posted: Sat Mar 26, 2011 7:11 pm
by atomo
New events are available :
- #MouseEvent_EventType_MiddleClick
- #MouseEvent_EventType_MiddleDoubleClick
- #MouseEvent_EventType_MiddleButtonPushed
- #MouseEvent_EventType_MiddleButtonReleased
- #MouseEvent_EventType_WheelUp
- #MouseEvent_EventType_WheelDown

Re: [Windows] MouseEvent

Posted: Sat Mar 26, 2011 7:23 pm
by c4s
Great and useful include. Image
Just one question: Is it by design that there is no drag event for middle and right mouse-clicks?

Re: [Windows] MouseEvent

Posted: Sat Mar 26, 2011 8:08 pm
by atomo
c4s wrote:Great and useful include. Image
Just one question: Is it by design that there is no drag event for middle and right mouse-clicks?
Yes, i will add support for middle and right click drag for the next version.

Re: [Windows] MouseEvent

Posted: Mon Mar 28, 2011 6:20 pm
by atomo
- Added events #MouseEvent_EventType_DragStart and #MouseEvent_EventType_DragStop.
- Drag&Drop works with middle and right mouse buttons now.

Re: [Windows] MouseEvent

Posted: Mon Mar 28, 2011 8:07 pm
by c4s
That's great, thank you!