2012-12-03 11 views
16

Ich möchte für mein Programm in der Lage sein, die maximale Größe der Maus 32x32 überschreiben, ähnlich wie das Programm in der beigefügten Bild, der Cursor im Bild ist 72x72 . Dies ist eine Aufnahme von ProcMon, die zeigt, was passiert, wenn sich die Cursor ändern.Wie maximale 32x32 Mausgröße in Windows wie dieses Programm überschreiben kann

Allerdings, wenn ich versuchen, die Registrierungswerte zu ändern, für die der Cursor selbst Dateien und dann die Änderungen Drück

SystemParametersInfo(SPI.SPI_SETCURSORS, 0, IntPtr.Zero, SPIF.SPIF_SENDCHANGE);

dann wird der Cursor ändern, aber es ist nach wie vor auf die 32x32 maximale Größe begrenzt. Wie konnte dieses Programm diese Einschränkung umgehen? Außerdem bleiben die Cursor nach dem Beenden des Programms erhalten. Es kann also nicht während des Laufens ausgeführt werden, sondern muss irgendwo eine Einstellung außer Kraft setzen.

enter image description here

Danke für Ihre Hilfe, ich habe nicht in der Lage gewesen, etwas Vergleichbares auf dem Netz zu finden, damit ich weiß nicht, selbst wenn jemand die Antwort hat.

EDIT: Ich sehe einige Zugriffe auf eine Datei namens C:\Windows\SysWOW64\Imageres.dll. Sie lesen nur, aber vielleicht sind diese Cursor hier gespeichert, oder sie haben diese Datei irgendwie modifiziert. Aber ich dachte, es könnte jemanden mit mehr Erfahrung als ich auf die richtige Spur bringen.

EDIT 2: Ich glaube, dass die Größen von den Variablen SM_CXCURSOR und SM_CYCURSOR diktiert werden. Wenn ich einen Weg finden könnte, diese zu setzen, könnte ich im Geschäft sein. Gehen Sie, um ein schnelles Programm zu schreiben, um mir diese Werte auf dem PC mit dem laufenden Programm und riesigen Mauszeiger zu bekommen und zu sehen, was es zurückgibt ...

EDIT 3: Kein Glück; Der PC mit dem riesigen Cursor gibt 32x32 für seine SM_CXCURSOR und SM_CYCURSOR zurück.

+0

Vielleicht könnten Sie Ihre Bildschirmgröße auf 150% einstellen? Es ist durch die Bildschirmauflösung Einstellung –

+0

Aber das ist nicht, wie dieses Programm es tun kann. Nichts anderes ändert sich außer dem Mauszeiger, was der Effekt ist, den ich zu replizieren hoffe. –

+1

Sie müssten angeben, wie Sie versuchen, die Größe des Mauszeigers zu ändern. –

Antwort

6

Mit SetSystemCursor es möglich ist, einen Cursor auf ein Bild von viel größer als die Standard-Cursor zu setzen.

Hier ist ein Klasse-I zum Ändern der Größe der System Cursor habe:

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); 
     } 

    } 
} 

Es funktioniert durch das aktuelle System Cursor in System.Windows.Forms.Cursors als vorgesehen erhalten und ein Bild von ihm mit Cursor.Draw machen. Das Bild wird dann auf die gewünschte Größe skaliert. Dazu muss das Cursorbild entweder in die untere rechte Ecke verschoben werden (wie bei den Pfeilzeigern) oder das Cursorbild innerhalb des größeren Bildes zentriert werden (wie bei Cross und IBeam).

Sie können bei Bedarf auch ein eigenes Bild für den Cursor verwenden, wobei Sie den gesamten Größenänderungscode umgehen. Liefern Sie die Bitmap einfach an SetCursor.

Sobald das neue Cursorbild fertig ist, ist das letzte Stück Daten, das benötigt wird, die ID des Cursors, den wir zu ersetzen versuchen. Jede System.Windows.Forms.Cursor enthält diese Information, aber in einer privaten Variablen, so dass die Reflexion verwendet wird, um den Wert zu erhalten. Wenn Sie Reflektionen vermeiden möchten, können Sie stattdessen eine Tabelle mit diesen Werten erstellen. Eine Liste der Werte finden Sie unter MSDN SetSystemCursor.

Um die Klasse zu nur

SystemCursors.SetSystemCursorsSize(128); 
+0

Hey, das ist definitiv das nächste, was ich je zu dem bekommen habe, wonach ich gesucht habe. Ich werde ein wenig herumschnüffeln, aber das einzige Problem dabei ist, dass es keine Möglichkeit gibt, zu den echten Standard-Cursors zurückzukehren, und wenn Sie "SetSystemCursorSize" von sagen, 32 bis 128 zu 32 und immer wieder wird es so verzerrt, dass es schließlich als schwarzes Quadrat endet. Wie gesagt, ich schaue mich um, war aber nur neugierig, ob du Ideen hast! Danke für die Post! –

+0

Wenn Sie im Voraus wissen, welche Größen Sie benötigen, können Sie jeden Cursor als Bilddatei speichern und dann jede Größe nach Bedarf laden. So etwas wie 'SetCursor (neues Bitmap (Image.FromFile (arrow32.png)), ...);'. Bei Bildern, die größer als 32 sind, müssen Sie das verschobene Bild speichern, wie 'ResizeCursorBitmap'. Eine andere Möglichkeit wäre, beim Starten des Programms eine Kopie der Bitmap eines jeden Cursors zu behalten und dann die Größe zu ändern und zu verschieben oder einfach das Original wiederherzustellen. – endofzero

+0

Leider funktioniert das nicht in Windows 10. Auch wenn eine größere externe Bitmap mit 'SetCursor' geladen wird, wird die Größe auf nur 32x32 skaliert. – kwill

6

Wenn Sie mit WPF arbeiten, können Sie Ihren eigenen Mauszeiger erstellen und zuweisen. Aber das ist keine systemweite Mauszeigeränderung. Hier ist ein Code, der den Trick machen würde. Im folgenden Code erstelle ich einen Cursor 50x50 Pixel. Sie können Ihre eigene Form auf das 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); 
      } 
     } 
    } 

} 
+0

Ich schätze die Hilfe und das Codebeispiel, aber leider würde es System-weit benötigt werden. Ich bin mir nicht sicher, welche Art von schwarzer Magie diese Leute gearbeitet haben, aber ich bin entschlossen, es herauszufinden: P Nochmals vielen Dank! –

0

Fügen Sie diese Importe zu Ihrer Klasse zeichnen:

[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); 

lesen Msdn Artikel über LoadImage und SetSystemCursor, vor allem über Parameter, die sie verwenden.

Dann nutzen Sie Funktionen im Code:

// "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) 
} 
0

ich dieses Problem nennen verwenden Lösen von intrueder der way.Supplement, die API Loadimage kann nicht Load.png useing. Verwenden Sie System.Drawing.BitMap.Wie das: Bitmap bmp = new Bitmap(str, true); IntPtr p = bmp.GetHicon(); SetSystemCursor(p, OCR_NORMAL);