Small Basic – Mouse Position


Mouse Position Methods

There are 2 ways to get the position of the mouse cursor in Small Basic.

gwX = GraphicsWindow.MouseX
gwY = GraphicsWindow.MouseY
 
mX = Mouse.MouseX
mY = Mouse.MouseY

GraphicsWindow.MouseX(Y)

The GraphicsWindow variant gets the X and Y coordinates of the mouse cursor relative to the top left corner of the GraphicsWindow.  These coordinates are the same as pixel coordinates within the GraphicsWindow.  We can then use these to move a shape within the GraphicsWindow or otherwise detect and use the current mouse position within the GraphicsWindow.

Recall that (X,Y) coordinates are X pixels from the left and Y pixels from the top.

ball = Shapes.AddEllipse(50,50)
While ("True")
  Shapes.Move(ball,GraphicsWindow.MouseX-25,GraphicsWindow.MouseY-25)
  Program.Delay(20)
EndWhile

Mouse.MouseX(Y)

The Mouse variant is less commonly used and it gets the X and Y coordinates of the mouse cursor relative to the top left of the desktop, even if no GraphicsWindow is present.

One feature of the Mouse variant is that we can also change or move the mouse cursor to any coordinates we want on the desktop.  The GraphicsWindow variant cannot be used to set the mouse position.

We can find a dispacement (offset) between the desktop and GraphicsWindow coordinates to position the cursur as we want within the GraphicsWindow.

'Position Mouse over a ball
ball = Shapes.AddEllipse(50,50)
While ("True")
  xPos = 25+Math.GetRandomNumber(GraphicsWindow.Width-50)
  yPos = 25+Math.GetRandomNumber(GraphicsWindow.Height-50)
  Shapes.Move(ball,xPos-25,yPos-25)
  offsetX = Mouse.MouseX-GraphicsWindow.MouseX
  offsetY = Mouse.MouseY-GraphicsWindow.MouseY
  Mouse.MouseX = offsetX+xPos
  Mouse.MouseY = offsetY+yPos
  Program.Delay(2000) 'Plenty delay to end program!
EndWhile

Problem

The code above doesn’t work as we might hope, see Mouse Object Bug forum post for Jibba Jabba’s original identification of this problem.

Solution

After some playing I determined that the problem lies in the fact that there is a device dependent scaling difference between GraphicsWindow and Mouse coordinates.

On my display each GraphicsWindow pixel is equal to 1.25 Mouse (device) pixels.

So here is my fix.

'Position Mouse over a ball
ball = Shapes.AddEllipse(50,50)
scale = 1.25
While ("True")
  xPos = 25+Math.GetRandomNumber(GraphicsWindow.Width-50)
  yPos = 25+Math.GetRandomNumber(GraphicsWindow.Height-50)
  Shapes.Move(ball,xPos-25,yPos-25)
  offsetX = Mouse.MouseX/scale-GraphicsWindow.MouseX
  offsetY = Mouse.MouseY/scale-GraphicsWindow.MouseY
  Mouse.MouseX = scale*(offsetX+xPos)
  Mouse.MouseY = scale*(offsetY+yPos)
  Program.Delay(2000) 'Plenty delay to end program!
EndWhile

If the cursor starts outside the GraphcsWindow then it fails (not surprisingly) and in general the scaling may be different for different monitors or display devices.

Also note that the GraphicsWindow coordinates are only updated when the mouse moves (reasonable), but it is done asynchronously and may take a millisecond or so to update and be out of sync with our code.  This slight delay effect initially misled me and also confused the issue when Jibba Jabba was trying to find a workaround.

So I guess this is a bug, not a feature.

Comments (2)

Skip to main content