Alex from Jitbit
Alex from Jitbit

Reputation: 60642

get current mouse cursor type

How do I get the current GLOBAL mouse cursor type (hourglass/arrow/..)? In Windows.

Global - I need it even if the mouse is ouside of my application or even if my program is windlowless.

In C#, Delphi or pure winapi, nevermind...

Thank you very much in advance!!

Upvotes: 11

Views: 12402

Answers (6)

Daniel
Daniel

Reputation: 506

@Alex You saved my day. I allowed myself to modify your code, so every-cursor gets reflected... may be helpful for someone else:

public enum Cursor
{
    UNKOWNCURSOR,
    AppStarting,
    Arrow,
    Cross,
    Default,
    IBeam,
    No,
    SizeAll,
    SizeNESW,
    SizeNS,
    SizeNWSE,
    SizeWE,
    UpArrow,
    WaitCursor,
    Help,
    HSplit,
    VSplit,
    NoMove2D,
    NoMoveHoriz,
    NoMoveVert,
    PanEast,
    PanNE,
    PanNorth,
    PanNW,
    PanSE,
    PanSouth,
    PanSW,
    PanWest,
    Hand
}

public static Cursor GetCursor()
{
    CURSORINFO pci;
    pci.cbSize = Marshal.SizeOf(typeof(CURSORINFO));
    if (!GetCursorInfo(out pci))
        throw new Win32Exception(Marshal.GetLastWin32Error());

    var h = pci.hCursor;
    if (h == Cursors.AppStarting.Handle) return Cursor.AppStarting;
    if (h == Cursors.Arrow.Handle) return Cursor.Arrow;
    if (h == Cursors.Cross.Handle) return Cursor.Cross;
    if (h == Cursors.Default.Handle) return Cursor.Default;
    if (h == Cursors.IBeam.Handle) return Cursor.IBeam;
    if (h == Cursors.No.Handle) return Cursor.No;
    if (h == Cursors.SizeAll.Handle) return Cursor.SizeAll;
    if (h == Cursors.SizeNESW.Handle) return Cursor.SizeNESW;
    if (h == Cursors.SizeNS.Handle) return Cursor.SizeNS;
    if (h == Cursors.SizeNWSE.Handle) return Cursor.SizeNWSE;
    if (h == Cursors.SizeWE.Handle) return Cursor.SizeWE;
    if (h == Cursors.UpArrow.Handle) return Cursor.UpArrow;
    if (h == Cursors.WaitCursor.Handle) return Cursor.WaitCursor;
    if (h == Cursors.Help.Handle) return Cursor.Help;
    if (h == Cursors.HSplit.Handle) return Cursor.HSplit;
    if (h == Cursors.VSplit.Handle) return Cursor.VSplit;
    if (h == Cursors.NoMove2D.Handle) return Cursor.NoMove2D;
    if (h == Cursors.NoMoveHoriz.Handle) return Cursor.NoMoveHoriz;
    if (h == Cursors.NoMoveVert.Handle) return Cursor.NoMoveVert;
    if (h == Cursors.PanEast.Handle) return Cursor.PanEast;
    if (h == Cursors.PanNE.Handle) return Cursor.PanNE;
    if (h == Cursors.PanNorth.Handle) return Cursor.PanNorth;
    if (h == Cursors.PanNW.Handle) return Cursor.PanNW;
    if (h == Cursors.PanSE.Handle) return Cursor.PanSE;
    if (h == Cursors.PanSouth.Handle) return Cursor.PanSouth;
    if (h == Cursors.PanSW.Handle) return Cursor.PanSW;
    if (h == Cursors.PanWest.Handle) return Cursor.PanWest;
    if (h == Cursors.Hand.Handle) return Cursor.Hand;
    return Cursor.UNKOWNCURSOR;
}

[StructLayout(LayoutKind.Sequential)]
struct POINT
{
    public Int32 x;
    public Int32 y;
}

[StructLayout(LayoutKind.Sequential)]
struct CURSORINFO
{
    public Int32 cbSize;        // Specifies the size, in bytes, of the structure. 
    // The caller must set this to Marshal.SizeOf(typeof(CURSORINFO)).
    public Int32 flags;         // Specifies the cursor state. This parameter can be one of the following values:
    //    0             The cursor is hidden.
    //    CURSOR_SHOWING    The cursor is showing.
    public IntPtr hCursor;          // Handle to the cursor. 
    public POINT ptScreenPos;       // A POINT structure that receives the screen coordinates of the cursor. 
}

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

Upvotes: 1

Alex from Jitbit
Alex from Jitbit

Reputation: 60642

After thee years its time to answer my own question. Here's how you check if the current global cursor is hourglass in C# (extend the code for you own needs if you need):

