get current mouse cursor type

2019-02-22 09:27发布

问题:

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

回答1:

To get the information on global cursor, use GetCursorInfo.



回答2:

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));
    GetCursorInfo(out pci);

    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")]
static extern bool GetCursorInfo(out CURSORINFO pci);


回答3:

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.



回答4:

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).



回答5:

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.