Search code examples
vb.netwinformsmouse-position

Rectangular hole dimensions isn't equals to real mouse position on my computer screen


I had searching on internet about how draw a rectangular hole on Form, and I found this good example in Delphi language, then I have tried reproduce this example in VB.NET, until now I had success in draw the rectangle hole on Form, but the dimensions this rectangle is not correspond with real mouse position on my computer screen

And also relative to Delphi example, had dificulties for adapt ClientToScreen function to my example, that probably could be solution for this problem.

Someone could help me with this, please?

Here is my last attempt:

 <DllImport("user32.dll")> _
    Private Shared Function ClientToScreen(ByVal hWnd As IntPtr, ByRef lpPoint As Point) As Boolean
    End Function

    Dim mRect As Rectangle

    Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
        mRect = New Rectangle(e.X, e.Y, 0, 0)
        Me.Invalidate()
    End Sub

    Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)

        If e.Button = Windows.Forms.MouseButtons.Left Then

            Dim gp As New System.Drawing.Drawing2D.GraphicsPath

            gp.AddRectangle(New Rectangle(0, 0, Me.Width, Me.Height))

            mRect = New Rectangle(mRect.Left, mRect.Top, e.X - mRect.Left, e.Y - mRect.Top)

            gp.AddRectangle(mRect)

            Me.Region = New Region(gp)

            Me.Invalidate()
        End If
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        Using pen As New Pen(Color.Red, 3)
            e.Graphics.DrawRectangle(pen, mRect)
        End Using
    End Sub

That produces the following: result


Solution

  • Option 1

    You can calculate the distance between top left point of form and top left point of its client area using Me.PointToClient(Me.Location) and use it when you want to calculate location:

    Code

    Public Class HoleForm
        Dim mRect As Rectangle
        Dim d
        Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
            mRect = New Rectangle(e.X - d.x, e.Y - d.y, 0, 0)
            Me.Invalidate()
        End Sub
    
        Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
    
            If e.Button = Windows.Forms.MouseButtons.Left Then
    
                Dim gp As New System.Drawing.Drawing2D.GraphicsPath
    
                gp.AddRectangle(New Rectangle(0, 0, Me.Width, Me.Height))
    
                mRect = New Rectangle(mRect.Left, mRect.Top, e.X - d.x - mRect.Left, e.Y - d.y - mRect.Top)
    
                gp.AddRectangle(mRect)
    
                Me.Region = New Region(gp)
    
                Me.Invalidate()
            End If
        End Sub
    
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            Dim mRect2 = New Rectangle(mRect.Location, mRect.Size)
            mRect2.Offset(d)
            Using pen As New Pen(Color.Red, 3)
                e.Graphics.DrawRectangle(pen, mRect2)
            End Using
        End Sub
    
        Private Sub HoleForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            d = Me.PointToClient(Me.Location)
        End Sub
    End Class
    

    Screenshot

    enter image description here

    Option2

    You can use Me.TransparencyKey= Color.Red and fill the rectangle with red color, then it will be a hole as you expect.

    Code

    Public Class HoleForm
        Public Sub New()
    
            ' This call is required by the designer.
            InitializeComponent()
    
            ' Add any initialization after the InitializeComponent() call.
            Me.TransparencyKey = Color.Red
        End Sub
        Dim mRect As Rectangle
        Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
            mRect = New Rectangle(e.X, e.Y, 0, 0)
            Me.Invalidate()
            MyBase.OnMouseDown(e)
        End Sub
        Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
    
            If e.Button = Windows.Forms.MouseButtons.Left Then
                mRect = New Rectangle(mRect.Left, mRect.Top, e.X - mRect.Left, e.Y - mRect.Top)
                Me.Invalidate()
            End If
        End Sub
    
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            Using HoleBrush As New SolidBrush(Me.TransparencyKey)
                e.Graphics.FillRectangle(HoleBrush, mRect)
            End Using
            Using BorderPen As New Pen(Color.Blue, 3)
                e.Graphics.DrawRectangle(BorderPen, mRect)
            End Using
        End Sub
    End Class
    

    Screenshot

    enter image description here