【问题标题】:How to properly clear or update a drawn rectangle on the screen如何正确清除或更新屏幕上绘制的矩形
【发布时间】:2014-05-15 09:52:47
【问题描述】:

我正在使用半透明表单来捕获鼠标事件,例如 LeftButtonDownLeftButtonUpMouseMove 以便能够选择屏幕上的一个区域在该区域上绘制一个矩形,问题是每次我移动鼠标时都会绘制一个新的矩形,从而产生如下烦人的结果:

当我将鼠标移动到新的鼠标位置时,我只想更新绘制的矩形以期望得到类似这样的结果:

我尝试处置、清除和重新实例化 Graphics 对象,但没有运气,我也见过 this S.O.讨论这个的问题。

这是我正在使用的代码的相关部分:

''' <summary>
''' The Graphics object to draw on the screen.
''' </summary>
Dim ScreenGraphic As Graphics = Graphics.FromHwnd(IntPtr.Zero)

Private Sub MouseEvents_MouseMove(ByVal MouseLocation As Point) Handles MouseEvents.MouseMove

    ' If left mouse button is hold then set the rectangle area...
    If IsMouseLeftDown Then

        ' ... blah blah blah
        ' ... more code here

        ' Draw the rectangle area.
        Me.DrawRectangle()

    End If

''' <summary>
''' Draws the rectangle on the selected area.
''' </summary>
Private Sub DrawRectangle()

    ' Call the "EraseRectanglehere" method here before re-drawing ?
    ' Me.EraseRectangle

    Using pen As New Pen(Me.BorderColor, Me.BorderSize)
        ScreenGraphic.DrawRectangle(pen, SelectionRectangle)
    End Using

End Sub

''' <summary>
''' Erases the last drawn rectangle.
''' </summary>
Private Sub EraseRectangle()

End Sub

如果有人需要更好地检查它,这里是完整的代码:

注意:我已经更新了我在上一个问题编辑中使用的代码。

Imports System.Runtime.InteropServices

Public Class RangeSelector : Inherits Form

#Region " Properties "

    ''' <summary>
    ''' Gets or sets the border size of the range selector.
    ''' </summary>
    ''' <value>The size of the border.</value>
    Public Property BorderSize As Integer = 2

    ''' <summary>
    ''' Gets or sets the border color of the range selector.
    ''' </summary>
    ''' <value>The color of the border.</value>
    Public Property BorderColor As Color = Color.Red

#End Region

#Region " Objects "

    ''' <summary>
    ''' Indicates the initial location when the mouse left button is clicked.
    ''' </summary>
    Private InitialLocation As Point = Point.Empty

    ''' <summary>
    ''' Indicates the rectangle that contains the selected area.
    ''' </summary>
    Private SelectionRectangle As Rectangle = Rectangle.Empty

    ''' <summary>
    ''' The Graphics object to draw on the screen.
    ''' </summary>
    Private ScreenGraphic As Graphics = Graphics.FromHwnd(IntPtr.Zero)

#End Region

#Region " Constructors "

    ''' <summary>
    ''' Initializes a new instance of the <see cref="RangeSelector"/> class.
    ''' </summary>
    Public Sub New()

        InitializeComponent()

    End Sub

    ''' <summary>
    ''' Initializes a new instance of the <see cref="RangeSelector" /> class.
    ''' </summary>
    ''' <param name="BorderSize">Indicates the border size of the range selector.</param>
    ''' <param name="BorderColor">Indicates the border color of the range selector.</param>
    Public Sub New(ByVal BorderSize As Integer, ByVal BorderColor As Color)

        Me.BorderSize = BorderSize
        Me.BorderColor = BorderColor

        InitializeComponent()

    End Sub

#End Region

