Files
McBitFont/McBitFont/McCursor.cs
Anton Mukhin ad15f08233 TODO features:
Application:
- Special cursor to indicate baseline set
- Special cursor when dragging canvas with middle mouse button

Functionality:
- Beside Baseline, also make top and mid lines

Bugs:
- Middle mouse button tries to change selection while dragging canvas with rectSelection tool active
2025-07-08 17:00:55 +03:00

173 lines
6.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace McBitFont {
internal class McCursor {
public struct IconInfo {
public bool fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
[DllImport("user32.dll")]
public static extern IntPtr CreateIconIndirect(ref IconInfo icon);
/// <summary>
/// Create a cursor from a bitmap without resizing and with the specified
/// hot spot
/// </summary>
public static Cursor CreateCursorNoResize(Bitmap bmp, int xHotSpot, int yHotSpot) {
IntPtr ptr = bmp.GetHicon();
IconInfo tmp = new IconInfo();
GetIconInfo(ptr, ref tmp);
tmp.xHotspot = xHotSpot;
tmp.yHotspot = yHotSpot;
tmp.fIcon = false;
ptr = CreateIconIndirect(ref tmp);
return new Cursor(ptr);
}
/// <summary>
/// Create a 32x32 cursor from a bitmap, with the hot spot in the middle
/// </summary>
public static Cursor CreateCursor(Bitmap bmp) {
int xHotSpot = 16;
int yHotSpot = 16;
IntPtr ptr = ((Bitmap)ResizeImage(bmp, 32, 32)).GetHicon();
IconInfo tmp = new IconInfo();
GetIconInfo(ptr, ref tmp);
tmp.xHotspot = xHotSpot;
tmp.yHotspot = yHotSpot;
tmp.fIcon = false;
ptr = CreateIconIndirect(ref tmp);
return new Cursor(ptr);
}
/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
/// <param name="image">The image to resize.</param>
/// <param name="width">The width to resize to.</param>
/// <param name="height">The height to resize to.</param>
/// <returns>The resized image.</returns>
public static Bitmap ResizeImage(Image image, int width, int height) {
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage)) {
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes()) {
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
public static Cursor GetCursor(int penSize, int cellSize, int gap) {
int size = (cellSize + gap) * penSize;
Bitmap bmp = new(size, size);
Pen pb = new(Color.Black, 1);
SolidBrush bw = new(Color.FromArgb(160, Color.White));
using (Graphics g = Graphics.FromImage(bmp)) {
g.DrawRectangle(pb, 0, 0, size-1, size-1);
g.FillRectangle(bw, 1, 1, size - 2, size - 2);
}
return CreateCursorNoResize(bmp, cellSize / 2, cellSize / 2);
}
public static Cursor GetCursorSelect() {
Point[] arrow = { new(1, 1), new(12, 12), new(11, 13), new(6, 13), new(2, 17), new(1, 16) };
Point[] corner1 = { new(13, 6), new(20, 6), new(20, 13), new(17, 13), new(17, 9), new(13, 9) };
Point[] corner2 = { new(17, 16), new(20, 16), new(20, 23), new(13, 23), new(13, 20), new(17, 20) };
Point[] corner3 = { new(3, 16), new(6, 16), new(6, 20), new(10, 20), new(10, 23), new(3, 23) };
Point[] corner4 = { new(6, 6), new(10, 6), new(10, 9), new(6, 9) };
Bitmap bmp = new(21, 24);
Pen pb = new(Color.Black, 1);
SolidBrush bw = new (Color.White);
using (Graphics g = Graphics.FromImage(bmp)) {
g.FillPolygon(bw, corner1);
g.DrawPolygon(pb, corner1);
g.FillPolygon(bw, corner2);
g.DrawPolygon(pb, corner2);
g.FillPolygon(bw, corner3);
g.DrawPolygon(pb, corner3);
g.FillPolygon(bw, corner4);
g.DrawPolygon(pb, corner4);
g.FillPolygon(bw, arrow);
g.DrawPolygon(pb, arrow);
}
return CreateCursorNoResize(bmp, 1, 1);
}
public static Cursor GetCursorLines() {
Point[] arrow = { new(1, 1), new(12, 12), new(11, 13), new(6, 13), new(2, 17), new(1, 16) };
Rectangle line = new(0, 18, 20, 5);
Bitmap bmp = new(21, 24);
Pen pb = new(Color.Black, 1);
Pen pw = new(Color.White, 1);
SolidBrush bw = new(Color.White);
SolidBrush bb = new(Color.Black);
using (Graphics g = Graphics.FromImage(bmp)) {
g.FillPolygon(bw, arrow);
g.DrawPolygon(pb, arrow);
g.FillRectangle(bb, line);
g.DrawRectangle(pw, line);
}
return CreateCursorNoResize(bmp, 1, 1);
}
public static Cursor GetCursorDrag() {
Point[] arrow1 = { new(11, 0), new(15, 4), new(13, 4), new(13, 7), new(9, 7), new(9, 4), new(7, 4) };
Point[] arrow2 = { new(22, 11), new(18, 15), new(18, 13), new(15, 13), new(15, 9), new(18, 9), new(18, 7) };
Point[] arrow3 = { new(11, 22), new(7, 18), new(9, 18), new(9, 15), new(13, 15), new(13, 18), new(15, 18) };
Point[] arrow4 = { new(0, 11), new(4, 7), new(4, 9), new(7, 9), new(7, 13), new(4, 13), new(4, 15) };
Bitmap bmp = new(23, 23);
Pen pb = new(Color.Black, 1);
SolidBrush bw = new(Color.White);
using (Graphics g = Graphics.FromImage(bmp)) {
g.FillPolygon(bw, arrow1);
g.DrawPolygon(pb, arrow1);
g.FillPolygon(bw, arrow2);
g.DrawPolygon(pb, arrow2);
g.FillPolygon(bw, arrow3);
g.DrawPolygon(pb, arrow3);
g.FillPolygon(bw, arrow4);
g.DrawPolygon(pb, arrow4);
}
return CreateCursorNoResize(bmp, 11, 11);
}
}
}