2016-12-13 7 views
0

Я хочу показать некоторую информацию, подобную ToolTip - Я не могу использовать ToolTip, потому что он не обеспечивает достаточную настройку, и мне нужно показать это все время, когда мышь находится над Control ,
Проблема заключается в том, что значение Cursor.Size установлено равным 32x32, но видимая часть курсора составляет всего 12x19 пикселей, поэтому между видимой частью курсора и информацией, которую я хочу показать (большой размер - 20x13 пикселей) могут отличаться в других версиях Windows или настройках курсора мыши).Окно курсора видимой части размера

Я знаю, что размер большего размера для разных типов курсора (стрелка с часами/вопросительный знак, рука, ...), но как рассчитать размер видимой части?
Должен быть какой-то способ, потому что ToolTip s показаны прямо под курсором.

Это как ToolTip показано:
standard tooltip
Это, как показано моя информация:
my tooltip

+0

Может быть, вместо 'Cursor.Size' вы можете проверить' Cursor.Current .Size'? –

+0

@ m.rogalski Он возвращает тот же результат. – Artholl

+0

Просто хотел быть уверен. Вы можете проверить [этот пример] (http://stackoverflow.com/questions/3509951/how-to-get-mouse-cursor-icon-vs-c), а затем найти самое нижнее правое смещение пикселей. На данный момент это просто идея. EDIT: неправильная ссылка, исправлено –

ответ

1

Благодаря m.rogalski (указал мне на this question) и this answer и this answer и this article я был в состоянии для создания кода, который подсчитывает видимую часть курсора мыши. Поскольку он использует неуправляемый код, самая большая проблема связана с управлением памятью, поэтому я надеюсь, что я все освобожу в конце. Пожалуйста, дайте мне знать, если нет.
Внешний

using System; 
using System.Runtime.InteropServices; 

namespace MouseCursorHelper 
{ 
    /// <summary> 
    /// Source: https://www.codeproject.com/kb/cs/desktopcapturewithmouse.aspx 
    /// + DestroyIcon, DeleteObject 
    /// </summary> 
    class ExternalDlls 
    { 
     #region Class Variables 

     public const Int32 CURSOR_SHOWING = 0x00000001; 

     [StructLayout(LayoutKind.Sequential)] 
     public struct ICONINFO 
     { 
      public bool fIcon;   // Specifies whether this structure defines an icon or a cursor. A value of TRUE specifies 
      public Int32 xHotspot;  // Specifies the x-coordinate of a cursor's hot spot. If this structure defines an icon, the hot 
      public Int32 yHotspot;  // Specifies the y-coordinate of the cursor's hot spot. If this structure defines an icon, the hot 
      public IntPtr hbmMask;  // (HBITMAP) Specifies the icon bitmask bitmap. If this structure defines a black and white icon, 
      public IntPtr hbmColor; // (HBITMAP) Handle to the icon color bitmap. This member can be optional if this 
     } 
     [StructLayout(LayoutKind.Sequential)] 
     public struct POINT 
     { 
      public Int32 x; 
      public Int32 y; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct CURSORINFO 
     { 
      public Int32 cbSize;  // Specifies the size, in bytes, of the structure. 
      public Int32 flags;   // Specifies the cursor state. This parameter can be one of the following values: 
      public IntPtr hCursor;   // Handle to the cursor. 
      public POINT ptScreenPos;  // A POINT structure that receives the screen coordinates of the cursor. 
     } 

     #endregion 

     #region Class Functions 

     [DllImport("user32.dll", EntryPoint = "GetCursorInfo")] 
     public static extern bool GetCursorInfo(out CURSORINFO pci); 

     [DllImport("user32.dll", EntryPoint = "CopyIcon")] 
     public static extern IntPtr CopyIcon(IntPtr hIcon); 

     [DllImport("user32.dll", EntryPoint = "GetIconInfo")] 
     public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); 

     [DllImport("user32.dll", EntryPoint = "DestroyIcon")] 
     public static extern bool DestroyIcon(IntPtr hIcon); 

     [DllImport("gdi32.dll")] 
     public static extern bool DeleteObject(IntPtr hObject); 

     #endregion 
    } 
} 

Расчет размера

using System; 
using System.Drawing; 
using System.Runtime.InteropServices; 

namespace MouseCursorHelper 
{ 
    class CursorActualSize 
    { 
     public static Size GetActualSize() 
     { 
      Bitmap bmp; 
      IntPtr hicon; 
      ExternalDlls.CURSORINFO ci = new ExternalDlls.CURSORINFO(); 
      ExternalDlls.ICONINFO icInfo; 
      ci.cbSize = Marshal.SizeOf(ci); 
      if (ExternalDlls.GetCursorInfo(out ci)) 
      { 
       if (ci.flags == ExternalDlls.CURSOR_SHOWING) 
       { 
        hicon = ExternalDlls.CopyIcon(ci.hCursor); 
        if (ExternalDlls.GetIconInfo(hicon, out icInfo)) 
        { 
         bmp = Bitmap.FromHbitmap(icInfo.hbmMask); 

         var x = 0; 
         var y = 0; 

         for (var i = 0; i < bmp.Width; i++) 
         { 
          for (var j = 0; j < bmp.Height; j++) 
          { 
           var a = bmp.GetPixel(i, j); 

           if (a.R == 0 && a.G == 0 && a.B == 0) 
           { 
            if (i > x) 
            { 
             x = i; 
            } 

            if (j > y) 
            { 
             y = j; 
            } 
           } 
          } 
         } 

         bmp.Dispose(); 
         if (hicon != IntPtr.Zero) 
         { 
          ExternalDlls.DestroyIcon(hicon); 
         } 
         if (icInfo.hbmColor != IntPtr.Zero) 
         { 
          ExternalDlls.DeleteObject(icInfo.hbmColor); 
         } 
         if (icInfo.hbmMask != IntPtr.Zero) 
         { 
          ExternalDlls.DeleteObject(icInfo.hbmMask); 
         } 
         if (ci.hCursor != IntPtr.Zero) 
         { 
          ExternalDlls.DeleteObject(ci.hCursor); 
         } 

         return new Size(x, y); 
        } 

        if (hicon != IntPtr.Zero) 
        { 
         ExternalDlls.DestroyIcon(hicon); 
        } 
        if (icInfo.hbmColor != IntPtr.Zero) 
        { 
         ExternalDlls.DeleteObject(icInfo.hbmColor); 
        } 
        if (icInfo.hbmMask != IntPtr.Zero) 
        { 
         ExternalDlls.DeleteObject(icInfo.hbmMask); 
        } 
       } 
      } 

      if (ci.hCursor != IntPtr.Zero) 
      { 
       ExternalDlls.DeleteObject(ci.hCursor); 
      } 

      return new Size(0, 0); 
     } 
    } 
} 

А потом просто позвонить

Size cursorSize = CursorActualSize.GetActualSize();