0

I want to show some information similar as ToolTip is shown - I can't use the ToolTip because it doesn't provide enough customization and I need to show it the whole time the mouse is over the Control.
The problem is that the Cursor.Size is set to 32x32, but the visible part of the cursor is only 12x19 pixels so there is big gap (20x13 pixels) between the visible part of the cursor and the information I want to show (it is may be different on other Windows versions or mouse cursor settings).

I know that the bigger size is there for different types of cursor (arrow with clocks/question mark, hand, ...), but how to calculate the size of the visible part?
There should be some way, because the ToolTips are shown right under the cursor.

This is how the ToolTip is shown:
standard tooltip
This is how my information is shown:
my tooltip

asked Dec 13, 2016 at 10:59
6
  • Maybe instead of Cursor.Size you can check Cursor.Current.Size ? Commented Dec 13, 2016 at 11:05
  • @m.rogalski It returns the same result. Commented Dec 13, 2016 at 11:06
  • Just wanted to be sure. You can check this example and then find the most bottom-right pixel offset. Just an quick idea for now. EDIT: wrong link, fixed Commented Dec 13, 2016 at 11:08
  • @m.rogalski thank you for your help. Your link helped me. I created a solution and posted it as an answer. Commented Dec 13, 2016 at 14:32
  • " I need to show it the whole time the mouse is over the Control" You can adjust a lot of settings (including ShowDuration) with the ToolTipService Attached Properties: EDIT Nevermind, I just saw you are using WinForms. Try this instead. Commented Dec 13, 2016 at 14:34

1 Answer 1

2

Thanks to m.rogalski (pointed me to this question) and this answer and this answer and this article I was able to create code which counts the visible part of the mouse cursor. Since it uses unmanaged code the biggest problem was with the memory management so I hope that I free everything at the end. Please let me know if not.
External

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

Size calculation

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

And then simply call

Size cursorSize = CursorActualSize.GetActualSize();
answered Dec 13, 2016 at 14:28
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.