Подключение к очередям виртуального ввода и переменным локального состояния ввода
Как Вы уже убедились, отказоустойчивость модели ввода достигается благодаря тому, что у каждого потока имеются собственные переменные локального состояния вво да, а подключение потока к RIT и отключение от него происходит по мере необхо димости. Иногда нужно, чтобы два потока (или более) разделяли один набор пере менных локального состояния ввода или одну очередь виртуального ввода
Вы можете заставить два и более потока совместно использовать одну и ту же очередь виртуального ввода и переменные локального состояния ввода с помощью функции AttachTbreadInput:
BOOL AttachThreadInput( DWORD idAttach, DWORD idAttachTo, BOOL fAttach);
Параметр idAttach задаст идентификатор потока, чьи переменные локального со стояния ввода и очередь виртуального ввода Вам больше не нужны, а паряметр idAtta chedTo — идентификатор потока, чьи переменные локального состояния ввода и вир туальная очередь ввода должны совместно использоваться потоками И, наконец, па раметр fAttach должен быть или TRUE, чтобы инициировать совместное использова ние одной очереди, или FALSE — тогда каждый поток будет вновь использовать свои переменные состояния ввода и очередь А чтобы одну очередь (и переменные состо яния ввода) разделяли более двух потоков, вызовите АttасЬТhrеаdInput соответствую щее число раз.
Вернемся к одному из предыдущих примеров и допустим, что поток А вызывает AttachThreadlnput, передавая в первом параметре свой идентификатор, во втором — идентификатор потока В и в последнем — TRUE:
AttachThreadInput(idThreadA, idThreadB, TRUE);
Теперь любое событие аппаратного ввода, адресованное окну A1, B1 или B2, будет добавлено в конец очереди виртуального ввода потока В. Аналогичная очередь пото ка А больше не получит новых событий, если только Вы не разъедините очереди, повторно вызвав AttachThreadInput с передачей FALSE в параметре fAttach
Рис. 27-3. Аппаратные сообщения для окон А1, В1 и B2 помещаются в очередь виртуального ввода потока В
Потоки, присоединенные к одной очереди виртуального ввода (VIQ), сохраняют индивидуальные очереди сообщений (синхронных, асинхронных и ответных), а так же флаги пробуждения. Однако Вы серьезно снизите надежность системы, если зас тавите все потоки использовать одну очередь сообщений. Если какой-нибудь поток зависнет при обработке нажатия клавиши, другие потоки не получат никакого ввода. Поэтому использования AttachThreadInput следует по возможности избегать.
Система неявно соединяет очереди виртуального ввода двух потоков, если какой то из них устанавливает ловушку регистрации (journal record hook) или ловушку вос произведения (journal playback hook). Когда ловушка снимается, система восстанав ливает схему организации очереди ввода, существовавшую до установки ловушки.
Установкой ловушки регистрации поток сообщает, что хочет получать уведомле ния о всех аппаратных событиях, вызываемых пользователем. Поток обычно сохра няет или регистрирует эту информацию в файле. Так как пользовательский ввод дол жен быть зарегистрирован в том порядке, в каком он происходил, все потоки в сис теме начинают разделять одну очередь виртуального ввода для синхронизации обра ботки ввода.
Есть еще один случай, когда система неявно вызывает AttachThreadlnput. Допустим, приложение создает два потока. Первый открывает на экране диалоговое окно Затем второй поток вызывает CreateWindow, указывая стиль WS_CHILD и передавая описа
тель этого диалогового окна, чтобы оно стало "родителем" дочернего окна. Тогда система сама вызывает АttасhТhrеаdIпрut, чтобы поток (которому принадлежит дочер нее окно) использовал ту же очередь ввода, что и поток, создавший исходное диало говое окно Это приводит к синхронизации ввода во всех дочерних окнах исходного диалогового окна.