Canvas and Mouse events

Just starting out? Need help? Post your questions and find answers here.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Canvas and Mouse events

Post by collectordave »

Just doing a bit on a canvas.

When I use #PB_EventType_LeftButtonDown

No matter how long I hold it I still get #PB_EventType_LeftClick and soon as let the mouse button go.

Is it possible to differentiaqte between left down and up and click events?

regards

CD
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Canvas and Mouse events

Post by TI-994A »

collectordave wrote:Is it possible to differentiate between left down and up and click events?
The #PB_EventType_LeftClick event essentially constitutes a mouse down event followed by a mouse up event. Accordingly, all three events will fire on a single mouse click.

A timer would be the simplest, cross-platform approach to handling them separately.

Code: Select all

Case #PB_EventType_LeftClick
  If ElapsedMilliseconds() - mouseDown < 500                
    Debug "Left mouse click..."  
  EndIf              
Case #PB_EventType_LeftButtonDown
  mouseDown = ElapsedMilliseconds()
  Debug "Left mouse down..."
Case #PB_EventType_LeftButtonUp              
  Debug "Left mouse up..."
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Canvas and Mouse events

Post by Josh »

Code: Select all

OpenWindow(0, 0, 0, 220, 220, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 10, 10, 200, 200)
    
Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Gadget And EventGadget() = 0 

    If EventType() = #PB_EventType_LeftButtonDown : Debug "LeftButtonDown" : EndIf
    If EventType() = #PB_EventType_LeftButtonUp   : Debug "LeftButtonUp"   : EndIf
    If EventType() = #PB_EventType_LeftClick      : Debug "LeftClick"      : EndIf

  EndIf
Until Event = #PB_Event_CloseWindow
  • In Windows, it is a default behavior that the Click-Event is triggered on MouseUp, no matter how much time has passed since the MouseDown.
  • For the Click-Event, MouseDown and MouseUp must be done in the same gadget.
  • If the mouse was moved between MouseDown and MouseUp, in some cases no Click-Event will be executed.
sorry for my bad english
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Canvas and Mouse events

Post by collectordave »

Thanks for the replies put me on the right track.

Maybe should have explained more.

I have three distinct pieces of code.

1. Should only be executed when the mouse button is down and not when clicked at all.

2. Should only be executed when the mouse button is released after the code for the mouse down event has been executed.

3. Should only be executed on a mouse click event not mousedown\mouseup

The following code seems to do the trick

Code: Select all

Global ClickTimer.i,MouseDownTime.i,MouseDown.i,JustAClick.i

ClickTimer = 300 ;milliseconds If button released in this time then clicked

OpenWindow(0, 0, 0, 220, 220, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 10, 10, 200, 200)

  Mouseup = #False
  MouseDown = #False



Repeat
  Event = WaitWindowEvent()

  
  
  Select Event
     
    Case #PB_Event_Gadget
 
      Select EventGadget()
 
        Case 0
         

          
          Select EventType()
             
            Case #PB_EventType_LeftButtonDown
             
              MouseDownTime = ElapsedMilliseconds()
              
              MouseDown = #False
              JustAClick = #False
              While ((ElapsedMilliseconds() - MouseDownTime) < ClickTimer) And JustAClick = #False
                WaitWindowEvent(1)
                If EventGadget() = 0 And EventType() = #PB_EventType_LeftButtonUp
                  JustAClick = #True
                EndIf       
              Wend
              
              If JustAClick = #True
                JustAClick = #False 
              Else
                Debug "MouseDown"
                MouseDown = #True
              EndIf
             
            Case #PB_EventType_LeftButtonUp
              MouseDown = #False
              Debug "LeftButtonUp Code"   
   
            Case #PB_EventType_LeftClick

              If ElapsedMilliseconds() - MouseDownTime < ClickTimer
                Debug "LeftClick Code"
              EndIf
              
            Case #PB_EventType_MouseMove
              
              If MouseDown = #True
                
                Debug "Mouse Down Code"
                
              EndIf
              
              
              
          EndSelect
      EndSelect
  EndSelect
 