#Region " Event Handlers "

    Protected Overrides Sub OnMouseDown(e As MouseEventArgs)

        ' MyBase.OnMouseDown(e)
        InitialLocation = e.Location
        SelectionRectangle = New Rectangle(InitialLocation.X, InitialLocation.Y, 0, 0)

    End Sub

    Protected Overrides Sub OnMouseUp(e As MouseEventArgs)

        ' Make the Form transparent to take the region screenshot.
        Me.Opacity = 0.0R

        ' ToDo:
        ' take the screenshot.
        ' Return the selected rectangle area and save it.

        Me.Close()

    End Sub

    Protected Overrides Sub OnMouseMove(e As MouseEventArgs)

        ' If left mouse button is hold then set the rectangle area...
        If e.Button = MouseButtons.Left Then

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

                Me.SelectionRectangle = New Rectangle(e.Location.X,
                                                      e.Location.Y,
                                                      Me.InitialLocation.X - e.Location.X,
                                                      Me.InitialLocation.Y - e.Location.Y)

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

                Me.SelectionRectangle = New Rectangle(Me.InitialLocation.X,
                                                      e.Location.Y,
                                                      e.Location.X - Me.InitialLocation.X,
                                                      Me.InitialLocation.Y - e.Location.Y)

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

                Me.SelectionRectangle = New Rectangle(e.Location.X,
                                                      Me.InitialLocation.Y,
                                                      Me.InitialLocation.X - e.Location.X,
                                                      e.Location.Y - Me.InitialLocation.Y)

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

                Me.SelectionRectangle = New Rectangle(Me.InitialLocation.X,
                                                      Me.InitialLocation.Y,
                                                      e.Location.X - Me.InitialLocation.X,
                                                      e.Location.Y - Me.InitialLocation.Y)
            End If

            ' Draw the rectangle area.
            Me.DrawRectangle()

        End If

    End Sub

#End Region

