有没有更快的方法在VB中绘制动态矩形?

时间:2015-05-11 13:48:28

标签: vb.net drawing invalidation

我正在设计一个与VB.NET中的MS Paint具有相同功能的程序。下面的代码允许我成功地单击并拖动以在图片框上绘制选择矩形,但它看起来很滞后(特别是与MS Paint本身相比)。有没有更有效的方法呢?

Public DrawCapture As Boolean = False
Public DrawCaptureOrigin As Point
Public DrawCaptureRectangle As Rectangle

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    DrawCapture = True
    DrawCaptureOrigin = e.Location
    DrawCaptureRectangle = New Rectangle(e.Location, New Point(1, 1))
End Sub

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    Dim curX As Integer = e.Location.X, curY As Integer = e.Location.Y
    Dim dcoX As Integer = DrawCaptureOrigin.X, dcoY As Integer = DrawCaptureOrigin.Y
    If DrawCapture Then
        If curX < dcoX And curY < dcoY Then
            DrawCaptureRectangle = New Rectangle(curX, curY, dcoX - curX, dcoY - curY)
        ElseIf curX < dcoX Then
            DrawCaptureRectangle = New Rectangle(curX, dcoY, dcoX - curX, curY - dcoY)
        ElseIf curY < dcoY Then
            DrawCaptureRectangle = New Rectangle(dcoX, curY, curX - dcoX, dcoY - curY)
        Else
            DrawCaptureRectangle = New Rectangle(dcoX, dcoY, curX - dcoX, curY - dcoY)
        End If
        PictureBox1.Invalidate()
    End If
End Sub

Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    DrawCapture = False
    PictureBox1.Invalidate()
End Sub

Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    If DrawCaptureRectangle.Width > 0 Then
        e.Graphics.DrawRectangle(Pens.Black, DrawCaptureRectangle)
    End If
End Sub

2 个答案:

答案 0 :(得分:1)

我无法在我的电脑上重现laggynes,所以我不确定这是否会有所帮助,但请尝试启用Double Buffering。您可以在Form属性中设置它。

答案 1 :(得分:0)

MS已经制作了一个名为Win2D的东西,它是

  

易于使用的Windows Runtime API,可通过GPU加速实现即时模式2D图形渲染。

我刚刚第一次试用了它。以下是性能的粗略比较:PictureBox - 14.5%CPU使用率和CanvasControl - 3.6%(减少4倍;尽管RAM使用率几乎是其中的5倍)。

所以看起来Win2D工作得更快,实际上很容易使用,但有一个问题。您只能将其用于Store App(适用于Windows或Windows Phone)。这意味着它不能在Windows 7上运行。接受或离开它。 :)

我有8核CPU,所以我假设100%加载的核心应该显示为12.5%的CPU使用率。

PictureBox CPU usage CanvasControl CPU usage

如何使用Win2D创建相同的应用程序

  1. 创建空白商店应用

    Blank App (Windows)

  2. 如果这是您的第一个商店应用,那么您将被要求获得开发者许可;只需点击I Agree

    Developer License

  3. 添加Win2D NuGet包。 (在Solution Explorer&gt; Manage NuGet Packages...

  4. 中右键点击您的项目
  5. MainPage.xaml添加CanvasControl。将其视为PictureBox的替代。

    <Page
        x:Class="Win2D_VBNET.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Win2D_VBNET"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
        mc:Ignorable="d">
    
        <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <canvas:CanvasControl ClearColor="White"
                                  Draw="CanvasControl_Draw"
                                  PointerPressed="CanvasControl_PointerPressed"
                                  PointerMoved="CanvasControl_PointerMoved"
                                  PointerReleased="CanvasControl_PointerReleased"/>
        </Grid>
    </Page>
    
  6. 在代码隐藏中添加所有必要的事件处理程序(MainPage.xaml.vb)。代码与您的代码完全相同。

    Imports Microsoft.Graphics.Canvas.UI.Xaml
    Imports Windows.UI
    Imports Microsoft.Graphics.Canvas
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        Public DrawCapture As Boolean = False
        Public DrawCaptureOrigin As Point
        Public DrawCaptureRectangle As Rect
    
        Private Sub CanvasControl_PointerPressed(sender As CanvasControl, e As PointerRoutedEventArgs)
            Dim location As Point = e.GetCurrentPoint(Nothing).Position
            DrawCapture = True
            DrawCaptureOrigin = location
            DrawCaptureRectangle = New Rect(location, New Size(1, 1))
        End Sub
    
        Private Sub CanvasControl_PointerMoved(sender As CanvasControl, e As PointerRoutedEventArgs)
            Dim location As Point = e.GetCurrentPoint(Nothing).Position
            Dim curX As Integer = location.X, curY As Integer = location.Y
            Dim dcoX As Integer = DrawCaptureOrigin.X, dcoY As Integer = DrawCaptureOrigin.Y
            If DrawCapture Then
                If curX < dcoX And curY < dcoY Then
                    DrawCaptureRectangle = New Rect(curX, curY, dcoX - curX, dcoY - curY)
                ElseIf curX < dcoX Then
                    DrawCaptureRectangle = New Rect(curX, dcoY, dcoX - curX, curY - dcoY)
                ElseIf curY < dcoY Then
                    DrawCaptureRectangle = New Rect(dcoX, curY, curX - dcoX, dcoY - curY)
                Else
                    DrawCaptureRectangle = New Rect(dcoX, dcoY, curX - dcoX, curY - dcoY)
                End If
            End If
            sender.Invalidate()
        End Sub
    
        Private Sub CanvasControl_PointerReleased(sender As CanvasControl, e As PointerRoutedEventArgs)
            DrawCapture = False
            sender.Invalidate()
        End Sub
    
        Private Sub CanvasControl_Draw(sender As CanvasControl, args As CanvasDrawEventArgs)
            If DrawCaptureRectangle.Width > 0 Then
                args.DrawingSession.Antialiasing = CanvasAntialiasing.Aliased
                args.DrawingSession.DrawRectangle(DrawCaptureRectangle, Colors.Black)
            End If
        End Sub
    
    End Class