вторник, 11 мая 2010 г.

Эффект от SetCursor длится только до следующего вызова SetCursor

Это перевод The effect of SetCursor lasts only until the next SetCursor. Автор: Реймонд Чен.

Конечно же, эффект от вызова функции SetCursor для потока длится только пока этот поток не сменит курсор на что-то ещё. Любой идиот знает это, верно?

Хитрость заключается в том, что вызов SetCursor может произойти в неожиданном месте.

Чаще всего люди встречаются с этой проблемой, когда они делают что-то такое:
// Переключиться на песочные часы
  hcurPrev := SetCursor(hcurWait);
  ... выполняем работу ...
  // Восстановить оригинальный курсор
  SetCursor(hcurPrev);
Этот код призван устанавливать песочные часы на время работы. Но если во время этой работы вы обрабатываете сообщения (или вызываете функцию, которая это делает), то песочные часы могут уйти, вернув умалчиваемую стрелочку.

Это потому что прокачка сообщений открывает ворота для таких сообщений как WM_NCHITTEST и WM_SETCURSOR. Последнее обычно приводит к смене курсора либо на курсор, определяемый окном, либо на курсор, определяемый оконным классом, если это сообщение обрабатывается DefWindowProc.

Если вы хотите сохранить свои песочные часы даже во время прокачки сообщений, то вам нужно указать окну, что "если тебя спросят - ты хочешь песочные часы вместо того курсора, что ты обычно показываешь". Этому окну нужно изменить свою обработку WM_SETCURSOR, чтобы удовлетворить эту просьбу:
case Msg of
  ...
  WM_SETCURSOR:
    if ForceHourglass then
    begin
      SetCursor(hcurWait);
      Result := True;
    end;
  ...
Прим.пер.: в Delphi вся эта работа выполняется автоматически, если вы используете свойства Cursor объектов VCL вместо ручного программирования на WinAPI.

Заметьте, что форсированная установка песочных часов - это только вершина айсберга. Даже хотя курсор сменился на песочные часы, но окно всё ещё активно и может принимать ввод пользователя - движения мыши и клавиатуру. Если ваша программа не готова обрабатывать новый ввод во время работы, то ей нужно распознавать такую ситуацию, чтобы не попасть в ситуацию рекурсии, когда пользователь несколько раз подряд нажимает кнопку "Вычисления", пока вы ещё не закончили предыдущий расчёт.

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.