Wie Cursorbild drehen lassen

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von chris_2091.

    Wie Cursorbild drehen lassen

    Hallo zusammen,

    ich verwende mein eigenes Bild als Cursor

    VB.NET-Quellcode

    1. Cursor = CursorFromImage("C:\...\eigenerCursor.png") 'Bild laden
    . Hier die Funktion:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Cursor aus einem Bild laden
    2. Private Function CursorFromImage(ByVal imagePath As String) As Cursor
    3. Using img As Image = Image.FromFile(imagePath)
    4. Using btm As New Bitmap(img)
    5. Dim ptrCur As IntPtr = btm.GetHicon
    6. Dim cur As New Cursor(ptrCur)
    7. Return cur
    8. End Using
    9. End Using
    10. End Function

    Das funktioniert problemlos.
    Als nächstes wollte ich das Cursorbild drehen lassen, auf Basis von Winkeln die ein Sensor ausspukt. Da habe ich folgende sehr hilfreicher Link hier im Forum gefunden: vb-paradise.de/index.php/Thread/?postID=171927#post171927
    Ich habe als Basis den Code von @yeti2078 übernommen.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Drawing2D
    2. Imports System.Math
    3. Public Class Form1
    4. Private WithEvents t As New Timer
    5. Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    6. 'Dim f2 As Pen = New Pen(Color.BlueViolet, 3)'sorgt nur für einen Pfeil
    7. Dim winkel As Double = GetAngle()' keine Eingangsparameter
    8. e.Graphics.TranslateTransform(-155, -155)
    9. e.Graphics.RotateTransform(-90 + winkel, MatrixOrder.Append)
    10. e.Graphics.TranslateTransform(155, 155, MatrixOrder.Append)
    11. e.Graphics.DrawImage(My.Resources.eigenerCursor, New Rectangle(0, 0, 310, 310), New Rectangle(New Point(0, 0), My.Resources.eigenerCursor.Size), GraphicsUnit.Pixel)
    12. 'e.Graphics.DrawLine(f2, 155, 155, 280, 155)
    13. 'f2.Dispose()
    14. End Sub
    15. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles t.Tick
    16. Me.Invalidate()
    17. End Sub
    18. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    19. winkel_x = 0
    20. Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer, True)
    21. t.Interval = 100
    22. t.Start()
    23. End Sub
    24. 'Winkel bestimmen
    25. Private Function GetAngle() As Double
    26. If sendenAnSensor = 0 Then ' Senden der Request-Nachricht war erfolgreich
    27. Dim rMsg As Sensor.FreespaceMessage_Read 'Nachricht die gelesen werden soll definiert
    28. rMsg.motionEngineOutput.meData = DirectCast(Array.CreateInstance(GetType(Byte), 44), Byte()) 'Array der Struktur motionEngineOutput instanzieren
    29. Dim daten_Beschleunigung As Sensor.MultiAxisSensor 'Paket in das die Winkelgeschwindigkeiten in x,y,z und w kommen
    30. Sensor.freespace_util_getAngularVelocity(rMsg.motionEngineOutput, daten_Beschleunigung)
    31. winkel_x = winkel_x + daten_Beschleunigung.x'daten_Beschleunigung.x ist vom Typ single
    32. End If
    33. Return winkel_x

    1.Problem: winkel_x zeigt die ganze Zeit über 0, obwohl ich an anderer Stelle (mit dem gleichen Code) Werte ungleich null bekomme.
    Kann man double nicht mit single addieren? Die Request-Nachricht habe ich im Form1Load-Event implementiert und die if-Bedingung wird erfüllt(habe Breakpoints gesetzt)
    2.Problem: Mit dem Code wird ja das Bild aus den Ressourcen geladen und dann rotiert, wie kann das Cursorbild direkt genommen werden?

    Ich danke für Eure Hilfe im Voraus!!
    @chris_2091 Wenn Du dir Cursors nicht selbst malen willst, probier mal dies:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. <System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="LoadCursorFromFile", _
    3. SetLastError:=True, CharSet:=CharSet.Unicode)> _
    4. Private Shared Function LoadCursorFromFile(ByVal Filename As String) As IntPtr
    5. End Function
    6. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7. Using dlg = New OpenFileDialog
    8. dlg.Filter = "Cursors|*.cur;*.ani|All Files|*.*"
    9. If dlg.ShowDialog() <> Windows.Forms.DialogResult.OK Then
    10. Return
    11. End If
    12. Me.LoadCursor(dlg.FileName)
    13. End Using
    14. End Sub
    15. Private Sub LoadCursor(path As String)
    16. Dim ptr = Form1.LoadCursorFromFile(path)
    17. Me.Cursor = New Cursor(ptr)
    18. End Sub
    19. End Class
    Und animierte Cursor findest Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo zusammen,

    ich verwende ein eigenes Bild als Cursor, wie oben beschrieben. Das mit dem Winkel habe ich ebenfalls hin gekriegt (war ein Fehler in der Nachricht)

    Ich habe das ganze so gelöst, das ich zuerst das Originalbild in einer Zwischenvariable gespeichert habe und diese dann drehen lasse und erst dann das Bild als Cursor verwende, das
    funktioniert problemlos. Allerdings ist das Bild nicht quadratisch, sprich es wird was abgeschnitten, wenn es zum Beispiel um 90° gedreht wurde.
    Daher wollte ich mit den Methoden Draw oder DrawStrechted den Cursor vergrößern leider klappt das nicht. Es ändert gar nichts an der Größe des Cursors-

    VB.NET-Quellcode

    1. 'im Load-Event
    2. cursorabbild = Image.FromFile("~\eigenerCursor.png") 'Zwischenspeichern des Bildes
    3. '*************************Drehen des Cursors (Timer-Event)**********************************************************
    4. Dim bild = RotateImageByAngle(cursorabbild, rollen) 'Bild drehen
    5. Dim grafik As Graphics = Graphics.FromImage(bild) '
    6. Dim cursorgroesse As New Rectangle(Cursor.Position.X - cursorabbild.Width, Cursor.Position.Y - cursorabbild.Height, 2 * cursorabbild.Width, 2 * cursorabbild.Height)
    7. Cursor = BildalsCursor(bild) 'Verwendung des Bildes als Cursors
    8. Cursor.Draw(grafik, cursorgroesse)


    Wie verwendet man am besten Draw und DrawStrechted ?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „chris_2091“ ()

    @chris_2091 Ich würde das Bild so bearbeiten, dass es vollständig in den In-Kreis des Cursor-Quadrats passt, da hast Du keine Probleme mehr.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Vielen Dank @RodFromGermany !!!
    habe um das Bild in PowerPoint einfach einen quadratischen unsichtbaren Rahmen gelegt und es klappt. ;)
    Allerdings sollte das Bild nicht zu groß sein (ca. 1,8cm * 1,8cm), da das ansonsten auch abgeschnitten wird.

    Allerdings bekomme ich manchmal nach einiger Zeit folgenden Fehler:
    An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll

    Additional information: Allgemeiner Fehler in GDI+.

    und zwar bei der Funktion BildalsCursor:

    VB.NET-Quellcode

    1. Private Function BildalsCursor(ByVal image As Image) As Cursor
    2. Using btm As New Bitmap(image)
    3. Dim ptrCur As IntPtr = btm.GetHicon'!! hier trifft der Fehler auf
    4. Dim cur As New Cursor(ptrCur)
    5. Return cur
    6. End Using
    7. End Function


    Edit: der Fehler entsteht wohl weil ich das Bild aus einem Pfad herauslade, siehe dazu [url]http://stackoverflow.com/…fter-using-savefiledialog[/url], ich habe das Bild in meine Ressourcen geladen (was wahrscheinlich eh mehr Sinn hat) und benutze es daraus und seitdem habe ich den Fehler nicht mehr bekommen.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „chris_2091“ ()

    chris_2091 schrieb:

    nicht zu groß sein (ca. 1,8cm * 1,8cm)
    Wie groß ist Dein Bildschirm? :thumbsup:
    Bilder musst Du in Pixel angeben, da ist die Bildschirmgröße egal.
    32 * 32 Pixel oder so.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo zusammen,

    leider habe ich mich geirrt.

    chris_2091 schrieb:

    benutze es daraus und seitdem habe ich den Fehler nicht mehr bekommen



    Leider bekomme ich den Fehler nach einiger Zeit trotzdem und ich habe dazu nichts hilfreiches im Internet gefunden.

    VB.NET-Quellcode

    1. ​Private Function BildalsCursor(ByVal image As Image) As Cursor
    2. Using btm As New Bitmap(image)
    3. Dim ptrCur As IntPtr = btm.GetHicon
    4. Dim cur As New Cursor(ptrCur)
    5. 'DestroyHandle()
    6. btm.Dispose()
    7. Return cur
    8. cur.Dispose()
    9. Marshal.FreeHGlobal(ptrCur)
    10. Marshal.FreeHGlobal(btm.GetHicon)
    11. End Using
    12. End Function


    Hat jemand vielleicht eine Idee?
    Vielen Dank!
    @chris_2091 ohne das jetzt voll zu durchsteigen, würde ich Deinen Code so schreiben (ungetestet):

    VB.NET-Quellcode

    1. Private Function BildalsCursor(ByVal image As Image) As Cursor
    2. Dim ptrCur As IntPtr = IntPtr.Zero
    3. Try
    4. Using btm As New Bitmap(image)
    5. ptrCur = btm.GetHicon
    6. Return New Cursor(ptrCur)
    7. End Using
    8. Finally
    9. If ptrCur <> IntPtr.Zero Then
    10. 'DestroyHandle()
    11. Marshal.FreeHGlobal(ptrCur)
    12. End If
    13. End Try
    14. End Function

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Vielen Dank für Deine schnelle Antwort.
    Leider kommt beim Starten der Form folgender Fehler:

    An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll

    Additional information: Das Handle ist ungültig. (Ausnahme von HRESULT: 0x80070006 (E_HANDLE))

    der Fehler ensteht wohl bei ​Marshal.FreeHGlobal(ptrCur)
    @jvbsl Jou.
    @chris_2091 Ich hab mal die MSDN befragt, da ist dieses Beispiel zu finden.
    Oben in Deine Klasse:

    VB.NET-Quellcode

    1. <System.Runtime.InteropServices.DllImportAttribute("user32.dll")> Private Shared Function DestroyIcon(ByVal handle As IntPtr) As Boolean
    und dann muss der Aufrufer von BildalsCursor() dies aufrufen:

    VB.NET-Quellcode

    1. DestroyIcon(icon.Handle)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @jvbsl und @RodFromGermany Super! Vielen Dank!

    Ich werde das mal ausprobieren.

    Nachtrag: scheint zu funktionieren.
    nur Marshal.FreeHGlobal(ptrCur)[/tt]muss weg, ansonsten habe ich den gleichen Fheler wie vorher.
    habe das jetzt gelöst:

    VB.NET-Quellcode

    1. Public Class KalibrierungKopfbewegung
    2. 'Import einer Funktion, damit Mauscursor nicht den Speicher zumüllen
    3. <System.Runtime.InteropServices.DllImportAttribute("user32.dll")> Private Shared Function DestroyIcon(ByVal handle As IntPtr) As Boolean
    4. ....
    5. 'Timer-Event
    6. ...
    7. End FunctionCursor = BildalsCursor(bild) 'gedrehtes Bild als Cursor verwenden
    8. DestroyIcon(Cursor.Handle)
    9. ...
    10. Private Function BildalsCursor(ByVal image As Image) As Cursor
    11. Dim ptrCur As IntPtr = IntPtr.Zero
    12. Try
    13. Using btm As New Bitmap(image)
    14. ptrCur = btm.GetHicon
    15. Return New Cursor(ptrCur)
    16. End Using
    17. Finally
    18. If ptrCur <> IntPtr.Zero Then
    19. 'DestroyHandle()
    20. 'Marshal.FreeHGlobal(ptrCur)
    21. End If
    22. End Try
    23. End Function

    oder habe ich das falsch verstanden?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „chris_2091“ ()