#Region " Private Methods "

    Private Sub InitializeComponent()

        Me.SuspendLayout()
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None
        Me.BackColor = System.Drawing.Color.Black
        Me.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None
        Me.CausesValidation = False
        Me.ClientSize = New System.Drawing.Size(100, 100)
        Me.ControlBox = False
        Me.Cursor = System.Windows.Forms.Cursors.Cross
        Me.DoubleBuffered = True
        Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None
        Me.MaximizeBox = False
        Me.MinimizeBox = False
        Me.Name = "RangeSelector"
        Me.Opacity = 0.01R
        Me.ShowIcon = False
        Me.ShowInTaskbar = False
        Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
        Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
        Me.TopMost = True
        Me.WindowState = System.Windows.Forms.FormWindowState.Maximized
        Me.ResumeLayout(False)

    End Sub

    ''' <summary>
    ''' Draws the rectangle on the selected area.
    ''' </summary>
    Private Sub DrawRectangle()

        ' Just a weird trick to refresh the painting.
        ' Me.Opacity = 0.0R
        ' Me.Opacity = 0.01R

        ' Using g As Graphics = Graphics.FromHwnd(IntPtr.Zero)

        Using pen As New Pen(Me.BorderColor, Me.BorderSize)
            ScreenGraphic.DrawRectangle(pen, Me.SelectionRectangle)
        End Using

        ' End Using

    End Sub

#End Region

End Class

更新 1

我已经翻译了所有代码以将其用作Form 对话框,以便在选择区域时具有更大的灵活性,我已经替换了上面的整个代码来更新我的问题,代码并没有太大变化使用 LL Hook 捕获鼠标事件我正在处理半透明最大化窗体的鼠标事件,我仍然在 Desktop Screen Graphics 上绘制矩形(而不是在 OnPaint Form 事件上) 那部分代码和你在上面的代码中看到的一样:

Private ScreenGraphic As Graphics = Graphics.FromHwnd(IntPtr.Zero)

...因为我说过表单是半透明的,所以如果我在表单中绘制一个矩形,它也会是半透明的(或者至少我不知道如何避免这种情况) .

然后我发现了一个奇怪的技巧,通过在新坐标中绘制矩形之前更改窗体的不透明度来解决矩形问题:

    Me.Opacity = 0.0R
    Me.Opacity = 0.01R

    Using pen As New Pen(Me.BorderColor, Me.BorderSize)
        ScreenGraphic.DrawRectangle(pen, Me.SelectionRectangle)
    End Using

问题? ...并不完美,它会产生非常烦人的效果,因为我在绘制矩形时会出现很多闪烁(是的,我有 Form doubleBuffered 并且我正在使用 CreateParams 技巧来避免闪烁,但什么都没有)。

更新 2

我已经尝试使用 @Plutonix 在他的评论中指出的 InvalidateRect 函数和这个 API 声明:

<DllImport("user32.dll")>
Private Shared Function InvalidateRect(
        ByVal hWnd As Integer,
        ByRef lpRect As Rectangle,
        ByVal bErase As Boolean) As Boolean
End Function

我尝试将它与False/True 标志一起使用。

问题?问题与我在第一次更新中指出的问题相同:

'并不完美,它会产生非常烦人的效果'因为在绘制矩形时我会出现很多闪烁(是的,我有 Form doubleBuffered,而且我正在使用CreateParams 技巧来避免闪烁,但没有)。'

更新 3

我正在尝试使用 RedrawWindow 函数解决此问题,正如我在 this SO answer 中看到的那样,它可以用来做与 InvalidateRect 函数相同的事情,但也具有更大的灵活性,也许没有我使用InvalidateRect 函数得到的烦人效果,我只需要尝试一下。

RedrawWindow 函数更新指定的矩形或区域 窗口的客户区。

这是 API 声明:

<DllImport("user32.dll")>
Private Shared Function RedrawWindow(
        ByVal hWnd As IntPtr,
        <[In]> ByRef lprcUpdate As Rectangle,
        ByVal hrgnUpdate As IntPtr,
        ByVal flags As RedrawWindowFlags) As Boolean
End Function

<Flags()>
Private Enum RedrawWindowFlags As UInteger
    ''' <summary>
    ''' Invalidates the rectangle or region that you specify in lprcUpdate or hrgnUpdate.
    ''' You can set only one of these parameters to a non-NULL value. If both are NULL, RDW_INVALIDATE invalidates the entire window.
    ''' </summary>
    Invalidate = &H1

    ''' <summary>Causes the OS to post a WM_PAINT message to the window regardless of whether a portion of the window is invalid.</summary>
    InternalPaint = &H2

    ''' <summary>
    ''' Causes the window to receive a WM_ERASEBKGND message when the window is repainted.
    ''' Specify this value in combination with the RDW_INVALIDATE value; otherwise, RDW_ERASE has no effect.
    ''' </summary>
    [Erase] = &H4

    ''' <summary>
    ''' Validates the rectangle or region that you specify in lprcUpdate or hrgnUpdate.
    ''' You can set only one of these parameters to a non-NULL value. If both are NULL, RDW_VALIDATE validates the entire window.
    ''' This value does not affect internal WM_PAINT messages.
    ''' </summary>
    Validate = &H8

    NoInternalPaint = &H10

    ''' <summary>Suppresses any pending WM_ERASEBKGND messages.</summary>
    NoErase = &H20

    ''' <summary>Excludes child windows, if any, from the repainting operation.</summary>
    NoChildren = &H40

    ''' <summary>Includes child windows, if any, in the repainting operation.</summary>
    AllChildren = &H80

    ''' <summary>Causes the affected windows, which you specify by setting the RDW_ALLCHILDREN and RDW_NOCHILDREN values, to receive WM_ERASEBKGND and WM_PAINT messages before the RedrawWindow returns, if necessary.</summary>
    UpdateNow = &H100

    ''' <summary>
    ''' Causes the affected windows, which you specify by setting the RDW_ALLCHILDREN and RDW_NOCHILDREN values, to receive WM_ERASEBKGND messages before RedrawWindow returns, if necessary.
    ''' The affected windows receive WM_PAINT messages at the ordinary time.
    ''' </summary>
    EraseNow = &H200

    Frame = &H400

    NoFrame = &H800
End Enum

我已经尝试使用带有这些参数的函数:

RedrawWindow(IntPtr.Zero, Me.SelectionRectangle, IntPtr.Zero, RedrawWindowFlags.Invalidate)

...我想正如 MSDN 文档所述,如果第一个参数为 NULL,则表示桌面屏幕,第二个参数表示要更新的矩形,如果我指定了第三个参数,则需要为空第二个参数中的矩形,最后一个参数表示一个标志,指示要执行的操作(在这种情况下,像@Plutonix所说的那样使矩形无效?)

我尝试在绘制矩形之后和绘制它之前使用该指令,我的意思是在 OnMouseMove 事件中,或者在我的代码中的 DrawRectangle 方法中,但我看不出有任何区别屏幕,我在绘制矩形时仍然遇到上图中显示的相同问题我的意思是当我移动鼠标时会绘制多个矩形并且此函数会擦除任何矩形,也许我使用了错误的参数? .

【问题讨论】:

  • 也许这会有所帮助:stackoverflow.com/questions/13361234/…
  • @Epistemex 感谢您的评论,但我真的不明白那里发布的“ClearRegion”方法,我需要使用从 C# 到 VB.NET 的在线转换器。反正我要试试,再次感谢。
  • 看答案底部,有完整的VB源码
  • @Epistemex,对不起我的错,解雇了。

标签: .net vb.net graphics gdi+ rectangles


【解决方案1】:

基思的回答基本正确,但缺少一个关键点:

Protected Overrides Sub OnPaint(ByVal e as PaintEventArgs)
    MyBase.OnPaint(e)
    If bClickHolding Then e.Graphics.DrawRectangle(pen:=Pen, rect:=Rect)
End Sub

您应该在绘制事件中进行绘图,而不是在事件处理程序中。

这就是为什么闪烁的原因,因为窗体绘制事件正在帧之间绘制,导致缓冲区被清除。

另外,这里还有一些额外的“黑客”:

Protected Overrides Sub OnPaintBackground(ByVal e as PaintEventArgs)
    Return ' will skip painting the background
    MyBase.OnPaintBackground(e)
End Sub

SetStyle(ControlStyles.ResizeRedraw, True)
SetStyle(ControlStyles.DoubleBuffer, True)
SetStyle(ControlStyles.AllPaintingInWmPaint, True)

不过,您可能应该在面板中绘制它。哦,不要把程序逻辑放在 OnPaint 事件中,把它放在处理程序中,或者放在单独的线程中。

如果您想从另一个控件/类中绘制它,请不要。相反,在主控件的 OnPaint 事件中绘制它,并简单地引用另一个控件中的对象/布尔值/大小、位置。 (即:如果 myBoundingbox.bClickHolding Then...)

一些解释问题的链接(引用自 MSDN):

当创建一个新的自定义控件或继承的控件时 不同的视觉外观,您必须提供代码来呈现 通过重写 OnPaint 方法进行控制。

MSDN - Control.Paint Event

MSDN - Control.OnPaint Method

MSDN - Custom Control Painting and Rendering

嗯,在阅读了关于透明度的那部分之后,我打算建议:(只需设置 .TransparencyKey = Color.Black)但是,绕过鼠标事件,可能需要一些 WndProc 来解决这个问题:MSDN - Form.TransparencyKey Property - 嗯是的,问题是窗口失去焦点。

可能是这样的:MSDN - NativeWindow Class - 但您可能需要使用鼠标钩子,因为您不再接收透明窗口的消息。

另外,这是一种“hack”,在光标后面的背景中绘制一个矩形。问题是,效果滞后于光标,所以如果你快速移动鼠标,它就不起作用。或者也许最好把它放在一个计时器上。我暂时把它留在这里。您可以使用 OnMouseMove 覆盖或 WndProc 方法,但我看不出性能差异。 (编辑:不,计时器不会减少延迟)。

Private Shared mouseNotify() As Int32 = {&H200, &H201, &H204, &H207} ' WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN

Friend Shared Function isOverControl(ByRef theControl As Control) As Boolean
    Return theControl.ClientRectangle.Contains(theControl.PointToClient(Cursor.Position))
End Function

    Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
        'Invalidate()
        MyBase.OnMouseMove(e)
    End Sub

    Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaintBackground(e)
        Dim x As Integer = PointToClient(Cursor.Position).X - 5
        Dim y As Integer = PointToClient(Cursor.Position).Y - 5
        e.Graphics.DrawRectangle(New Pen(Brushes.Aqua, 1), 0, 0, ClientRectangle.Width - 1, ClientRectangle.Height - 1)
        e.Graphics.FillRectangle(Brushes.Aqua, x, y, 10, 10)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        If mouseNotify.Contains(CInt(m.Msg)) Then
            If isOverControl(Me) Then Invalidate()
        End If
        MyBase.WndProc(m)
    End Sub

【讨论】:

  • 啊,是的,流畅多了。我的错。谢谢你。更新了我的帖子,因为这是一种更好/正确的方法。
【解决方案2】:

解决方案更简单,不需要 Windows API。只需创建一个透明的并在其上绘制红色矩形。以下代码执行此操作,您只需要以半透明形式替换。闪烁是因为我们清理图形然后绘制,避免它的最简单方法是立即绘制,所以如果我们在位图上绘制矩形然后绘制位图,操作是一步完成的,并且闪烁不会发生。

绘图将在绘图窗体的 OnPaintBackground 上完成,因此需要一个绘图窗体。这是捕获事件的主类:

Public Class YourFormClass

    Dim Start As Point
    Dim DrawSize As Size
    Public DrawRect As Rectangle
    Public Drawing As Boolean = False
    Dim Info As Label
    Dim DrawForm As Form

    Private Sub YourFormClass_Load(sender As Object, e As EventArgs) Handles Me.Load
        ' Add any initialization after the InitializeComponent() call.
        ControlBox = False
        WindowState = FormWindowState.Maximized
        FormBorderStyle = Windows.Forms.FormBorderStyle.None
        BackColor = Color.Gray
        Opacity = 0.2

        DrawForm = New DrawingFormClass(Me)
        With DrawForm
            .BackColor = Color.Tomato
            .TopLevel = True
            .TransparencyKey = Color.Tomato
            .TopMost = True
            .FormBorderStyle = Windows.Forms.FormBorderStyle.None
            .ControlBox = False
            .WindowState = FormWindowState.Maximized
        End With

        Info = New Label
        With Info
            .Top = 16
            .Left = 16
            .ForeColor = Color.White
            .AutoSize = True
            DrawForm.Controls.Add(Info)
        End With

        Me.AddOwnedForm(DrawForm)
        DrawForm.Show()
    End Sub

    Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
        Drawing = True
        Start = e.Location
    End Sub

    Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
        If Drawing Then
            DrawSize = New Size(e.X - Start.X, e.Y - Start.Y)
            DrawRect = New Rectangle(Start, DrawSize)

            If DrawRect.Height < 0 Then
                DrawRect.Height = Math.Abs(DrawRect.Height)
                DrawRect.Y -= DrawRect.Height
            End If

            If DrawRect.Width < 0 Then
                DrawRect.Width = Math.Abs(DrawRect.Width)
                DrawRect.X -= DrawRect.Width
            End If

            Info.Text = DrawRect.ToString
            DrawForm.Invalidate()
        End If
    End Sub

    Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
        Drawing = False
    End Sub

End Class

由于绘图将在 OnPaintBackground 中完成,因此需要第二个类:

Public Class DrawingFormClass

    Private DrawParent As YourFormClass

    Public Sub New(Parent As YourFormClass)

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Me.DrawParent = YourFormClass
    End Sub

    Protected Overrides Sub OnPaintBackground(e As PaintEventArgs)
        Dim Bg As Bitmap
        Dim Canvas As Graphics


        If DrawParent.Drawing Then
            Bg = New Bitmap(Width, Height)
            Canvas = Graphics.FromImage(Bg)
            Canvas.Clear(Color.Tomato)
            Canvas.DrawRectangle(Pens.Red, DrawParent.DrawRect)
            Canvas.Dispose()
            e.Graphics.DrawImage(Bg, 0, 0, Width, Height)

            Bg.Dispose()
        Else
            MyBase.OnPaintBackground(e)
        End If

    End Sub

End Class

只需创建两个窗体并粘贴...它将创建绘图窗体并绘制红色矩形创建一个位图缓冲区,因此在绘图时只执行一个操作。这工作得很好,没有闪烁。希望对您有所帮助!

【讨论】:

  • 谢谢,但我已经尝试过了,它只显示了一个 TopMost 透明表单,但我无法“绘制”任何东西,当我按下左键时它什么也不做。我错过了什么?
  • 我猜到了主窗体的一些属性...我已经编辑并添加了所需的属性,现在它可以工作了,你能试试吗?
  • 是的,现在它在我身边工作了,太棒了,当矩形一直被重绘时,你的表单仍然闪烁,但至少比我的开始方法闪烁少得多,谢谢。
  • 我尝试设置“DrawForm”的“DoubleBuffered”属性但没有成功,它说它受到保护,您能否扩展您的解决方案以避免矩形闪烁?我会很感激的,谢谢
  • 当然!编辑和更新......现在没有闪烁。希望对您有所帮助!
【解决方案3】:

希望对您有所帮助。


更新 1:重新编写代码。处理向后选择矩形、较少检查等。清理它。

更新 2:更新以反映猪排的更正。


Public Class SelectionRectTesting

    Private pCurrent As Point
    Private pStart As Point
    Private pStop As Point

    Private Rect As Rectangle
    Private Graphics As Graphics
    Private Pen As New Pen(Color.Red, 1)

    Private bClickHolding = False

    Private Sub SelectionRectTestingLoad(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        SetStyle(ControlStyles.ResizeRedraw, True)
        SetStyle(ControlStyles.DoubleBuffer, True)
        SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    End Sub

    Private Sub HandleMouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
        bClickHolding = True
        pStart.X = e.X
        pStart.Y = e.Y
    End Sub

    Private Sub HandleMouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
        If bClickHolding = True Then
            pCurrent.X = e.X
            pCurrent.Y = e.Y

            If pCurrent.X < pStart.X Then
                Rect.X = pCurrent.X
                Rect.Width = pStart.X - pCurrent.X
            Else
                Rect.X = pStart.X
                Rect.Width = pCurrent.X - pStart.X
            End If

            If pCurrent.Y < pStart.Y Then
                Rect.Y = pCurrent.Y
                Rect.Height = pStart.Y - pCurrent.Y
            Else
                Rect.Y = pStart.Y
                Rect.Height = pCurrent.Y - pStart.Y
            End If

            Invalidate()
        End If
    End Sub

    Private Sub HandleMouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp
        bClickHolding = False
        Invalidate()
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        MyBase.OnPaint(e)
        If bClickHolding Then
            e.Graphics.DrawRectangle(pen:=Pen, rect:=Rect)
        End If
    End Sub

    Protected Overrides Sub OnPaintBackground(ByVal e As PaintEventArgs)
        Return ' will skip painting the background
        MyBase.OnPaintBackground(e)
    End Sub

End Class

【讨论】:

  • 感谢您尝试提供帮助,但您的代码无法以任何方式帮助我,代码与我在问题中发布的代码基本相同,但您在表单中绘图。我没有假装冒犯你,但你读过我的问题和我遇到的问题吗?我真的不明白你为什么意识到那个代码,但无论如何谢谢
  • 如果我看错了,我深表歉意。昨天看了,今天写了个笔记写代码,你回复我后又看了两遍,呵呵。我认为目标是一次正确地绘制一个选择矩形,并在按住按钮移动鼠标时更新它,不留下以前绘制的矩形。我发布的代码正是这样做的。如果我误解了,再次抱歉。
  • 是的,这正是我想要的,但在表单之外,正如我在我的问题中澄清的那样,我试图在屏幕上而不是在表单内绘制矩形,原因是我没有找到了一种使用透明表单的方法,然后我在屏幕上绘制矩形,但再次感谢您的帮助!
  • Keith 真的你的代码运行得很好,没有任何烦人的效果,但要明白这不是我想要的,除非你能找到方法来适应我的需求,如@ ZeroWorks类似的代码,对不起我的英语,我的意思是我需要选择屏幕的一个区域,然后使用不透明的表格我认为它无法帮助我,并且使用透明的表格我无法绘制该表单内的可见矩形会导致透明度,但也许我错了,可以这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多