How to use WPF Mouse.OverrideCursor in a VB.NET application

Jim Webb 41 Reputation points
2021-01-27T21:30:00.707+00:00

I tried a sample WPF code, that Kareninstructor recommended to me, from https://github.com/karenpayneoregon/visual-basic-getting-started/tree/master/ChangeCursor to test the usage of Mouse.OverrideCursor - this worked beautifully. However, it is a WPF standalone application, and I have not been able to find a way of incorporating the Mouse.OverrideCursor in my VB.NET code (I am writing in Visual Basic using VS 2019).

I need to force my mouse pointer to a custom cursor image when I am performing a drag and drop operation. Mouse.OverrideCursor is the required instruction but I have not been able to get it to work in VB. Any clues or pointers would be more than welcome.

HotIndigo

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,807 questions
VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,764 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. DaisyTian-1203 11,631 Reputation points
    2021-01-28T08:26:23.183+00:00

    I update CursorExample code as below:
    61362-capture.png

    Public Function CreateCursor() As Cursor  
            Dim brush As SolidColorBrush = Brushes.Gold  
            Dim rx As Double = 50  
            Dim ry As Double = 50  
            Dim vis = New DrawingVisual()  
      
      
            Using dc = vis.RenderOpen()  
                dc.DrawRectangle(brush, New Pen(Brushes.Black, 0.1), New Rect(0, 0, rx, ry))  
                dc.Close()  
            End Using  
      
            Dim rtb = New RenderTargetBitmap(64, 64, 96, 96, PixelFormats.Pbgra32)  
            rtb.Render(vis)  
      
            Using ms1 = New MemoryStream()  
                Dim penc = New PngBitmapEncoder()  
                penc.Frames.Add(BitmapFrame.Create(rtb))  
                penc.Save(ms1)  
                Dim pngBytes = ms1.ToArray()  
                Dim size = pngBytes.GetLength(0)  
      
                Using ms = New MemoryStream()  
      
                    If True Then  
                        ms.Write(BitConverter.GetBytes(CType(0, Int16)), 0, 2)  
                        ms.Write(BitConverter.GetBytes(CType(2, Int16)), 0, 2)  
                        ms.Write(BitConverter.GetBytes(CType(1, Int16)), 0, 2)  
                    End If  
      
                    If True Then  
                        ms.WriteByte(32)  
                        ms.WriteByte(32)  
                        ms.WriteByte(0)  
                        ms.WriteByte(0)  
                        ms.Write(BitConverter.GetBytes(CType((rx / 2.0), Int16)), 0, 2)  
                        ms.Write(BitConverter.GetBytes(CType((ry / 2.0), Int16)), 0, 2)  
                        ms.Write(BitConverter.GetBytes(size), 0, 4)  
                        ms.Write(BitConverter.GetBytes(CType(22, Int32)), 0, 4)  
                    End If  
      
                    ms.Write(pngBytes, 0, size)  
                    ms.Seek(0, SeekOrigin.Begin)  
                    Return New Cursor(ms)  
                End Using  
            End Using  
        End Function  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. Karen Payne MVP 35,466 Reputation points
    2021-01-28T13:01:35.947+00:00

    Hello,

    I added to my repository a code sample where in this case I loaded the image from disk, there are of course other ways to load e.g. from resources.

    61386-screen.png

    Full source

    Cursor class

    (has two methods, one to use a bitmap, one for text)

    Option Infer On  
      
    Imports System.Drawing  
    Imports System.Globalization  
    Imports System.IO  
    Imports System.Runtime.InteropServices  
    Imports System.Security.Permissions  
    Imports System.Windows.Interop  
    Imports Microsoft.Win32.SafeHandles  
      
    Public Class CursorHelper  
        Private NotInheritable Class NativeMethods  
            Public Structure IconInfo  
                Public fIcon As Boolean  
                Public xHotspot As Integer  
                Public yHotspot As Integer  
                Public hbmMask As IntPtr  
                Public hbmColor As IntPtr  
            End Structure  
      
            Private Sub New()  
            End Sub  
      
      
            <DllImport("user32.dll")>  
            Public Shared Function CreateIconIndirect(ByRef icon As IconInfo) As SafeIconHandle  
            End Function  
      
            <DllImport("user32.dll")>  
            Public Shared Function DestroyIcon(hIcon As IntPtr) As Boolean  
            End Function  
      
            <DllImport("user32.dll")>  
            Public Shared Function GetIconInfo(  
               hIcon As IntPtr,  
               ByRef pIconInfo As IconInfo) As <MarshalAs(UnmanagedType.Bool)> Boolean  
            End Function  
        End Class  
      
        <SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode:=True)>  
        Private Class SafeIconHandle  
            Inherits SafeHandleZeroOrMinusOneIsInvalid  
      
            Public Sub New()  
                MyBase.New(True)  
            End Sub  
      
            Protected Overrides Function ReleaseHandle() As Boolean  
                Return NativeMethods.DestroyIcon(handle)  
            End Function  
      
        End Class  
      
        Private Shared Function InternalCreateCursor(bmp As Bitmap) As Cursor  
      
            Dim iconInfo = New NativeMethods.IconInfo()  
            NativeMethods.GetIconInfo(bmp.GetHicon(), iconInfo)  
      
            iconInfo.xHotspot = 0  
            iconInfo.yHotspot = 0  
            iconInfo.fIcon = False  
      
            Dim cursorHandle As SafeIconHandle = NativeMethods.CreateIconIndirect(iconInfo)  
      
            Return CursorInteropHelper.Create(cursorHandle)  
      
        End Function  
        Public Shared Function CreateCursorFromImage(  
             bmpName As String,  
             Optional xHotSpot As Integer = 0,  
             Optional yHotSpot As Integer = 0) As Cursor  
      
            Dim bitmapImage = New BitmapImage()  
      
            Using stream = New FileStream(bmpName, FileMode.Open)  
                bitmapImage.BeginInit()  
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad  
                bitmapImage.StreamSource = stream  
                bitmapImage.EndInit()  
                bitmapImage.Freeze()  
            End Using  
      
            Dim bitMap = BitmapImage2Bitmap(bitmapImage)  
      
            Dim iconInfo As New NativeMethods.IconInfo()  
            NativeMethods.GetIconInfo(bitMap.GetHicon(), iconInfo)  
      
            iconInfo.xHotspot = 0  
            iconInfo.yHotspot = 0  
            iconInfo.fIcon = False  
      
            Dim cursorHandle As SafeIconHandle = NativeMethods.CreateIconIndirect(iconInfo)  
      
            Return CursorInteropHelper.Create(cursorHandle)  
      
      
        End Function  
        Private Shared Function BitmapImage2Bitmap(bitmapImage As BitmapImage) As Bitmap  
      
            Using outStream As New MemoryStream()  
                Dim enc As BitmapEncoder = New BmpBitmapEncoder()  
                enc.Frames.Add(BitmapFrame.Create(bitmapImage))  
                enc.Save(outStream)  
                Dim bitmap As New Bitmap(outStream)  
      
                Return New Bitmap(bitmap)  
      
            End Using  
        End Function  
        Public Shared Function CreateCursor(cursorText As String) As Cursor  
      
      
            Dim formattedText As New FormattedText(  
                cursorText,  
                New CultureInfo("en-us"), FlowDirection.LeftToRight,  
                New Typeface(New Media.FontFamily("Arial"), FontStyles.Normal,  
                             FontWeights.Normal,  
                             New FontStretch()), 12.0, Media.Brushes.Black)  
      
      
            Dim drawingVisual As New DrawingVisual()  
            Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()  
            drawingContext.DrawText(formattedText, New Windows.Point())  
            drawingContext.Close()  
      
      
            Dim rtb As New RenderTargetBitmap(  
                CInt(drawingVisual.ContentBounds.Width),  
                CInt(drawingVisual.ContentBounds.Height), 96, 96, PixelFormats.Pbgra32)  
      
            rtb.Render(drawingVisual)  
      
            Dim encoder As New PngBitmapEncoder()  
            encoder.Frames.Add(BitmapFrame.Create(rtb))  
      
            Using ms = New MemoryStream()  
      
                encoder.Save(ms)  
      
                Using bmp = New Bitmap(ms)  
                    Return InternalCreateCursor(bmp)  
                End Using  
      
            End Using  
        End Function  
      
    End Class  
      
    

    Code behind

    Class MainWindow  
        Private Sub Label_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)  
      
            Dim data As New DataObject(DataFormats.Text, CType(e.Source, Label).Content)  
      
            DragDrop.DoDragDrop(CType(e.Source, DependencyObject), data, DragDropEffects.Copy)  
      
        End Sub  
      
        Private Sub Label_Drop(sender As Object, e As DragEventArgs)  
      
            CType(e.Source, Label).Content = CStr(e.Data.GetData(DataFormats.Text))  
            MessageBox.Show("Dropped")  
      
        End Sub  
      
        Private _customCursor As Cursor = Nothing  
      
        Private Sub Label_GiveFeedback(sender As Object, e As GiveFeedbackEventArgs)  
      
            If e.Effects = DragDropEffects.Copy Then  
                If _customCursor Is Nothing Then  
                    _customCursor = CursorHelper.CreateCursorFromImage("Dynamic.bmp")  
                End If  
      
                If _customCursor IsNot Nothing Then  
                    e.UseDefaultCursors = False  
                    Mouse.SetCursor(_customCursor)  
                End If  
            Else  
                e.UseDefaultCursors = True  
            End If  
      
            e.Handled = True  
      
        End Sub  
      
    End Class  
      
    

    XAML

    <Window x:Class="MainWindow"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
        xmlns:local="clr-namespace:ChangeCursorDragDrop"  
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
        Title="Drop-Drop"  
        Width="332"  
        Height="248"  
        mc:Ignorable="d" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">  
        <Grid>  
            <StackPanel  
                Margin="45"  
                HorizontalAlignment="Center"  
                Orientation="Vertical">  
                <Label  
                    Margin="10"  
                    Padding="15,10"  
                    Background="AliceBlue"  
                    Content="Data to drag"  
                    GiveFeedback="Label_GiveFeedback"  
                    MouseLeftButtonDown="Label_MouseLeftButtonDown" />  
                <Label  
                    Margin="10"  
                    Padding="15,10"  
                    AllowDrop="True"  
                    Background="MediumSpringGreen"  
                    Content="Drag to here"  
                    Drop="Label_Drop" />  
            </StackPanel>  
        </Grid>  
    </Window>  
      
    

  3. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.

    6 deleted comments

    Comments have been turned off. Learn more

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.