schangxiang@126.com
2025-11-04 f5ed29dc26c7cd952d56ec5721a2efc43cd25992
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Interop;
using System.Windows.Input;
using System.Windows;
 
namespace XHandler.Controls.DrawCanvas
{
    public static class DrawCursors
    {
        public static Cursor CreateBmpCursor(Bitmap bmp, UInt32 xHotSpot, UInt32 yHotSpot)
        {
            if (!NativeMethods.GetIconInfo(bmp.GetHicon(), out IconInfo iconInfo))
                return Cursors.Arrow;
 
            iconInfo.xHotspot = xHotSpot;   // 焦点x轴坐标
            iconInfo.yHotspot = yHotSpot;   // 焦点y轴坐标
            iconInfo.fIcon = false;         // 设置鼠标
 
            var cursorHandle = NativeMethods.CreateIconIndirect(ref iconInfo);
            return CursorInteropHelper.Create(cursorHandle);
        }
 
        public static Cursor CreateBmpCursor(Uri uri, UInt32 xHotSpot, UInt32 yHotSpot)
        {
            var sri = Application.GetResourceStream(uri);
 
            using (var bmp = new Bitmap(sri.Stream))
            {
                return CreateBmpCursor(bmp, xHotSpot, yHotSpot);
            }
        }
 
        public static Cursor CreateBmpCursor(UInt32 width, UInt32 height, UInt32 border, System.Windows.Media.SolidColorBrush brush)
        {
            using (var bmp = new Bitmap((Int32)(width + border * 2), (Int32)(height + border * 2)))
            {
                using (var g = Graphics.FromImage(bmp))
                {
                    g.SmoothingMode = SmoothingMode.HighQuality;
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
 
                    var color = brush.Color;
                    using (var pen = new Pen(Color.FromArgb(color.A, color.R, color.G, color.B), border))
                    {
                        g.DrawRectangle(pen, border, border, width, height);
                        g.Flush();
                    }
                }
 
                return CreateBmpCursor(bmp, width / 2 + border, height / 2 + border);
            }
        }
 
        private static Lazy<Cursor> hand = new Lazy<Cursor>(() => { return CreateBmpCursor(new Uri("Assets/hand.png", UriKind.Relative), 12, 12); });
        /// <summary>
        /// 拖动
        /// </summary>
        public static Cursor Hand => hand.Value;
    }
 
    public static class NativeMethods
    {
        [DllImport("user32.dll")]
        public static extern SafeIconHandle CreateIconIndirect(ref IconInfo icon);
 
        [DllImport("user32.dll")]
        public static extern Boolean DestroyIcon(IntPtr hIcon);
 
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern Boolean GetIconInfo(IntPtr hIcon, out IconInfo pIconInfo);
    }
 
    public struct IconInfo
    {
        public Boolean fIcon;
        public UInt32 xHotspot;
        public UInt32 yHotspot;
        public IntPtr hbmMask;
        public IntPtr hbmColor;
    }
 
    [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
    public class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        public SafeIconHandle() : base(true) { }
        protected override Boolean ReleaseHandle() => NativeMethods.DestroyIcon(handle);
    }
}