Pregunta

I need to show a region selector on my application to select a rectangle region over the screen.

I've taken and tried to modify to my needs this code example of Hans Passant, the code selects an area with the mouse and draw a rectangle, it works only on a form and not on the screen ...but that is a problem for later 'cause first what I need is improve the functionality of this selector.

At the moment the rectangle selection can be done only starting from top-left to right-bottom, I need a more flexible selection to draw in all directions in one step (I mean a rectangle that can be able to select to right, left, bottom, up, etc)

A real example of the selection flexibility that I need is basically like the Windows Explorer selector does:

enter image description here

What more changes I should do in my code?:

PS: I also accept a cleaver way to mimic the Windows selection rectangle flexibility (maybe using the WinAPI?).

Public Class Form1

Dim SelectionRectangle As Rectangle

Private Shadows Sub Load() Handles MyBase.Load
    Me.DoubleBuffered = True
End Sub

Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
    SelectionRectangle = New Rectangle(e.X, e.Y, 0, 0)
    Me.Invalidate()
End Sub

Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)

    If SelectionRectangle.Width > 0 AndAlso SelectionRectangle.Height > 0 Then

        Dim sb As New System.Text.StringBuilder
        sb.AppendFormat("Selection Location: {0}", SelectionRectangle.Location.ToString)
        sb.AppendLine()
        sb.AppendFormat("Selection Size: {0}", SelectionRectangle.Size.ToString)
        MessageBox.Show(sb.ToString)

    End If

End Sub

Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)

    If e.Button = MouseButtons.Left _
    AndAlso (SelectionRectangle.Right >= SelectionRectangle.X) _
    AndAlso (SelectionRectangle.Bottom >= SelectionRectangle.Y) Then

        SelectionRectangle = New Rectangle(SelectionRectangle.Left,
                                           SelectionRectangle.Top,
                                           e.X - SelectionRectangle.Left,
                                           e.Y - SelectionRectangle.Top)
        Me.Invalidate()

    Else
        SelectionRectangle = New Rectangle(SelectionRectangle.X,
                                           SelectionRectangle.Y,
                                           0, 0)
    End If

End Sub

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

    Using pen As New Pen(Color.Red, 1)
        e.Graphics.DrawRectangle(pen, SelectionRectangle)
    End Using

End Sub

End Class
¿Fue útil?

Solución 2

Solution according to @Digital_Utopia comment:

This way works with the same flexibility as the windows explorer selector, except that the rectangle is not filled with a color and the rectangle is not 'released' after 'mouse up' 'cause that is not what I need.

Dim SelectionRectangle As Rectangle
Dim InitialPosition As Point

Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
    ' Store the starting coordinates
    InitialPosition = e.Location
    SelectionRectangle = New Rectangle(InitialPosition.X, InitialPosition.Y, 0, 0)
    Me.Invalidate()
End Sub

Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)

    ' Me.SuspendLayout()

    If e.Button = MouseButtons.Left Then

        If (e.Location.X < InitialPosition.X) _
        AndAlso (e.Location.Y < InitialPosition.Y) Then ' Top-Left

            SelectionRectangle = New Rectangle(e.X,
                                               e.Y,
                                               InitialPosition.X - e.X,
                                               InitialPosition.Y - e.Y)

        ElseIf (e.Location.X > InitialPosition.X) _
        AndAlso (e.Location.Y < InitialPosition.Y) Then ' Top-Right

            SelectionRectangle = New Rectangle(InitialPosition.X,
                                               e.Y,
                                               e.X - InitialPosition.X,
                                               InitialPosition.Y - e.Y)

        ElseIf (e.Location.X < InitialPosition.X) _
        AndAlso (e.Location.Y > InitialPosition.Y) Then ' Bottom-Left

            SelectionRectangle = New Rectangle(e.X,
                                               InitialPosition.Y,
                                               InitialPosition.X - e.X,
                                               e.Y - InitialPosition.Y)

        ElseIf (e.Location.X > InitialPosition.X) _
        AndAlso (e.Location.Y > InitialPosition.Y) Then ' Bottom-Right

            SelectionRectangle = New Rectangle(InitialPosition.X,
                                               InitialPosition.Y,
                                               e.X - InitialPosition.X,
                                               e.Y - InitialPosition.Y)
        End If

        Me.Invalidate()

    End If

    ' Me.ResumeLayout()

End Sub

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

    Using pen As New Pen(Color.Red, 1)
        e.Graphics.DrawRectangle(pen, SelectionRectangle)
    End Using

End Sub

Otros consejos

maybe you can find something usefull inside of the source of the GreenShot application!? http://sourceforge.net/projects/greenshot/

Because the use a rectangle trap to select the area for the Screenshot you need!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top