Until Event = #PB_Event_CloseWindow
Regards

CD
Last edited by collectordave on Mon Feb 25, 2019 5:12 pm, edited 1 time in total.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: Canvas and Mouse events

Post by mestnyi »

This does not fit?

Code: Select all

OpenWindow(0, 0, 0, 220, 220, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 10, 10, 200, 200)

Define down, up

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Select EventType()
            Case #PB_EventType_MouseMove
              If down
                up = 1
                Debug "LeftButtonDown Code" 
                down = 0
              EndIf
              
            Case #PB_EventType_LeftButtonDown : down = 1 
            Case #PB_EventType_LeftButtonUp   
              If up
                Debug "LeftButtonUp Code"  
                up = 0
              Else
                Debug "LeftClick Code"
              EndIf
              down = 0
              
            Case #PB_EventType_LeftClick 
              
          EndSelect
      EndSelect
  EndSelect
  
Until Event = #PB_Event_CloseWindow
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Canvas and Mouse events

Post by Josh »

Sorry Dave, but I would simply describe this code as unusable. Two WaitWindowEvent() in one thread is only causing problems. For example, your code for LeftButtonDown will only be executed when another event occurs, such as a MouseMove event. What else can happen if events are swallowed by your code, you have to imagine for yourself.

Your code for LeftClick seems ok, but for LeftButtonDown I would revise that again. How you execute a code at LeftButtonDown is shown in the help of the CanvasGadget.
sorry for my bad english
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Canvas and Mouse events

Post by TI-994A »

collectordave wrote:...three distinct pieces of code.
1. Should only be executed when the mouse button is down and not when clicked at all.
2. Should only be executed when the mouse button is released after the code for the mouse down event has been executed.
3. Should only be executed on a mouse click event not mousedown\mouseup
Since there's no way of knowing beforehand whether the event is going to be a normal or long click, the only way to isolate the mouse down event would be after the mouse up event. Binding the mouse events of the canvas gadget would be the best approach.

Code: Select all

