My Problem
When creating a cursor from a bitmap the new cursor hotspot is the center point of that cursor image.
Though I had a nice cursor now, using it posed a challenge for my users. People -rightfully- assume the "fingertip" to be the point where they are pointing at not the center of their cursor.
Problem solved?!
Another Google search brought me the solution. To create my custom cursor (assuming the image is one of my resources) I had this code: Cursor.Current = New Cursor(My.Resources.addCursor.GetHicon())
To create a custom cursor with a custom hotspot I changed it to:
Cursor.Current = FormHelper.CreateCursor(My.Resources.addCursor, New Point(5, 5))
The voodoo happens in the CreateCursor -static- method. Though you're probably not interested, I copied the source anyway:
#Region "Create Custom Cursor"
Private Structure IconInfo
Public fIcon As Boolean
Public xHotspot As Int32
Public yHotspot As Int32
Public hbmMask As IntPtr
Public hbmColor As IntPtr
End Structure
<DllImport("user32.dll", EntryPoint:="CreateIconIndirect")> _
Private Shared Function CreateIconIndirect(ByVal iconInfo As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Public Shared Function DestroyIcon(ByVal handle As IntPtr) As Boolean
End Function
<DllImport("gdi32.dll")> _
Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
End Function
''' <summary>
''' Create a custom winforms cursor with a designated hotspot
''' </summary>
''' <param name="bmp">Image to be used as cursor</param>
''' <param name="hotspot">Hotspot location of the cursor</param>
''' <returns></returns>
''' <remarks>
''' Requires imports:
''' Imports System.Drawing
''' Imports System.Runtime.InteropServices
''' Imports System.Windows.Forms
'''</remarks>
Public Shared Function CreateCursor(ByVal bmp As Bitmap, ByVal hotspot As Point) As Cursor
'Setup the Cursors IconInfo
Dim tmp As New IconInfo
tmp.xHotspot = hotspot.X
tmp.yHotspot = hotspot.Y
tmp.fIcon = False
tmp.hbmMask = bmp.GetHbitmap()
tmp.hbmColor = bmp.GetHbitmap()
'Create the Pointer for the Cursor Icon
Dim pnt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(tmp))
Marshal.StructureToPtr(tmp, pnt, True)
Dim curPtr As IntPtr = CreateIconIndirect(pnt)
'Clean Up
DestroyIcon(pnt)
DeleteObject(tmp.hbmMask)
DeleteObject(tmp.hbmColor)
Return New Cursor(curPtr)
End Function
#End Region
Don't forget the required imports! (In case you it did interest you)
No comments:
Post a Comment