0 Replies - 1157 Views - Last Post: 25 February 2016 - 01:52 PM

#1 IronRazer  Icon User is offline

  • Custom Control Freak
  • member icon

Reputation: 1465
  • View blog
  • Posts: 3,715
  • Joined: 01-February 13

Using Animated and 32bpp Cursors In Your Application

Posted 25 February 2016 - 01:52 PM

As some of you may know already, using custom cursors for you application is a limited capability in VB.Net. Some of those limitations are that you have no way to use animated cursors (.ani) or standard cursors (.cur) that have a 32bpp format.

The Cursor class does not support loading those cursor types from a File or a Stream. However, if you use the Win32 LoadImage Function to load/create the cursor from a file into the memory and get a handle (IntPtr) to the cursor in memory, you can use the Cursor class constructor overload that excepts a handle (IntPtr) to the cursor.

Here is a small helper class you can add to your project to assist you in loading and creating any valid cursor files in your application.

Imports System.Runtime.InteropServices
Imports System.IO

Public Class CursorHelper
    Private Const IMAGE_CURSOR As Integer = &H2
    Private Const LR_LOADFROMFILE As Integer = &H10

    'the unicode LoadImage Win32 Api function is used to load and create the cursor file in memory and give a handle pointing to the cursor
    <DllImport("user32.dll", EntryPoint:="LoadImageW")> _
    Private Shared Function LoadImageW(ByVal hinst As IntPtr, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpszName As String, ByVal uType As UInteger, ByVal cxDesired As Integer, ByVal cyDesired As Integer, ByVal fuLoad As UInteger) As IntPtr
    End Function

    ''' <summary>Loads and returns a standard (.cur) or animated (.ani) cursor from a file. This also works for 32bpp cursors too.</summary>
    ''' <param name="Filename">The full path and file name to the cursor file.</param>
    Public Shared Function LoadCursorFromFile(ByVal Filename As String) As Cursor

        'first make sure the file exists and that it has a valid cursor extension (.cur) or (.ani)
        If Not File.Exists(Filename) OrElse (Path.GetExtension(Filename).ToLower <> ".ani" And Path.GetExtension(Filename).ToLower <> ".cur") Then
            Throw New ArgumentException("Filename does not exist or is not a valid cursor file.", "Filename")
        End If

        'load the cursor file into memory and get the handle that points to the cursor in the memory
        Dim hCursor As IntPtr = LoadImageW(IntPtr.Zero, Filename, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE)

        Dim Crsr As Cursor = Nothing 'declare a cursor to return from this function

        If hCursor <> IntPtr.Zero Then 'make sure the cursor handle is not IntPtr.Zero, which indicates the cursor failed to load
            Crsr = New Cursor(hCursor) 'create a New cursor from the handle to the cursor loaded into memory
        End If

        Return Crsr 'return the cursor
    End Function
End Class


Keep this in mind, in most cases when using cursors in your application, You are responsible for disposing them either when you are done with them or when your Form is closing.

Here is an example of using this helper class in your application if you just want to set a few cursors as a one time deal. This example sets the cursor of the Form to a 32bpp cursor and a Button`s cursor to an animated cursor.
Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
        'set your controls cursors
        Button1.Cursor = CursorHelper.LoadCursorFromFile("C:\TestFolder\MyAnimatedCursor.ani")
        Me.Cursor = CursorHelper.LoadCursorFromFile("C:\TestFolder\My32bppCursor.cur")
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        'I imagine that as the form and all of its controls are disposed that the Cursors would be disposed too since they Implement IDisposable.
        'However, i like to Dispose them myself when the form is closing just to be sure they are destroyed and i have no memory leaks.
        Button1.Cursor.Dispose()
        Me.Cursor.Dispose()
    End Sub

End Class



In the case that you have two or more cursors that you need to load and switch one control`s cursor back and forth between them, then here is how you can do that. In this example i switch a Button`s cursor between two cursors as the mouse in pressed down and released on the Button.
Public Class Form1
    Private ButtonDownCursor As Cursor = Nothing
    Private ButtonUpCursor As Cursor = Nothing

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Load
        'set your controls cursors
        ButtonDownCursor = CursorHelper.LoadCursorFromFile("C:\TestFolder\MyAnimatedCursor.ani")
        ButtonUpCursor = CursorHelper.LoadCursorFromFile("C:\TestFolder\My32bppCursor.cur")

        Button1.Cursor = ButtonUpCursor 'set the ButtonUpCursor to the Button`s cursor
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        'since only one cursor is assigned to the Button`s cursor, we can surely not depend on the Dispose method being called
        'on it when the Form is closing. So, you need to Dispose of the cursors.
        ButtonDownCursor.Dispose()
        ButtonUpCursor.Dispose()
    End Sub

    Private Sub Button1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseDown
        Button1.Cursor = ButtonDownCursor 'when the mouse is down, use the ButtonDownCursor
    End Sub

    Private Sub Button1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseUp
        Button1.Cursor = ButtonUpCursor 'when the button is released, use the ButtonUpCursor
    End Sub
End Class


This post has been edited by IronRazer: 25 February 2016 - 01:58 PM


Is This A Good Question/Topic? 0
  • +

Page 1 of 1