Visual Basic Forum

Visual Basic Forum
für VB6 und VB.NET Programmierer
 
RegistrierenRegistrieren  LoginLogin
Neues Thema eröffnen   Neue Antwort erstellen    Visual Basic Forum Foren-Übersicht -> [VB.NET] Fragen - Antworten
Autor
Nachricht
Hexer
Newbie
Newbie

Anmeldedatum: 16.12.2010
Beiträge: 2

Ruckeln bei DrawReversibleFrame oder DrawFocusRect
Verfasst am: 16.12.2010, 20:36

Hallo erstmal.
Ich bin neu hier. Und wie das meistens so ist, haben die Neulinge erst einmal ein paar Fragen. Genau so wie meine Wenigkeit.
Ich habe folgendes Problem:

Ich versuche eine Funktion zu implementieren, bei der man ein Objekt (Block) durch drücken der linken Maustaste quasi wie bei Drag&Drop bewegen kann. Um anzuzeigen, daß der Nutzer dieses Objekt mit der Maus hält, möchte ich einen Rahmen der Form des Objektes unter dem Mauszeiger auf dem Bildschirm bewegen. Das Problem ist, wenn ich die Funktion ControlPaint.DrawReversibleFrame verwende, ruckelt dieser Rahmen unendlich stark. Da dieser Rahmen ja nur auf dem Screen/Desktop gezeichnet wird, habe ich etwas rumprobiert und bin auf ein merkwürdiges Phänomen gestoßen. Verwende ich die alte GDI-Funktion DrawFocusRect auf dem DeviceContext der Parent-Form, so kann dieser Frame flüssig auf der Form bewegt werden. Verwende ich die Funktion DrawFocusRect allerdings auf dem DeviceContext des Desktop (genau wie es ja bei der DrawReversibleFrame-Funktion ja üblich ist) so ruckelt der Rahmen bei Bewegung des Mauszeigers (im selbstgebastelten Drag-Modus).

Hier der Test-Quelltext:

Code:
Imports System.Drawing
Public Class Form1
  Dim Block As clBlock
  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    'erst einmal einen neuen Block erstellen, wenn dies noch nicht geschehen ist
    If Block Is Nothing Then
      Block = New clBlock(Me)
      Block.Left = 20
      Block.Top = 20
    End If
  End Sub

  Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    'Wenn der Block bereits existiert, die Farbe des Rahmens ändern
    If Not (Block Is Nothing) Then
      Block.FrameColor = Color.Red
    End If
  End Sub
End Class


