3468
.pdfРис. 74. Организация подсистемы ввода-вывода
Обработка прерываний
Прерывания должны быть скрыты как можно глубже в недрах ОС, чтобы как можно меньшая часть ОС имела с ними дело.
161
Наилучший способ состоит в разрешении процессу, инициировавшему операцию ввода-вывода, блокировать себя до завершения операции и наступления прерывания.
Драйверы устройств
Весь зависимый от устройства код помещается в драйвер устройства.
Каждый драйвер управляет устройствами одного типа или, может быть, одного класса.
В ОС только драйвер устройства знает о конкретных особенностях какого-либо устройства.
Например, только драйвер диска имеет дело с дорожками, секторами, цилиндрами и другими факторами, обеспечивающими правильную работу диска.
Независимый от устройств слой ОС
Типичные функции:
•обеспечение общего интерфейса к драйверам устройств;
•именование устройств;
•защита устройств;
•обеспечение независимого размера блока;
•буферизация;
•распределение памяти на блок-ориентированных устройствах;
•распределение и освобождение выделенных устройств;
•уведомление об ошибках.
Пользовательский слой ПО
Большая часть ПО ввода-вывода находится внутри ОС, Некоторая его часть содержится в библиотеках, связы-
ваемых с пользовательскими программами.
Системные вызовы, включающие вызовы ввода-вывода, обычно делаются библиотечными процедурами.
162
Если программа, написанная на языке С, содержит вызов count = write (fd, buffer, nbytes),
то библиотечная процедура write будет связана с программой.
Набор подобных процедур является частью системы вво- да-вывода.
В частности, форматирование ввода или вывода выполняется библиотечными процедурами.
Функции API
1. Клавиатура
О состоянии клавиатуры дают информацию следующие функции API: GetKeyState, GetAsyncKeyState, GetKeyboardState.
1.1. Функция GetKeyState
Описание: function GetKeyState(VirtKey: Integer): Integer;
Функция определяет каково состояние виртуальной клавиши: поднята, нажата или пеpеключается.
Паpаметpы:
VirtKey - виpтуальная клавиша.
Возвpащаемое значение:
Клавиша нажата, если стаpший бит pавен 1, и клавиша пеpеключается, если младший бит pавен 1.
Функция GetKeyState (другое описание)
Declare Function GetKeyState Lib "user32.dll" (ByVal nVirtKey As Long) As Integer
Платформа
Windows NT: Требуется Windows NT 3.1 или выше.
Windows 2000: Поддерживается.
163
GetKeyState определяет текущее состояние клавиши. Функция находит, нажата ли клавиша в настоящее время или нет, и определяет, переключается ли клавиша в настоящее время.
Возвращаемое значение
Если установлен параметр &H1, клавиша переключается. Если установлен параметр &H80, то клавиша в данный момент нажата.
Параметры
nVirtKey - код виртуальной клавиши.
Windows NT, 2000: Это может быть один из следующих флажков, которые различают левый и правый Ctrl, Alt, и SHIFT:
Const VK_LSHIFT = &HA0 Левый Shift.
Const VK_RSHIFT = &HA1
Правый Shift.
Const VK_LCONTROL = &HA2
Левый Ctrl.
Const VK_RCONTROL = &HA3
Правый Ctrl.
Const VK_LMENU = &HA4
Левый Alt.
Const VK_RMENU = &HA5
Правый Alt.
Пример:
' Отобразим текущее состояние клавиши ENTER. Dim keystate As Long ' состояние клавиши
'Читаем текущее состояние клавиши ENTER. keystate = GetKeyState(VK_RETURN)
'Отобразим состояние переключателя клавиши ENTER. If (keystate And &H1) = &H1 Then
164
Debug.Print "Клавиша ENTER в настоящее время переключается."
Else
Debug.Print "Клавиша ENTER в настоящее время не переключается."
End If
' Нажимается ли Клавиша ENTER или нет. If (keystate And &H80) = &H80 Then
Debug.Print "Клавиша ENTER в настоящее время нажа-
та."
Else
Debug.Print "Клавиша ENTER сейчас не нажата." End If
Функция GetKeyboardState
Declare Function GetKeyboardState Lib "user32.dll" (pbKeyState As Byte) As Long
Платформа
Windows NT: Требуется Windows NT 3.1 или выше.
Windows 2000: Поддерживается.
GetKeyboardState отыскивает состояние каждой клавиши на клавиатуре и размещает информацию в массив. Каждый элемент массива с 256 элементами идентифицирует информацию относительно виртуальной клавиши, чей код виртуальной клавиши соответствует индексу элемента. На вашей клавиатуре нет 256 клавиш? Это сделано с прицелом на будущее. Если установлен бит &H1 , та клавиша выключена. Если установлен бит &H80, клавиша в настоящее время включена.
Примечание: Обратите внимание, что функции передается массив, указывая его первый элемент.
Возвращаемое значение
165
В случае ошибки функция возвращает 0 (используйте GetLastError для получения кода ошибки). В успешном случае функция возвращает значение отличное от нуля.
Параметры
pbKeyState - массив байтов с 256 элементами, который получает информацию состояния для всех виртуальных клавиш.
Каждая клавиша идентифицирована элементом, соответствующим коду виртуальной клавиши.
Windows NT, 2000: В дополнение к виртуальным клавишам, массив также получает информацию, способную различать левый и правый клавиши Ctrl, Alt, и SHIFT, которые помещены в массив в следующих индексах:
VK_LSHIFT = &HA0 Левый Shift. VK_RSHIFT = &HA1 Правыйt Shift. VK_LCONTROL = &HA2
Левый Ctrl. VK_RCONTROL = &HA3
Правый Ctrl. VK_LMENU = &HA4
Левый Alt. VK_RMENU = &HA5
Правый Alt.
Пример
'Установим статус для каждой клавиши на клавиатуре
'на "не включено"
Dim keystates(0 To 255) As Byte ' содержит статус всех клавиш в массиве
Dim c As Integer ' счетчик
Dim retval As Long ' возвращаемое значение
166
'Сначала, получим текущее состояние клавиатуры. retval = GetKeyboardState(keystates(0))
'Теперь, установим бит для всех клавиш в 0.
For c = 0 To 255
' Удостоверимся,что бит &H1 не установлен. keystates(c) = keystates(c) And (Not &H1) Next c
' Наконец, установим это к текущему состоянию клавиа-
туры.
retval = SetKeyboardState(keystates(0))
Процедура keybd_event
Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Платформа
Windows NT: Требуется Windows NT 3.1 или выше, но устарела для Windows NT 4.0 с Service Pack 3 (SP3) или выше;
пользуйтесь SendInput.
keybd_event имитирует нажатия клавиш на клавиатуре. keybd_event не является функцией и не возвращает ни-
каких значений.
Параметры
bVk - виртуальный код клавиши для имитации нажатия и отпускания клавиши;
bScan - зарезервировано (установлено в 0).
dwFlags - комбинация следующих флагов определяет различные способы имитации:
KEYEVENTF_EXTENDEDKEY
Префикс скэн-кода с префиксным байтом, имеющим значение &HE0.
KEYEVENTF_KEYUP
167
Клавиша, указанная в bVk будет отпущена. Если этот флажок не определен, клавиша будет нажата.
dwExtraInfo - дополнительное 32-разрядное значение, связанное с событием клавиатуры.
Константы
Const KEYEVENTF_EXTENDEDKEY = &H1 Const KEYEVENTF_KEYUP = &H2
Пример
' Имитируем нажатия клавиш CTRL+ESC для нажатия кнопки Пуск
keybd_event VK_CONTROL, 0, 0, 0 ' нажимаем CTRL keybd_event VK_ESCAPE, 0, 0, 0 ' нажимаем ESC keybd_event VK_CONTROL, 0, KEYEVENTF_KEYUP, 0
' отпускаем CTRL
keybd_event VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0 '
отпускаем ESC
2. Мышь
2.1.Функция GetDoubleClickTime
Declare Function GetDoubleClickTime Lib "user32.dll" () As
Long
Платформа: Win NT
GetDoubleClickTime определяет максимальный промежуток временив миллисекундах между двумя щелчками мыши, которые обрабатываются системой как двойной щелчок.
Пример:
'Показываем промежуток времени
'между двумя щелчками мыши в событии DoubleClick Dim doubletime As Long
doubletime = GetDoubleClickTime() ' получаем значение
промежутка времени в миллисекундах
Debug.Print doubletime; "миллисекунд"
168
2.2.Функция ReleaseCapture
Declare Function ReleaseCapture Lib "user32.dll" () As Long
Платформа
Windows NT: Требуется Windows NT 3.1 или выше.
Windows 2000: Поддерживается.
ReleaseCapture завершает фиксацию мыши для указанного окна. При вызове ReleaseCapture, все сообщения ввода мыши немедленно возвращаются обратно в обычный режим. Функция должна использоваться сразу же,как только вы уже не нуждаетесь в фиксации мыши после вызова SetCapture.
В успешном случае функция возвращает значение, отличное от нуля, в противном случае функция возвратит 0 (используйте GetLastError для получения кода ошибки).
Пример
'Перемещаем форму за любое место,
'а не только за заголовок
' Вставьте код в Form_MouseMove
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim retval As Long 'возвращаемое значение
If Button = 1 Then
Call ReleaseCapture
'посылаем сообщение о нажатии левой кнопки мыши на заголовке нашей формы
retval = SendMessage(Me.hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
End If
End Sub
' код для Form_Paint Private Sub Form_Paint()
Me.Print "Щелкните на форме и удерживая кнопку перетаскивайте форму"
End Sub
169
2.3.Функция SwapMouseButton
Declare Function SwapMouseButton Lib "user32.dll" (ByVal bSwap As Long) As Long
Платформа
Win 95/98, Win NT
SwapMouseButton изменяет настройку, используемую для кнопок мыши. Windows позволяет Вам интерпретировать щелчки с левой кнопкой как щелчки с правой кнопкой и наоборот. Эти функциональные возможности предназначены для левшей. Делайте это с предостережением - новые настройки будут действовать во всех программах. Функция возвращает 1 в успешном случае, или 0 в случае ошибки.
Параметры
bSwap - определяет настройки кнопки мыши.
Значение "0" не меняет кнопки . Значение "1" меняют левые и правые кнопки .
Пример
' Меняем кнопки местами
Dim retval As Long ' возвращаемое значение
retval = SwapMouseButton(1) ' переключаем кнопки Debug.Print "Вы поменяли местами левую и правую
кнопки мыши!"
Задание 1. Разработать программу, позволяющую пользователю получить информацию о состоянии клавиатуры, т.е. вывести на экран работу программы-ловушки нажатия пользователем некоторых клавиш.
Просмотреть функции API, описанные выше и относящиеся к данному заданию, применить их в приложении (самостоятельно).
Для языка программирования С# использовать:
170