我想我的程序能够覆盖32×32的最大征收鼠标大小很像附图片的程序做,描绘光标最高72x72。 这是从捕捉ProcMon
显示是怎么回事,当光标改变。
不过,如果我尝试光标文件自己更改的注册表值,然后按使用变化
SystemParametersInfo(SPI.SPI_SETCURSORS, 0, IntPtr.Zero, SPIF.SPIF_SENDCHANGE);
那么光标会改变,但它仍然限于32×32的最大尺寸。 如何为这一计划能够得到周围的限制? 此外,光标停留在程序结束后,所以它不可能是什么它做在运行,但必须覆盖的地方设置。
感谢您的帮助,我一直没能找到在网络上像这样的东西,所以我甚至不知道是否有人将有答案。
编辑:我看到一些访问一个名为C:\Windows\SysWOW64\Imageres.dll
。 他们只读取,但也许这些游标存放在这里,或者他们以某种方式修改此文件。 但我想它可能会有人比我在正确的轨道上更有经验了。
编辑2:我认为大小是由SM_CXCURSOR和SM_CYCURSOR变量决定。 如果我能找到一种方法来设置这些,我可能会在企业。 打算写一个快速程序,让我这些值与程序运行和巨大的鼠标光标在PC上,看看它返回......
编辑3:没有运气; 它是SM_CXCURSOR和SM_CYCURSOR与巨大光标PC返回32×32。
使用SetSystemCursor
有可能的光标设定为比标准光标尺寸大得多的图像。
这是一类我有一个调整的系统光标:
using System;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
class SystemCursors
{
[DllImport("user32.dll")]
static extern bool SetSystemCursor(IntPtr hcur, uint id);
enum CursorShift
{
Centered,
LowerRight,
}
public static void SetSystemCursorsSize(int newSize)
{
ResizeCursor(System.Windows.Forms.Cursors.AppStarting, newSize, CursorShift.LowerRight);
ResizeCursor(System.Windows.Forms.Cursors.Arrow, newSize, CursorShift.LowerRight);
ResizeCursor(System.Windows.Forms.Cursors.Cross, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.Hand, newSize, CursorShift.LowerRight);
ResizeCursor(System.Windows.Forms.Cursors.Help, newSize, CursorShift.LowerRight);
ResizeCursor(System.Windows.Forms.Cursors.HSplit, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.IBeam, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.No, newSize, CursorShift.LowerRight);
ResizeCursor(System.Windows.Forms.Cursors.NoMove2D, newSize, CursorShift.LowerRight);
ResizeCursor(System.Windows.Forms.Cursors.NoMoveHoriz, newSize, CursorShift.LowerRight);
ResizeCursor(System.Windows.Forms.Cursors.NoMoveVert, newSize, CursorShift.LowerRight);
ResizeCursor(System.Windows.Forms.Cursors.PanEast, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.PanNE, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.PanNorth, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.PanNW, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.PanSE, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.PanSouth, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.PanSW, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.PanWest, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.SizeAll, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.SizeNESW, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.SizeNS, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.SizeNWSE, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.SizeWE, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.UpArrow, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.VSplit, newSize, CursorShift.Centered);
ResizeCursor(System.Windows.Forms.Cursors.WaitCursor, newSize, CursorShift.LowerRight);
}
private static void ResizeCursor(System.Windows.Forms.Cursor cursor,
int newSize, CursorShift cursorShift)
{
Bitmap cursorImage = GetSystemCursorBitmap(cursor);
cursorImage = ResizeCursorBitmap(cursorImage, new Size(newSize, newSize), cursorShift);
SetCursor(cursorImage, getResourceId(cursor));
}
public static Bitmap GetSystemCursorBitmap(System.Windows.Forms.Cursor cursor)
{
Bitmap bitmap = new Bitmap(
cursor.Size.Width, cursor.Size.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
cursor.Draw(graphics,
new Rectangle(new Point(0, 0), cursor.Size));
bitmap = Crop(bitmap);
return bitmap;
}
private static Bitmap Crop(Bitmap bmp)
{
//code from http://stackoverflow.com/a/10392379/935052
int w = bmp.Width;
int h = bmp.Height;
Func<int, bool> allWhiteRow = row =>
{
for (int i = 0; i < w; ++i)
if (bmp.GetPixel(i, row).A != 0)
return false;
return true;
};
Func<int, bool> allWhiteColumn = col =>
{
for (int i = 0; i < h; ++i)
if (bmp.GetPixel(col, i).A != 0)
return false;
return true;
};
int topmost = 0;
for (int row = 0; row < h; ++row)
{
if (allWhiteRow(row))
topmost = row;
else break;
}
int bottommost = 0;
for (int row = h - 1; row >= 0; --row)
{
if (allWhiteRow(row))
bottommost = row;
else break;
}
int leftmost = 0, rightmost = 0;
for (int col = 0; col < w; ++col)
{
if (allWhiteColumn(col))
leftmost = col;
else
break;
}
for (int col = w - 1; col >= 0; --col)
{
if (allWhiteColumn(col))
rightmost = col;
else
break;
}
if (rightmost == 0) rightmost = w; // As reached left
if (bottommost == 0) bottommost = h; // As reached top.
int croppedWidth = rightmost - leftmost;
int croppedHeight = bottommost - topmost;
if (croppedWidth == 0) // No border on left or right
{
leftmost = 0;
croppedWidth = w;
}
if (croppedHeight == 0) // No border on top or bottom
{
topmost = 0;
croppedHeight = h;
}
try
{
var target = new Bitmap(croppedWidth, croppedHeight);
using (Graphics g = Graphics.FromImage(target))
{
g.DrawImage(bmp,
new RectangleF(0, 0, croppedWidth, croppedHeight),
new RectangleF(leftmost, topmost, croppedWidth, croppedHeight),
GraphicsUnit.Pixel);
}
return target;
}
catch (Exception ex)
{
throw new Exception(
string.Format("Values are topmost={0} btm={1} left={2} right={3} croppedWidth={4} croppedHeight={5}", topmost, bottommost, leftmost, rightmost, croppedWidth, croppedHeight),
ex);
}
}
private static Bitmap ResizeCursorBitmap(Bitmap bitmap, Size size, CursorShift cursorShift)
{
if (size.Width > 32)
{
//shifting must occur
Bitmap intermediateBitmap = new Bitmap(64, 64);
Graphics intermediateGraphics = Graphics.FromImage(intermediateBitmap);
if (cursorShift == CursorShift.LowerRight)
//place the mouse cursor in the lower right hand quadrant of the bitmap
intermediateGraphics.DrawImage(bitmap,
intermediateBitmap.Width / 2, intermediateBitmap.Height / 2);
else if (cursorShift == CursorShift.Centered)
intermediateGraphics.DrawImage(bitmap,
intermediateBitmap.Width / 2 - bitmap.Width / 2,
intermediateBitmap.Height / 2 - bitmap.Height / 2);
//now we have a shifted bitmap; use it to draw the resized cursor
//Bitmap finalBitmap = new Bitmap(intermediateBitmap, size); //normal quality
Bitmap finalBitmap = new Bitmap(size.Width, size.Height);
Graphics finalGraphics = Graphics.FromImage(finalBitmap);
finalGraphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
finalGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
finalGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
finalGraphics.DrawImage(intermediateBitmap, 0, 0, finalBitmap.Width, finalBitmap.Height);
return finalBitmap;
}
else
{
Bitmap newBitmap = new Bitmap(bitmap, size);
return newBitmap;
}
}
private static uint getResourceId(System.Windows.Forms.Cursor cursor)
{
FieldInfo fi = typeof(System.Windows.Forms.Cursor).GetField(
"resourceId", BindingFlags.NonPublic | BindingFlags.Instance);
object obj = fi.GetValue(cursor);
return Convert.ToUInt32((int)obj);
}
private static void SetCursor(Bitmap bitmap, uint whichCursor)
{
IntPtr ptr = bitmap.GetHicon();
bool retval = SetSystemCursor(ptr, whichCursor);
}
}
}
它通过获取当前的系统光标在提供System.Windows.Forms.Cursors
并从中使图像与Cursor.Draw
。 然后,图像被调整大小到所需的大小。 这需要移动光标图像,可以是对于右下角(像箭头指针)或定心光标图像的放大图像内(例如为十字和I梁)。
如果需要的话,绕过所有的调整大小代码,你可以使用自己的图像光标。 只需提供该位图SetCursor
。
一旦新的光标图像准备就绪,所需数据的最后一块是我们正在试图取代光标的ID。 每个System.Windows.Forms.Cursor
包含此信息,但在私有变量,所以反射来获得的价值。 如果你希望避免反射,你可以建立这些值的表来代替。 请参阅MSDN SetSystemCursor的值的列表。
使用类只需调用
SystemCursors.SetSystemCursorsSize(128);
如果您正在使用WPF工作,你可以创建自己的鼠标光标并分配它。 但是,这不是一个全系统的鼠标光标的变化。 下面是一些代码,会做的伎俩。 在下面的代码我创建一个光标50x50像素。 您可以绘制自己的形状到RenderTargetBitmap
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Mouse.OverrideCursor = CreateCursor(50,50, Brushes.Gold, null);
}
Cursor CreateCursor(double rx, double ry, SolidColorBrush brush, Pen pen)
{
var vis = new DrawingVisual();
using (var dc = vis.RenderOpen())
{
dc.DrawRectangle(brush, new Pen(Brushes.Black, 0.1), new Rect(0, 0, rx, ry));
dc.Close();
}
var rtb = new RenderTargetBitmap(64, 64, 96, 96, PixelFormats.Pbgra32);
rtb.Render(vis);
using (var ms1 = new MemoryStream())
{
var penc = new PngBitmapEncoder();
penc.Frames.Add(BitmapFrame.Create(rtb));
penc.Save(ms1);
var pngBytes = ms1.ToArray();
var size = pngBytes.GetLength(0);
//.cur format spec http://en.wikipedia.org/wiki/ICO_(file_format)
using (var ms = new MemoryStream())
{
{//ICONDIR Structure
ms.Write(BitConverter.GetBytes((Int16)0), 0, 2);//Reserved must be zero; 2 bytes
ms.Write(BitConverter.GetBytes((Int16)2), 0, 2);//image type 1 = ico 2 = cur; 2 bytes
ms.Write(BitConverter.GetBytes((Int16)1), 0, 2);//number of images; 2 bytes
}
{//ICONDIRENTRY structure
ms.WriteByte(32); //image width in pixels
ms.WriteByte(32); //image height in pixels
ms.WriteByte(0); //Number of Colors in the color palette. Should be 0 if the image doesn't use a color palette
ms.WriteByte(0); //reserved must be 0
ms.Write(BitConverter.GetBytes((Int16)(rx / 2.0)), 0, 2);//2 bytes. In CUR format: Specifies the horizontal coordinates of the hotspot in number of pixels from the left.
ms.Write(BitConverter.GetBytes((Int16)(ry / 2.0)), 0, 2);//2 bytes. In CUR format: Specifies the vertical coordinates of the hotspot in number of pixels from the top.
ms.Write(BitConverter.GetBytes(size), 0, 4);//Specifies the size of the image's data in bytes
ms.Write(BitConverter.GetBytes((Int32)22), 0, 4);//Specifies the offset of BMP or PNG data from the beginning of the ICO/CUR file
}
ms.Write(pngBytes, 0, size);//write the png data.
ms.Seek(0, SeekOrigin.Begin);
return new Cursor(ms);
}
}
}
}
添加这些进口到类:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr LoadImage(IntPtr hinst, string lpszName, uint uType, int cxDesired, int cyDesired, uint fuLoad);
[DllImport("user32.dll")]
static extern bool SetSystemCursor(IntPtr hcur, uint id);
阅读MSDN文章的LoadImage和SetSystemCursor ,尤其是他们所使用的参数。
然后在你的代码中使用的功能:
// "cursor.cur" - cursor image of any size you want
// 2 == IMAGE_CURSOR (from Winuser.h)
// cxDesired = 0 and cyDesired = 0, using original image size
// 0x8010 == LR_DEFAULTCOLOR | LR_SHARED | LR_LOADFROMFILE (from Winuser.h)
var ptr = LoadImage(IntPtr.Zero, "cursor.cur", 2, 0, 0, 0x8010);
if(ptr != IntPtr.Zero)
{
SetSystemCursor(ptr, 32512); // 32512 == OCR_NORMAL (from Winuser.h)
}
我通过期运用intrueder的way.Supplement,该API的LoadImage不能Load.png解决这个问题。 使用System.drawing.BitMap.Like这样的: Bitmap bmp = new Bitmap(str, true); IntPtr p = bmp.GetHicon(); SetSystemCursor(p, OCR_NORMAL);
Bitmap bmp = new Bitmap(str, true); IntPtr p = bmp.GetHicon(); SetSystemCursor(p, OCR_NORMAL);