Set custom cursor access point in WPF

I am trying to use custom images in Cursor, and I did this with this code.

public static class cursorHelper { public static Cursor vertical = new Cursor(Application.GetResourceStream(getFromResource("PenCADwpf", "Images/cursors/Vertical.ico")).Stream); public static Cursor horizontal = new Cursor(Application.GetResourceStream(getFromResource("PenCADwpf", "Images/cursors/Horizontal.ico")).Stream); public static Uri getFromResource(string psAssemblyName, string psResourceName) { Uri oUri = new Uri("pack://application:,,,/" + psAssemblyName + ";component/" + psResourceName, UriKind.RelativeOrAbsolute); return oUri; } public static ImageSource getImageSourceFromResource(string psAssemblyName, string psResourceName) { Uri oUri = getFromResource(psAssemblyName, psResourceName); return BitmapFrame.Create(oUri); } } 

And using the code,

  private void btnVerticalMullion_Click(object sender, RoutedEventArgs e) { this.Cursor = cursorHelper.vertical; } 

My problem is the cursor access point is the bottom left point. I need to change it to the 0.0 (top left) point of the image. Can anyone help me out? Thanks in advance,

+1
source share
1 answer

This is because you use .ICO files instead of .CUR files as data for the Cursor class.

While the .ICO and .CUR formats are similar, the .ICO format does not contain hot spot information.

You have 2 options:

  • convert your .ICO files to .CUR files and embed them as resources.

    Do this using the conversion utility that you can find on the Internet, or create a new .CUR file in Visual Studio, and then copy and paste the data from your .ICO files.

  • save them as .ICO files, but crack the data so that it matches the CUR format when passing to the Cursor class.

Here is a sample code to change the ICO stream to turn it into a CUR format.

In this example, I tested it with an ICO file that contained one 32X32X4bit BMP image, and I wanted the cursor to have a (15.15) hot spot.

This code is only intended to get started if you go along this route ... it needs more code to handle errors and the ability to work with ICO files that contain several icon images (that is, if there are several entries), etc. d.

You can also use BinaryWriter for more natural data management, for example. to write hotspots coords that use 2 bytes (i.e. more than 255) using Write(UInt16) .

enter image description here

enter image description here

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.IO; using System.Windows.Resources; namespace WpfApplication2 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Uri uri = new Uri("pack://application:,,,/test.ico"); Stream iconstream = GetCURFromICO(uri, 15, 15 ); Cursor cursor = new Cursor(iconstream); this.Cursor = cursor; } public static Stream GetCursorFromICO(Uri uri, byte hotspotx, byte hotspoty) { StreamResourceInfo sri = Application.GetResourceStream(uri); Stream s = sri.Stream; byte []buffer = new byte[s.Length]; s.Read(buffer, 0, (int)s.Length); MemoryStream ms = new MemoryStream(); buffer[2] = 2; // change to CUR file type buffer[10] = hotspotx; buffer[12] = hotspoty; ms.Write(buffer, 0, (int)s.Length); ms.Position = 0; return ms; } public static Stream GetCURFromICOAlternativeMethod(Uri uri, byte hotspotx, byte hotspoty) { StreamResourceInfo sri = Application.GetResourceStream(uri); Stream s = sri.Stream; byte []buffer = new byte[s.Length]; MemoryStream ms = new MemoryStream(); ms.WriteByte(0); // always 0 ms.WriteByte(0); ms.WriteByte(2); // change file type to CUR ms.WriteByte(0); ms.WriteByte(1); // 1 icon in table ms.WriteByte(0); s.Position = 6; // skip over first 6 bytes in ICO as we just wrote s.Read(buffer, 0, 4); ms.Write(buffer, 0, 4); ms.WriteByte(hotspotx); ms.WriteByte(0); ms.WriteByte(hotspoty); ms.WriteByte(0); s.Position += 4; // skip 4 bytes as we just wrote our own int remaining = (int)s.Length - 14; s.Read(buffer, 0, remaining); ms.Write(buffer, 0, remaining); ms.Position = 0; return ms; } } } 

 <Window x:Class="WpfApplication2.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> </Grid> </Window> 
+3
source

Source: https://habr.com/ru/post/1200934/


All Articles