Public Class clBlock
  Inherits Control

  Private Declare Function DrawFocusRect Lib "user32" Alias "DrawFocusRect" (ByVal hDC As Integer, ByRef lpRect As RECT) As Integer
  Private Declare Function GetDC Lib "user32" Alias "GetDC" (ByVal hWnd As Integer) As Integer
  Private Declare Function ReleaseDC Lib "user32" Alias "ReleaseDC" (ByVal hWnd As Integer, ByVal DC As Integer) As Integer
  Private Structure RECT
    Dim Left As Integer
    Dim Top As Integer
    Dim Right As Integer
    Dim Bottom As Integer
  End Structure



  'Lokale Variablen
  Private FramePen As Pen
  Private DrawArea As Graphics
  Private MouseDwn As Boolean
  Private Frame As RECT
  Private SrcPt As Point
  Private DrawOnClient As Boolean
  Private Dragging As Boolean

  'Eigenschaften
  Public Property FrameColor()
    Get
      Return (FramePen.Color)
    End Get
    Set(ByVal value)
      FramePen.Color = value
      Me.Refresh()
    End Set
  End Property

  'Konstruktor
  Sub New(ByVal AParent As Control)
    If Not (AParent Is Nothing) Then
      Me.Parent = AParent
    End If
    FramePen = New Pen(Color.Black, 1)
    'eine Standardgröße von 40x40 festlegen
    Me.Width = 40
    Me.Height = 40
    DrawArea = Me.CreateGraphics
    DrawOnClient = False
  End Sub
 
  Private Sub clBlock_Paint(ByVal Sender As Object, ByVal e As PaintEventArgs) Handles Me.Paint
    If Not (DrawArea Is Nothing) Then
      If Visible Then
        DrawArea.DrawRectangle(FramePen, 0, 0, Width - 1, Height - 1)
        DrawArea.DrawRectangle(FramePen, 2, 2, Width - 5, Height - 5)
      End If
    End If
  End Sub
  Private Sub clBlock_MouseDown(ByVal Sender As Object, ByVal e As MouseEventArgs) Handles Me.MouseDown
    MouseDwn = True
    'Quellkoordinaten des Mauszeigers festlegen (iin Client-Koordinaten!)
    SrcPt = e.Location
    Parent.Text = CStr(e.X) + "  ,  " + CStr(e.Y)
  End Sub
  Private Sub clBlock_MouseUp(ByVal Sender As Object, ByVal e As MouseEventArgs) Handles Me.MouseUp
    MouseDwn = False
    If Dragging Then
      Dragging = False
      'ein letztes mal das Frame zeichnen damit keine Rester des Frames auf dem Bildschirm zurückbleiben
      DrawReversibleRect(Frame)
      Me.Visible = True
    End If
  End Sub

  Private Sub clBlock_MouseMove(ByVal Sender As Object, ByVal e As MouseEventArgs) Handles Me.MouseMove
    Dim dx, dy As Integer

    If Dragging Then
      'Veränderung zum
      dx = e.X - SrcPt.X
      dy = e.Y - SrcPt.Y
      'Altes Frame durch neuzeichnen löschen
      DrawReversibleRect(Frame)
      Frame.Left = Left + dx
      Frame.Top = Top + dy
      Frame.Right = Frame.Left + Width
      Frame.Bottom = Frame.Top + Height
      DrawReversibleRect(Frame)
    End If
    If (MouseDwn) And Not (Dragging) Then
      Dragging = True
      Me.Hide()
      dx = e.X - SrcPt.X
      dy = e.Y - SrcPt.Y
      Frame.Left = Left + dx
      Frame.Top = Top + dy
      Frame.Right = Frame.Left + Width
      Frame.Bottom = Frame.Top + Height
      DrawReversibleRect(Frame)
    End If
  End Sub

  Private Sub DrawReversibleRect(ByRef ARect As RECT)
    Dim g As Graphics = Parent.CreateGraphics
    Dim DC As Integer
    Dim BRect As Rectangle
    Dim CRect As RECT
    'Koordinaten von ARect sind Client-Koordinaten
    If DrawOnClient Then
      DC = g.GetHdc.ToInt32
      Call DrawFocusRect(DC, ARect)
    Else
      'Koordinaten konvertieren in Screen-Koordinaten
      DC = GetDC(0)
      BRect = New Rectangle(ARect.Left, ARect.Top, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top)
      BRect = Parent.RectangleToScreen(BRect)
      CRect.Left = BRect.Left
      CRect.Top = BRect.Top
      CRect.Right = BRect.Right
      CRect.Bottom = BRect.Bottom
      Call DrawFocusRect(DC, CRect)
      ReleaseDC(0, DC)
    End If
    g.Dispose()
  End Sub
 
End Class

(Die Form enthält nur zwei Taster [Button1, Button2], wobei nur Button1 zum Test gebraucht wird.)

Zum Test einfach die DrawOnClient = True setzen, damit der Rahmen auf der Form gezeichnet wird und wenn DrawOnClient = False so wird der Rahmen auf dem Desktop gezeichnet.

Nun die Frage:
Was kann der Grund für das Ruckeln, beim Zeichnen auf dem DC des Screen/Desktop sein? Ich habe auch schon die DoubleBuffering-Option auf True gesetzt.

Zusätzliche (vielleicht nützliche) Informationen:
Ich programmiere die Anwendung mit VisualBasic.NET 2008 Express Edition auf Windows 7.
Aero Peek ist aktiviert.

Vielen Dank für die Hilfe schon im Voraus.
Gruß,
Der Hexer.
 
Neues Thema eröffnen   Neue Antwort erstellen    Visual Basic Forum Foren-Übersicht -> [VB.NET] Fragen - Antworten

Tags: windows, ruckelt, rectangle, refresh, express, problem

 
 Verwandte Themen   Aufrufe   Letzter Beitrag 
Keine neuen Beiträge Problem mit always on top funktion 1107 30.10.2009, 12:26
Keine neuen Beiträge IntStr()funktion 1309 11.10.2007, 09:49
Keine neuen Beiträge TopMost Funktion unter DirectX 1022 27.07.2007, 11:48
Keine neuen Beiträge Wie Funktion nutzen ? 1214 29.06.2007, 21:59
Keine neuen Beiträge update funktion einbauen 1455 29.01.2007, 00:11
 


[ Time: 0.0730s ][ Queries: 80 (0.0274s) ][ GZIP on - Debug on ]