Problem confining pointer to Form
Hi Guys,
I am trying to confine the mouse pointer to the form in a little test app.
So far, I am able to trap all the buttons and wheel action, but when I attempt to limit the pointer movement to the active form, I am encountering an error.
The Error I am getting is " Value does not fall within the expected range. The error occurs on line 122 of my code.
I did have to convert some of the snippets from VB6 code so that is where I may have messed up, but I cannot figure out my mistake.
Code:
Imports System.Deployment.Application
Imports System.Reflection.Emit
Imports System.Windows.Forms.VisualStyles.VisualStyleElement
Public Class Form1
Dim lTwipsX As Long
Dim lTwipsY As Long
Structure RECT
Public left As Long
Public top As Long
Public right As Long
Public bottom As Long
End Structure
Dim RectArea As RECT
Structure POINT
Public x As Long
Public y As Long
End Structure
'Private Declare Function ClipCursor Lib "user32" (lpRect As Any) As Long
Private Declare Function ClipCursor Lib "user32" (lpRect) As Long
Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As Long, lpPoint As POINT) As Long
Private Declare Function OffsetRect Lib "user32" (lpRect As RECT, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Const VK_LBUTTON = &H1
Private Const VK_RBUTTON = &H2
Dim RightClicked As Integer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lTwipsX = My.Computer.Screen.Bounds.Width / 15 ' TwipsPerPixelX
lTwipsY = My.Computer.Screen.Bounds.Height / 15 ' TwipsPerPixelY
For Each c As Control In Controls
AddHandler c.MouseClick, AddressOf ClickHandler
Next
End Sub
Private Sub Form1_MouseEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.MouseEnter
TextBox1.Text = " Mouse Entered "
'displaying "mouse entered" when the mouse pointer enters the form
End Sub
Private Sub Form1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
If e.Button = MouseButtons.Left Then
TextBox2.Text = " Mouse Left click at " + CStr(e.X) + " :" + CStr(e.Y)
ElseIf e.Button = MouseButtons.Right Then
TextBox2.Text = " Mouse Right click at " + CStr(e.X) + " :" + CStr(e.Y)
ElseIf e.Button = MouseButtons.Middle Then
TextBox2.Text = " Mouse Middle click at " + CStr(e.X) + " :" + CStr(e.Y)
Else
'displaying the coordinates when the mouse is pressed on the form
End If
End Sub
Private Sub Form1_MouseLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.MouseLeave
TextBox1.Text = " Mouse Exited "
'displaying "mouse exited" when the mouse pointer leaves the form
End Sub
Private Sub Form1_MouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseClick
If e.Button = MouseButtons.Right Then
RightClicked += CStr(e.Clicks)
TextBox3.Text = " Mouse Right click " + RightClicked.ToString + " times."
'Displaying number of times the mouse right button is pressed and released.
End If
End Sub
Private Sub Form1_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel
If e.Delta > 0 Then
TextBox2.Text = " Mouse Wheel Scrolled UP "
Label1.Text = "Wheel UP"
Else
TextBox2.Text = " Mouse Wheel Scrolled DOWN "
Label1.Text = "Wheel Down"
End If
'If MouseWheel.scrollup Then
' UserZoom = UserZoom + 0.05
'Me.Refresh()
'End If
End Sub
' Source - https://stackoverflow.com/a/37639493
' Posted by Apachi, modified by community. See post 'Timeline' for change history
' Retrieved 2026-03-30, License - CC BY-SA 3.0
Public Sub ClickHandler(sender As Object, e As MouseEventArgs) Handles Me.MouseClick, PictureBox1.MouseClick, Label1.MouseClick, Button1.MouseClick
Label1.Text = String.Format("Clicked ""{0}"" with the {1} mouse button.", sender.name, e.Button.ToString.ToLower)
Select Case e.Button
Case MouseButtons.Left, Label1.Text = "Left"
Case MouseButtons.Right, Label1.Text = "Right"
Case MouseButtons.Middle, Label1.Text = "Middle"
Case Else
Label1.Text = "Some other button"
End Select
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If GetAsyncKeyState(VK_LBUTTON) Then
Label2.Text = "Left Click"
ElseIf GetAsyncKeyState(VK_RBUTTON) Then
Label2.Text = "Right Click"
Else
Label2.Text = ""
End If
End Sub
Private Sub CmdTrap_Click(sender As Object, e As EventArgs) Handles CmdTrap.Click
If CmdTrap.Text = "Trap Cursor" Then
'MsgBox("Cursor Clipped to the Form")
With RectArea
.left = .left / lTwipsX
.top = .top / lTwipsY
.right = .left + Me.Width / lTwipsX
.bottom = .top + Me.Height / lTwipsY
End With
Call ClipCursor(RectArea)
CmdTrap.Text = "Release Cursor"
Else
'MsgBox("Cursor Released")
With RectArea
.left = 0
.top = 0
.right = My.Computer.Screen.Bounds.Width / lTwipsX
.bottom = My.Computer.Screen.Bounds.Height / lTwipsY
End With
Call ClipCursor(RectArea)
CmdTrap.Text = "Trap Cursor"
End If
End Sub
End Class
Regards,
Antony.
Re: Problem confining pointer to Form
You can restrict your cursor with the Cursor.Clip property…
https://learn.microsoft.com/en-us/do...wsdesktop-10.0
As a clue why your API functions aren’t working, you’re using legacy declarations. VB.Net uses 32 bit variables. What was Short is now Integer, what was Long is now Integer. When a Long would’ve been used for a handle, that’s now IntPtr
Code:
Private Declare Function ClipCursor Lib "user32" (lpRect As RECT) As Integer
Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As IntPtr, lpRect As RECT) As Integer
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As IntPtr, lpPoint As POINT) As Integer
Private Declare Function OffsetRect Lib "user32" (lpRect As RECT, ByVal x As Integer, ByVal y As Integer) As Integer
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Integer) As Integer
Private Const VK_LBUTTON As Integer = &H1
Private Const VK_RBUTTON As Integer = &H2
Dim RightClicked As Boolean
Re: Problem confining pointer to Form
Thanks Paul.
Your guidance helped me sort out the clip.cursor function and now it works.
Cheers.
Re: Problem confining pointer to Form
Quote:
Originally Posted by
.paul.
You can restrict your cursor with the Cursor.Clip property…
https://learn.microsoft.com/en-us/do...wsdesktop-10.0
As a clue why your API functions aren’t working, you’re using legacy declarations. VB.Net uses 32 bit variables. What was Short is now Integer, what was Long is now Integer. When a Long would’ve been used for a handle, that’s now IntPtr
Code:
Private Declare Function ClipCursor Lib "user32" (lpRect As RECT) As Integer
Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As IntPtr, lpRect As RECT) As Integer
Private Declare Function ClientToScreen Lib "user32" (ByVal hwnd As IntPtr, lpPoint As POINT) As Integer
Private Declare Function OffsetRect Lib "user32" (lpRect As RECT, ByVal x As Integer, ByVal y As Integer) As Integer
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Integer) As Integer
Private Const VK_LBUTTON As Integer = &H1
Private Const VK_RBUTTON As Integer = &H2
Dim RightClicked As Boolean
Ok… I can see problems there. To clarify…
Short or Int16 is 16 bit
Integer or Int32 is 32 bit
Long or Int64 is 64 bit
IntPtr represents a signed integer where the bit-width is the same as a pointer.
Re: Problem confining pointer to Form
I was originally encountering problems but I understood what was going on and was able to adjust to get it working.
The only difference was in the last line, I couldn't use the Boolean response so I changed it to an integer and was able to get the test to work.
I am now trying to get the clip rect to go back to full screen (I.E. turn clip.cursor on and off as needed.
I can change the dimensions of rect but cannot seem to define coord 0,0, screen height, screen width in pixels or in twips as the acceptable input is only size (width, height) and it assumes that 0,0 is form top left.
Wish it was as simple as define rect(top,left,bottom,right), then clip.cursor.enable or clip.cursor.disable but alas, it is not
Regards,
Antony.
Re: Problem confining pointer to Form
Code:
Cursor.Clip = Me.ClientRectangle
To reset…
Code:
Cursor.Clip = Nothing
Re: Problem confining pointer to Form
RightClicked += CStr(e.Clicks)???
Not sure what you’re doing there? If it’s an Integer, why CStr?
Re: Problem confining pointer to Form
Or save the clip value to a variable before changing it, then you can easily reset it after
Re: Problem confining pointer to Form
Thanks Paul.
It's embarrassing when the fix is so simple.
I have the values in a string and can now toggle it on and off as needed.
Threw away thirtyfive lines of useless code that I created and replaced it with three.
This is a clear case of Nothing being so much more than a stack of code doing nothing.
Thanks again.
Re: Problem confining pointer to Form
You should turn Option Strict on for all of your projects.
To set Option Strict in this dialog box, on the Tools menu, click Options. In the Options dialog box, expand Projects and Solutions, and then click VB Defaults. The initial default setting in VB Defaults is Off.
You’ll find it won’t let you set an Integer with a String. Also, if you have a Rectangle, use a variable of type Rectangle instead of a String…