Procedure ClickHandler()
  Static lastEvent, doClick
  Select EventType()
    Case #PB_EventType_LeftButtonDown
      Debug "execute unconditional mouse DOWN code..."
    Case #PB_EventType_LeftButtonUp
      If ElapsedMilliseconds() - lastEvent > 200
        Debug "execute no-click mouse DOWN code..."
        Debug "execute no-click mouse UP code..."
      Else
        doClick = #True
      EndIf
    Case #PB_EventType_LeftClick
      If doClick
        Debug "execute mouse CLICK code..."
        doClick = #False
      EndIf
  EndSelect  
  lastEvent = ElapsedMilliseconds()
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, 0, 0, 300, 200, "Canvas Mouse Handler", wFlags)
CanvasGadget(0, 0, 0, 300, 200)
BindGadgetEvent(0, @ClickHandler(), #PB_EventType_LeftClick)
BindGadgetEvent(0, @ClickHandler(), #PB_EventType_LeftButtonUp)
BindGadgetEvent(0, @ClickHandler(), #PB_EventType_LeftButtonDown)
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Derren
Enthusiast
Enthusiast
Posts: 313
Joined: Sat Jul 23, 2011 1:13 am
Location: Germany

Re: Canvas and Mouse events

Post by Derren »

Is your mouse up and down event for a drag function?
If so, I would rather check the distance themouse moved between down and up. i.e. if it the mouse didn't move more than 10px it was a click. if it moved more than that, it might have been a drag.
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: Canvas and Mouse events

Post by collectordave »

The mouse events are for a drag type event on the canvas somrtimes foe simply moving an object etc.

The mouseup event stops the drag function

The click event positions another object.

So when a mouse down event is detected it needs to see the mouse move events but only when it is a definite mousedown.

The only way I can see to differentiate is as TI-994A has posted and that is to insert a short delay from the mousedown event before registering a mousedown.

The problem with my above posted code is when someone with a very steady hand clicks and holds the mouse button the windowevent loop waits forever. Added a (1) after waitwindowevent and all is fine a few other minor changes and I have all three events isolated.

The mousedown event is registered only after a specific period of time set by ClickTimer.

The left Buttonup event is only triggered after a mousedown event has been registered and the click event is only fired if a mouseupevent happens in the ClickTimer time after a mousedown event.

I have reposted the code above with amendments.

Run The code

Click Just click event
Hold After a time Mousedown is registered
Let go of button Up event fired with no click event

CD
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Canvas and Mouse events

Post by TI-994A »

The same bind event code, with an added timer to emulate a long press on the mouse button:

Code: Select all

Procedure ClickHandler()
  Static lastEvent, doClick, longPress
  If EventTimer() = 0 And longPress > 0
    longPress + 1
    If longPress > 10
      longPress = 0
      Debug "execute mouse DOWN code..."  
    EndIf    
  EndIf  
  Select EventType()
    Case #PB_EventType_LeftButtonDown
      longPress + 1      
      lastEvent = ElapsedMilliseconds()
    Case #PB_EventType_LeftButtonUp
      longPress = 0
      If ElapsedMilliseconds() - lastEvent > 1000
        Debug "execute mouse UP code..."
      Else
        doClick = #True
      EndIf              
    Case #PB_EventType_LeftClick
      If doClick
        doClick = #False
        Debug "execute mouse CLICK code..."        
      EndIf
    Case #PB_EventType_MouseMove
      ;Debug "execute mouse MOVE code..."      
  EndSelect    
EndProcedure

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, 0, 0, 300, 200, "Canvas Mouse Handler", wFlags)
CanvasGadget(0, 0, 0, 300, 200)
AddWindowTimer(0, 0, 100)
BindEvent(#PB_Event_Timer, @ClickHandler()) 
BindGadgetEvent(0, @ClickHandler(), #PB_EventType_LeftClick)
BindGadgetEvent(0, @ClickHandler(), #PB_EventType_MouseMove)
BindGadgetEvent(0, @ClickHandler(), #PB_EventType_LeftButtonUp)
BindGadgetEvent(0, @ClickHandler(), #PB_EventType_LeftButtonDown)
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Canvas and Mouse events

Post by Mijikai »

same idea different code

Code: Select all

tick.q
OpenWindow(0,0,0,320,200,"canvas",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(0,0,0,320,200)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      If EventGadget() = 0
        Select EventType()   
          Case #PB_EventType_MouseEnter
            tick = 0
          Case #PB_EventType_MouseLeave
            tick = 0
          Case #PB_EventType_LeftButtonUp
            If Not tick = 0
              If ElapsedMilliseconds() - tick > 80
                PostEvent(#PB_Event_FirstCustomValue,0,0,1)
                tick = 0  
              Else
                PostEvent(#PB_Event_FirstCustomValue,0,0,2)
              EndIf
            Else
              PostEvent(#PB_Event_FirstCustomValue,0,0,2)
            EndIf 
          Case #PB_EventType_LeftButtonDown
            tick = ElapsedMilliseconds()
        EndSelect
      EndIf 
    Case #PB_Event_FirstCustomValue
      Debug 123
      If EventType() = 1
        Debug "RELEASE"
      Else
        Debug "UP"
      EndIf   
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Canvas and Mouse events

Post by mk-soft »

LeftClick, LeftButtonDoubleClick, MiddleButtonClick, MiddleButtonDoubleClick, RightButtonClick, RightButtonDoubleClick

Link: http://www.purebasic.fr/english/viewtop ... 12&t=66856

Code: Select all

;-TOP
; Example Canvas Mouse Events


; Include: Module Advanced Gadget Functions (AGF)
; Link   : http://www.purebasic.fr/english/viewtopic.php?f=12&t=66856

IncludeFile "AdvancedGadgetFunctions.pb"

UseModule AGF

Define Event

If OpenWindow(0, 0, 0, 220, 220, "Canvas Mouse Clicks", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  CanvasGadget(0, 10, 10, 200, 200)
  BindGadgetEvent(0, @CheckCanvasMouse())
  
  Repeat
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Gadget
      Select EventGadget()
        Case 0
          Select EventType()
            Case #My_EventType_LeftButtonClick
              Debug "Left Button Click"
            Case #My_EventType_LeftButtonDoubleClick
              Debug "Left Button DoubleClick"
            Case #My_EventType_MiddleButtonClick
              Debug "Middle Button Click"
            Case #My_EventType_MiddleButtonDoubleClick
              Debug "Middle Button DoubleClick"
            Case #My_EventType_RightButtonClick
              Debug "Right Button Click"
            Case #My_EventType_RightButtonDoubleClick
              Debug "Right Button DoubleClick"
            Case #My_EventType_MouseWheelUp
              Debug "MouseWheel Up: " + EventData()
            Case #My_EventType_MouseWheelDown
              Debug "MouseWheel Down: " + EventData()
          EndSelect
      EndSelect
      
    EndIf
    
  Until Event = #PB_Event_CloseWindow
EndIf
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Derren
Enthusiast
Enthusiast
Posts: 313
Joined: Sat Jul 23, 2011 1:13 am
Location: Germany

Re: Canvas and Mouse events

Post by Derren »

If your code should place a new object when clicking, and still being able to move an object when dragging, then this whole timer thing doesn't make much sense.
Simply ignore the click event. Instead, check if your cursor is over an existing object when the mouse_down effect fires.
Then, either move the object along with the cursor, or do nothing.
Upon the mouse_up event, check whether you dragged an object along or not. if not, simply place a new one at the current cursor position.


Granted, this code needs refinement, like collision/overlapping handling. But if you're not trying to drag two pieces at once by clicking on the overlapping area, this code handles drag and drop as well as simple clicking to place objects.

Code: Select all


#size = 50
NewList objects.point()

AddElement(objects())
objects()\x = 10
objects()\y = 10

AddElement(objects())
objects()\x = 50
objects()\y = 200

Define x,y, offset_x, offset_y
Define e
Define drag ;flag


Macro DrawBoxes()
	Box(0,0,500,500,$FFFFFF)
	ForEach objects()
		Box(objects()\x, objects()\y, #size, #size, $0000CC)
	Next 
EndMacro  

OpenWindow(0, 0, 0, 500, 500, "LMB = Place & Move, RMB = Delete", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 500, 500)


StartDrawing(CanvasOutput(0))
DrawBoxes()
StopDrawing()

Repeat
	e=WaitWindowEvent()
	If e=#PB_Event_Gadget
		If EventGadget()=0
			x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
			y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
			Select EventType()
					
				Case #PB_EventType_MouseMove 
					If drag=#True
						StartDrawing(CanvasOutput(0))
						DrawBoxes()
						Box(x-offset_x, y-offset_y, #size, #size, $FF9900)
						StopDrawing()
					EndIf 
					
					
				Case #PB_EventType_LeftButtonDown
					ForEach objects()
						If x>objects()\x And x<objects()\x+#size And y>objects()\y And y<objects()\y+#size
							drag = #True
							offset_x = x - objects()\x 
							offset_y = y - objects()\y 
							DeleteElement(objects())
						EndIf 
					Next 
					
				Case #PB_EventType_LeftButtonUp
					
					AddElement(objects())
					If drag=#True
						objects()\x = x-offset_x
						objects()\y = y-offset_y
					Else 
						objects()\x = x-#size/2
						objects()\y = y-#size/2
					EndIf 
					drag=#False
					StartDrawing(CanvasOutput(0))
					DrawBoxes()
					StopDrawing()
					
				Case #PB_EventType_RightButtonUp	
					ForEach objects()
						If x>objects()\x And x<objects()\x+#size And y>objects()\y And y<objects()\y+#size
							DeleteElement(objects())
						EndIf 
					Next 
					StartDrawing(CanvasOutput(0))
					DrawBoxes()
					StopDrawing()
					
			EndSelect
		EndIf 
	EndIf 
Until e=#PB_Event_CloseWindow
End 
Post Reply