private static bool IsWaitCursor()
{
    var h = Cursors.WaitCursor.Handle;

    CURSORINFO pci;
    pci.cbSize = Marshal.SizeOf(typeof(CURSORINFO));
    if(!GetCursorInfo(out pci))
        throw new Win32Exception(Marshal.GetLastWin32Error());

    return pci.hCursor == h;
}

[StructLayout(LayoutKind.Sequential)]
struct POINT
{
    public Int32 x;
    public Int32 y;
}

[StructLayout(LayoutKind.Sequential)]
struct CURSORINFO
{
    public Int32 cbSize;        // Specifies the size, in bytes, of the structure. 
    // The caller must set this to Marshal.SizeOf(typeof(CURSORINFO)).
    public Int32 flags;         // Specifies the cursor state. This parameter can be one of the following values:
    //    0             The cursor is hidden.
    //    CURSOR_SHOWING    The cursor is showing.
    public IntPtr hCursor;          // Handle to the cursor. 
    public POINT ptScreenPos;       // A POINT structure that receives the screen coordinates of the cursor. 
}

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

Upvotes: 8

Sertac Akyuz
Sertac Akyuz

Reputation: 54802

OEM cursors are shared resources, so all processes requesting a specific cursor will retrieve the same handle. An application can cache standard system cursor handles at start-up, then it can use GetCursorInfo to get the global cursor handle, and look-up this handle in the cache to retrieve its kind - if it is of a system cursor.

The below Delphi sample code demonstrates. Cursor handles are populated to an array by using LoadImage at form creation. A timer polls the global cursor by using GetCursorInfo at regular intervals, the code looks-up the handle in the array to retrieve the cursor's name from a constant array of names:

const
  HighCursor = 13;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    FCursorHandles: array [0..HighCursor] of HCURSOR;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  OEMCursors: array [0..HighCursor] of Integer = (OCR_NORMAL, OCR_IBEAM,
      OCR_WAIT, OCR_CROSS, OCR_UP, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEWE,
      OCR_SIZENS, OCR_SIZEALL, OCR_NO, OCR_HAND, OCR_APPSTARTING,
      32651 {OCR_HELP?});

  CursorNames: array [0..HighCursor] of string = ('OCR_NORMAL', 'OCR_IBEAM',
      'OCR_WAIT', 'OCR_CROSS', 'OCR_UP', 'OCR_SIZENWSE', 'OCR_SIZENESW',
      'OCR_SIZEWE', 'OCR_SIZENS', 'OCR_SIZEALL', 'OCR_NO', 'OCR_HAND',
      'OCR_APPSTARTING', 'OCR_HELP');

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to HighCursor do
    FCursorHandles[i] := LoadImage(0, MakeIntResource(OEMCursors[i]),
        IMAGE_CURSOR, 0, 0, LR_DEFAULTCOLOR or LR_DEFAULTSIZE or LR_SHARED);
end;

procedure TForm1.Timer1Timer(Sender: TObject);

  function GetCursorName(Cursor: HCURSOR): string;
  var
    i: Integer;
  begin
    for i := 0 to HighCursor do
      if Cursor = FCursorHandles[i] then begin
        Result := CursorNames[i];
        Exit;
      end;
    Result := 'Unknown Cursor';  // A custom cursor.
  end;

var
  CursorInfo: TCursorInfo;
begin
  CursorInfo.cbSize := SizeOf(CursorInfo);
  if GetCursorInfo(CursorInfo) then
    Label1.Caption := GetCursorName(CursorInfo.hCursor)
  else
    Label1.Caption := 'Fail: ' + SysErrorMessage(GetLastError);
end;

Note that when using Delphi one does not have to cache cursor handles, since Delphi does it through its Screen.Cursors list. The sample code does not use it to have better portability.

Also note that there's no 'OCR_HELP' in 'winuser.h', but the provided constant corresponding to 'IDC_HELP' seems to work fine (though I couldn't find a dialog in W7 which makes use of the "Help Select" cursor).

Upvotes: 4

gabr
gabr

Reputation: 26830

To get the information on global cursor, use GetCursorInfo.

Upvotes: 5

Drejc
Drejc

Reputation: 14286

EDIT: In Delphi

In most visual objects you can use the Cursor property, otherwise use the Screen.Cursor propery. Setting it back to crDefault canceles your change to whatever it was set before.

Upvotes: 0

Toon Krijthe
Toon Krijthe

Reputation: 53366

Use (in Delphi)

Screen.MouseCursor.

For the current mouse cursor.

General Win32 (user32) gives:

function GetCursor: HCURSOR; stdcall;

This should be available for other win32 languages.

Upvotes: 4

Related Questions