При работе с курсорами в Delphi разработчики часто сталкиваются с неочевидным поведением константы crNone.
В этой статье мы разберем три ключевых вопроса:
1. Почему crNone отсутствует в Object Inspector?
2. Что на самом деле делает crNone?
3. Как правильно скрывать курсор в компонентах?
1. Почему crNone отсутствует в Object Inspector?
Хотя в модуле System.UITypes объявлена константа crNone = TCursor(-1), она не отображается в выпадающем списке Object Inspector. Причина кроется в реализации функций работы с курсорами в модуле System.UIConsts:
// System.UIConsts.pas
function GetCursorValues: TStringList;
begin
Result := Cursors;
end;
Массив Cursors содержит только стандартные курсоры, исключая crNone. Поэтому редактор свойств просто не включает его в список доступных вариантов.
Обходное решение: Вы можете вручную установить значение -1 в свойстве Cursor через Object Inspector (для этого нужно включить режим отображения числовых значений через Ctrl+Alt+S):
2. Что на самом деле делает crNone?
По задумке, crNone должен скрывать курсор при наведении на компонент. Однако в некоторых случаях (особенно в FMX) вместо скрытия курсора вы можете увидеть курсор с вопросительным знаком или другой нестандартный указатель.
Это происходит из-за особенностей реализации курсоров в разных платформах (Windows, macOS, Android). Для кроссплатформенных приложений рекомендуется использовать альтернативные методы.
3. Как правильно скрывать курсор в компонентах?
Способ 1: Использование crNone (работает не всегда)
Panel1.Cursor := crNone; // или Panel1.Cursor := -1;
Если этот способ работает в вашей среде - отлично. Но для гарантированного результата лучше использовать другие методы.
Способ 2: Переопределение метода SetCursor (FMX)
type
TMyPanel = class(TPanel)
protected
procedure SetCursor; override;
end;
procedure TMyPanel.SetCursor;
begin
// Не вызываем inherited - курсор не будет изменен
end;
Способ 3: Использование платформозависимого кода (Windows)
uses
Winapi.Windows;
procedure TForm1.Panel1MouseEnter(Sender: TObject);
begin
ShowCursor(False);
end;
procedure TForm1.Panel1MouseLeave(Sender: TObject);
begin
ShowCursor(True);
end;
Расхождения в поведении crNone могут быть вызваны:
1. Версией Delphi (12.2 vs 12.3)
2. Использованием VCL vs FMX
3. Внешними факторами (антивирусы, удаленный доступ)
4. Настройками операционной системы
Рекомендации
Для FMX-приложений используйте переопределение SetCursor
Для кроссплатформенных решений создавайте кастомный "пустой" курсор
Тестируйте поведение на всех целевых платформах
При использовании crNone добавляйте комментарии для ясности:
Panel1.Cursor := crNone; // -1, попытка скрыть курсор
Заключение
Хотя crNone не отображается в Object Inspector и не всегда работает ожидаемым образом, в Delphi существует несколько надежных способов управления курсором. Выбор метода зависит от конкретной задачи и целевых платформ. Для профессиональных приложений рекомендуется использовать переопределение методов управления курсором или создание кастомных курсоров.
Объяснение причин отсутствия курсора crNone в Object Inspector Delphi, его фактического поведения и различных методов корректного скрытия курсора в компонентах.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS