Управление курсором мыши
В концепцию локального состояния ввода входит и управление состоянием курсора мыши. Поскольку мышь, как и клавиатура, должна быть доступна всем потокам, Win dows не позволяет какому-то одному потоку монопольно распоряжаться курсором мыши, изменяя его форму или ограничивая область его перемещения. Посмотрим, как система управляет этим курсором
Один из аспектов управления курсором мыши заключается в его отображении или гашении, Если поток вьзывает ShowCursor(FAI.SE), то система скрывает курсор, когда он оказывается на любом окне, созданном этим потоком, и показывает курсор вся кий раз, когда он попадает в окно, созданное другим потоком.
Другой аспект управления курсором мыши — возможность ограничить его пере мещение каким-либо прямоугольным участком. Для этого надо вызвать функцию ClipCursor:
BOOL ClipCursor(CONST RECT *ргс);
Она ограничивает перемещение курсора мыши прямоугольником, на который указывает параметр prc. И опять система разрешает потоку ограничить перемещение курсоря заданным прямоугольником. Но, когда возникает событие асинхронной ак тивизации, т. e. когда пользователь переключается в окно другого приложения, нажи мает клавиши Ctrl+Esc или же поток вызывает SetForegroundWindow, система снимает ограничения на передвижение курсора, позволяя свободно перемещать его по экрану.
И здесь мы подошли к концепции захвата, мыши (mouse capture). "Захватывая" мышь (вызовом SetCapture), окно требует, чтобы все связанные с мышью сообщения RIT отправлял в очередь виртуального ввода вызывающего потока, а из нее — устано вившему захват окну до тех пор, пока программа не вызовет ReleaseCapture.
Как и в предыдущих случаях, это тоже снижает отказоустойчивость системы, но без компромиссов, увы, не обойтись. Вызывая SetCapture, поток заставляет RIT поме щать все сообщения от мыши в свою очередь виртуального ввода. При этом SetCapture соответственно настраивает переменные локального состояния ввода данного потока.
Обычно приложение вызывает SetCapture, когда пользователь нажимает кнопку мыши.
Но поток может вызвать эту функцию, даже если нажатия кнопки мыши не было. Если SetCapture вызывается при нажатой кнопке, захват действует для всей си стемы Как только система определяет, что все кнопки мыши отпущены, RIT переста ет направлять сообщения от мыши исключительно в очередь виртуального ввода дан ного потока. Вместо этого он передает сообщения в очередь ввода, связанную с ок ном, "поверх" которого курсор находится в данный момент. И это нормальное пове дение системы, когда захват мыши не установлен
Однако для вызвавшего SetCapture потока ничего не меняется. Всякий раз, когда курсор оказывается на любом из окон, созданных установившим захват потоком, со общения от мыши направляются в окно, применительно к которому этот захват и установлен. Иначе говоря, когда пользователь отпускает всс кнопки мыши, захват осуществляется на уровне лишь данного потока, а нс всей системы
Если пользователь попытается активизировать окно, созданное другим потоком, система автоматически отправит установившему захват потоку сообщения о нажатии и отжатии кнопок мыши. Затем она изменит переменные локального состояния вво да потока, чтобы отразить тот факт, что поток более не работает в режиме захвата. Словом, Microsoft считает, что захват мыши чаще всего применяется для выполнения таких операций, как щелчок и перетаскивание экранного объекта.
Последняя переменная локального состояния ввода, связанная с мышью, относится к форме курсора. Всякий раз, когда поток вызывает SetCursor для изменения формы курсора, переменные локального состояния ввода соответствующим образом обнов ляются То есть переменные локального состояния ввода всегда запоминают послед нюю форму курсора, установленную потоком
Допустим, пользователь перемещает курсор мыши на окно Вашей программы, окно получает сообщение WM_SETCURSOR, и Вы вызываете SetCursor, чтобы преоб разовать курсор в "несочные часы". Вызвав SetCursor, программа начинает выполнять какую-то длительную операцию (Бесконечный цикл — лучший пример длительной операции Шутка ) Далее пользователь перемещает курсор из окна Вашей программы в окно другого приложения, и это окно может изменить форму курсора.
Для такого изменения переменные локального состояния ввода не нужны Но пе реведем курсор обратно в то окно, поток которого по-прежнсму занят обработкой. Системе "хочется" послать окну сообщения WM_SETCURSOR, но процедура этого окна не может выбрать их из очереди, так кяк его поток продолжает свою операцию. Тогда система определяет, какая форма была у курсора в прошлый раз (информация об этом содержится в переменных локального состояния ввода данного потока), и автомати чески восстанавливает ее (в нашем примере — "песочные часы"). Теперь пользовате лю четко видно, что в этом окне работа еще не закончена и придется подождать.