2015-05-11 3 views
-1

Я разрабатываю программу, которая будет иметь некоторые из тех же функций, что и MS Paint в VB.NET. Следующий код позволяет мне успешно щелкнуть и перетащить, чтобы нарисовать прямоугольник выделения на кадре, но он кажется лагги (особенно по сравнению с самой MS Paint). Есть ли более эффективный способ сделать это?Есть ли более быстрый способ рисовать динамические прямоугольники в VB?

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 
+0

Вероятная скорость/лаг виновником является 'PictureBox'.IIrc, «PictureBox» - это просто изображение «Bitmap», которое завернуто в элемент управления. Чтобы ускорить его до приличного уровня, вам, скорее всего, придется использовать графический API, который по своей природе быстрее. То есть MDX, XNA, SlimDX и т. Д. –

+0

Спасибо EBrown. Я никогда не использовал их; есть ли, в частности, что вы могли бы рекомендовать для воссоздания MS Paint? – RapierMother

+0

Я бы начал с изучения чего-то вроде SlimDX, SFML или подобного. Я не помню сразу, но я думаю, что у них есть элементы управления, которые вы можете перетащить в окно Windows Form/WPF. –

ответ

1

Я не могу воспроизвести laggynes на моем компьютере, так что я не уверен, если это поможет, но попробуйте включить Double Buffering. Вы можете установить его в свойствах Form.

+0

Форма была уже дважды буферизована, но я ценю предложение. Это не супер-лагги, но разница между моим кодом и MS Paint заметно, особенно при увеличении размера окна. – RapierMother

+0

Это зависит от размера. Если приложение будет полноэкранным, вы увидите его. –

0

MS сделали то, что называется Win2D, который

простой в использовании среды выполнения Windows API для немедленного режиме 2D визуализации графики с ускорением GPU.

Я только что попробовал это в первый раз. Вот приблизительное сравнение производительности: PictureBox - 14,5% использования ЦП и CanvasControl - 3,6% (в 4 раза меньше, хотя почти в 5 раз больше использования ОЗУ).

Так что кажется, что Win2D работает быстрее, и на самом деле он прост в использовании, но есть улов. Вы можете использовать его только в приложении Store (для Windows или Windows Phone). Это означает, что он не будет работать в Windows 7. Возьмите его или оставьте. :)


У меня 8-ядерный процессор, поэтому я предполагаю, что 100% загруженное ядро ​​должно отображаться как 12,5% использования ЦП.

PictureBox CPU usage CanvasControl CPU usage


Как создать то же самое приложение с Win2D

  1. Создать пустой магазин App.

    Blank App (Windows)

  2. Если это ваш первый магазин App, то вам будет предложено получить лицензию разработчика; Просто нажмите I Agree.

    Developer License

  3. Добавить Win2D NuGet пакет. (Щелкните правой кнопкой мыши на проект в Solution Explorer>Manage NuGet Packages...)

  4. В 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> 
    
  5. Добавьте все необходимые обработчики событий в коде-за (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