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!!
To get the information on global cursor, use GetCursorInfo.
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);
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.
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).
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.