问题
is there a way how to determine if the current mouse cursor is animated ?
I was looking for a way how to save the current cursor some time ago. I found the DrawIconEx function which perfectly suits to my purpose. Unfortunately I don't know how do I determine if the current cursor is animated. I was hoping that if I set the istepIfAniCur parameter to 1 in case of static cursor DrawIconEx returns False but it really ignores that parameter and returns True what disallows me to use it in the loop for getting the static cursor as well as all the frames from the animated one. In case of animated one works as expected so when you get out of range with istepIfAniCur it returns False.
So how do I find out that HICON (HCURSOR) is the animated cursor ? How the DrawIconEx determine that the cursor is animated ?
Thanks a lot
回答1:
I've found one workaround - pass to the istepIfAniCur parameter of the DrawIconEx function max value of UINT. It's impossible that someone would create animated cursor with 4,294,967,295 frames (possible maybe for some cursor movie :)
With this fact you can pass this value to the DrawIconEx function which will return False in case when the cursor is animated (because of exceeding the frame range) and True in case of static one, because it ignores the istepIfAniCur parameter. You should pass 0 to the diFlags parameter because there's no need to draw anything.
Here's the Delphi example:
if not DrawIconEx(Canvas.Handle, 0, 0, hCursor, 0, 0, High(Cardinal), 0, 0) then
Caption := 'Cursor is animated ...'
else
Caption := 'Cursor is not animated ...';
And because I promised C++ tag here's my translation attempt
if (!DrawIconEx(this->Canvas->Handle, 0, 0, hCursor, 0, 0, UINT_MAX, NULL, 0))
this->Caption = "Cursor is animated ...";
else
this->Caption = "Cursor is not animated ...";
Exceeding the frame range is also indicated by the OS error ERROR_INVALID_PARAMETER what you may inspect using GetLastError function when the DrawIconEx fails.
回答2:
Best way:
typedef HCURSOR(WINAPI* GET_CURSOR_FRAME_INFO)(HCURSOR, LPCWSTR, DWORD, DWORD*, DWORD*);
GET_CURSOR_FRAME_INFO fnGetCursorFrameInfo = 0;
HMODULE libUser32 = LoadLibraryA("user32.dll");
if (!libUser32)
{
return false;
}
fnGetCursorFrameInfo = reinterpret_cast<GET_CURSOR_FRAME_INFO>(GetProcAddress(libUser32, "GetCursorFrameInfo"));
if (!fnGetCursorFrameInfo)
{
return false;
}
DWORD displayRate, totalFrames;
fnGetCursorFrameInfo(hcursor, L"", 0, &displayRate, &totalFrames);
回答3:
Here's the example in Delphi (and attempt to translation to C++) how I was trying to get the cursor dimensions using GetIconInfo function, but it doesn't work as I've expected. It always returns the width of one frame in case of animated cursor so it seems that GetIconInfo doesn't take care of the frames at all. Or am I wrong ?
procedure TForm1.Timer1Timer(Sender: TObject);
var
IconInfo: TIconInfo;
CursorInfo: TCursorInfo;
Bitmap: Windows.TBitmap;
begin
CursorInfo.cbSize := SizeOf(CursorInfo);
GetCursorInfo(CursorInfo);
GetIconInfo(CursorInfo.hCursor, IconInfo);
if GetObject(IconInfo.hbmColor, SizeOf(Bitmap), @Bitmap) <> 0 then
begin
Caption := 'Cursor size: ' +
IntToStr(Bitmap.bmWidth) + ' x ' +
IntToStr(Bitmap.bmHeight) + ' px';
end;
DeleteObject(IconInfo.hbmColor);
DeleteObject(IconInfo.hbmMask);
end;
My Visual C++ attempt (note that I don't know C++ and have no compiler :)
CString txt;
ICONINFO ii;
CURSORINFO ci;
BITMAP bitmap;
ci.cbSize = SizeOf(CURSORINFO);
GetCursorInfo(ci);
GetIconInfo(ci.hCursor, ii);
GetObject(ii.hbmColor, sizeof(BITMAP), &bitmap);
txt.Format("Cursor width: %d px", bitmap.bmWidth);
MessageBox(txt);
来源:https://stackoverflow.com/questions/6969801/how-do-i-determine-if-the-current-mouse-cursor-is-animated