Как определить, анимирован ли текущий курсор мыши?

есть ли способ определить, анимирован ли текущий курсор мыши?

Я искал способ как сохранить текущий курсор некоторое время назад. Я нашел функцию DrawIconEx, которая идеально подходит для моей цели. К сожалению, я не знаю, как определить, анимирован ли текущий курсор. Я надеялся, что если я установлю для параметра istepIfAniCur значение 1 в случае статического курсора DrawIconEx возвращает False, но он действительно игнорирует этот параметр и возвращает True, что не позволяет мне использовать его в цикле для получения статического курсора, а также всех кадров из анимированного. В случае с анимацией он работает так, как ожидалось, поэтому, когда вы выходите за пределы диапазона с помощью istepIfAniCur, он возвращает False.

Итак, как мне узнать, что HICON (HCURSOR) является анимированным курсором? Как DrawIconEx определяет, что курсор анимирован?

Большое спасибо


person Community    schedule 06.08.2011    source источник
comment
Похоже, вы пишете программное обеспечение для удаленного рабочего стола. Если да, то не должны ли вы использовать курсоры локальной машины?   -  person David Heffernan    schedule 07.08.2011
comment
@ Дэвид - да, что-то похожее. Но мои последние два вопроса возникли в основном из-за моего любопытства. Конечно, я должен отобразить набор курсоров, который находится на стороне зрителя, я не могу позволить пользователю нащупать что, черт возьми, за курсор прыгающего кролика на его стороне. Я только застрял на этой примитивной вещи и удивляюсь, как DrawIconEx распознает, что вы передаете ему анимированный дескриптор курсора, в моем случае он не имеет практического применения.   -  person    schedule 07.08.2011
comment
@David - теперь, когда я думаю об этом; как насчет пользовательского курсора? В этом случае было бы неплохо позволить зрителю видеть, например, кисть, если пользователь на другой стороне рисует. В случае OEM курсоров я, конечно, буду использовать набор просмотра.   -  person    schedule 07.08.2011
comment
Возможно, вы можете использовать GetIconInfo для получения размеров растрового изображения, связанного с курсором (используя GetObject), и получить numFrames = width_of_bitmap / height_of_bitmap`, предполагая, что все курсоры квадратные.   -  person user786653    schedule 07.08.2011
comment
@user786653 user786653 - Я пробовал, но мне всегда возвращается ширина одного кадра. См. временный ответ с примером Delphi ниже.   -  person    schedule 07.08.2011


Ответы (3)


Я нашел один обходной путь — перейти к параметру istepIfAniCur в DrawIconEx равно UINT. Невозможно, чтобы кто-то создал анимированный курсор с 4 294 967 295 кадрами (может быть, для какого-то ролика курсора :)

Учитывая этот факт, вы можете передать это значение в DrawIconEx. функция, которая вернет False в случае, если курсор анимирован (из-за превышения диапазона кадров) и True в случае статического, поскольку игнорирует параметр istepIfAniCur. Вы должны передать 0 параметру diFlags, потому что не нужно ничего рисовать.

Вот пример Дельфи:

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 ...';

И поскольку я обещал тег C++, вот моя попытка перевода

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 ...";


На превышение диапазона кадров также указывает ошибка ОС ERROR_INVALID_PARAMETER, что можно проверить с помощью GetLastError, когда DrawIconEx не работает.

person Community    schedule 07.08.2011

Лучший способ:

      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);
person user2558526    schedule 02.03.2017
comment
Это весь код? В конце чего-то не хватает - person Aleks G; 03.03.2017
comment
Насколько я могу судить, GetCursorFrameInfo — это недокументированный API, но я считаю, что он должен предоставить вам информацию о скорости отображения и общем количестве кадров. Если курсор статичен, я ожидаю, что общее количество кадров будет равно 1 (или, может быть, 0). Если это анимация, она должна сообщить вам, сколько кадров в цикле анимации. - person Adrian McCarthy; 03.03.2017

Вот пример в Delphi (и попытка перевода на C++), как я пытался получить размеры курсора, используя GetIconInfo, но она работает не так, как я ожидал. Он всегда возвращает ширину одного кадра в случае анимированного курсора, поэтому кажется, что GetIconInfo вообще не заботится о фреймах. Или я ошибаюсь?

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;

Моя попытка Visual C++ (обратите внимание, что я не знаю C++ и не имею компилятора :)

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);
person Community    schedule 07.08.2011
comment
Как насчет bmWidthBytes члена Bitmap? Он может иметь реальную ширину. - person user786653; 08.08.2011
comment
Это возвращает мне 128, но я думаю, что это не то, что нам нужно: The number of bytes in each scan line. This value must be divisible by 2, because the system assumes that the bit values of a bitmap form an array that is word aligned. поэтому я бы сказал, что это может сработать, если мы знаем B/px, что такое я предполагаю вызов другой функции. - person ; 08.08.2011
comment
Предполагая, что ваш курсор 32-битный и 32x32, это тоже нехорошо. Это был просто выстрел в темноте в надежде, что он вернет объединенную ширину анимированных кадров курсора. - person user786653; 08.08.2011
comment
@ user786653 - Я надеялся на то же самое. Такая простая вещь и такая сложная. Если MS не будет игнорировать параметр istepIfAniCur, то мы сможем рисовать статический курсор или все анимированные кадры за один цикл. - person ; 08.08.2011