Аппаратное обеспечение персонального компьютера© Александр Фролов, Григорий ФроловТом 33, М.: Диалог-МИФИ, 1997, 304 стр. Мышь Microsoft IntelliMouseВ 1997 году Microsoft выпустила новую мышь с названием Microsoft IntelliMouse, добавив в нее принципиально новый орган управления – небольшое колесо, расположенное между левой и правой клавишами мыши. Это небольшое, на первый взгляд, усовершенствование намного упрощает работу пользователей с приложениями Windows, в которых нужно просматривать длинные документы или выполнять плавное масштабирование изображений. Колесо имеет двойное назначение. Во-первых, оно служит вместо третьей кнопки, которая есть в трехкнопочных мышах типа Mouse System и совместимых с ними. Ранее Microsoft упорно игнорировала третью кнопку в приложениях Windows, однако как вы увидите, теперь положение несколько изменилось. Во-вторых, вы можете вращать колесо в обоих направлениях без ограничения угла поворота, причем такое вращение имеет дискретный характер. Приложение Windows может использовать колесо, например, вместо вертикальной полосы просмотра Scrollbar. В этом случае для того чтобы сдвинуть содержимое окна просмотра, вам не нужно снимать руку с мыши и переносить ее на клавиатуру или перемещать курсор мыши к полосе просмотра. Достаточно просто немного повернуть колесо в нужном направлении – и содержимое окна будет сдвинуто. К сожалению, для использования возможности новой мыши вам не достаточно просто подключить ее к компьютеру и установить соответствующий драйвер. Программы MS-DOS и приложения Microsoft Windows версии 3.1 совсем не могут пользоваться колесом, принимая новую мышь как обычную двухкнопочную мышь Microsoft. Что же касается приложений Microsoft Windows 95 и Microsoft Windows NT, то в них необходимо предусмотреть обработку сообщений, создаваемых колесом. Заметим, что все новые приложения, созданные Microsoft, такие как Microsoft Office 97 и Microsoft Visual C++ версии 5.0, умеют работать с мышью Microsoft IntelliMouse. Для того чтобы воспользоваться колесом в старых приложениях, таких как Microsoft Word 7.0, вы можете применить условно-бесплатное приложение Flywheel, загрузив его из Internet с сервера Web, расположенного по адресу http://www.plannetarium.com. Это приложение преобразует сообщения от колеса в сообщения от вертикальной полосы просмотра и выполняет ряд других интересных функций. Мы же в этой книге расскажем вам, как можно оорганизовать обработку сообщений от колеса мыши Microsoft IntelliMouse в своих приложениях. Проверка наличия мыши Microsoft IntelliMouseВаше приложение должно уметь работать с любой мышью, даже если в нем предусмотрена обработка специфических сообщений от мыши Microsoft IntelliMouse. Поэтому не будет лишним в процессе инициализации приложения определить, подключена ли к компьютеру мышь Microsoft IntelliMouse или обычная мышь. Способ проверки зависит от операционной системы. Проверка в среде Microsoft Windows 95 и Microsoft Windows NT версии 3.51В текущей на момент написания книги версии Microsoft Windows 95 драйвер мыши Microsoft IntelliMouse отсутствует. Если вы купили такую мышь, необходимо установить драйвер с дискеты, которая прилагается к мыши. Для проверки наличия мыши с колесом в среде Microsoft Windows 95 вам следует сначала зарегистрировать сообщение с кодом MSH_WHEELSUPPORT, вызвав для этого функцию RegisterWindowMessage: UINT uMSH_SUPPORT = 0; uMSH_SUPPORT = RegisterWindowMessage(MSH_WHEELSUPPORT); Идентификатор MSH_WHEELSUPPORT, а также другие идентификаторы, необходимые для программирования новой мыши, находятся в файле zmouse.h, который можно бесплатно переписать в составе Microsoft IntelliMouse SDK с сервера Microsoft с адресом http://www.microsoft.com. Далее нужно определить идентификатор главного окна приложения MSWheel, которое устанавливается с дискеты, входящей в комплект мыши. Идентификатор определяется следующим образом: HWND hwndMSHWheel = NULL; hwndMSHWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); Если сообщение MSH_WHEELSUPPORT успешно зарегистрировано, а указанный выше идентификатор определен, можно послать сообщение MSH_WHEELSUPPORT в окно приложения MSWheel, вызвав для этого функцию SendMessage: BOOL fWheel = FALSE; if(uMSH_SUPPORT != 0 && hwndMSHWheel != 0) { fWheel = (BOOL)SendMessage(hwndMSHWheel, uMSH_SUPPORT, 0, 0); } Если мышь Microsoft IntelliMouse подключена, функция SendMessage возвратит значение TRUE, если нет – FALSE. Проверка в среде Microsoft Windows NT версии 4.0Операционная система Microsoft Windows NT версии 4.0 содержит драйвер мыши Microsoft IntelliMouse, поэтому установка дополнительных драйверов не требуется. Проверить наличие мыши с колесом можно при помощи обычной функции GetSystemMetrics, передав ей в качестве параметра значение SM_MOUSEWHEELPRESENT: if(!GetSystemMetrics(SM_MOUSEWHEELPRESENT)) { MessageBox(NULL, "Microsoft IntelliMouse not found", "Error message", MB_OK); } Если функция возвратит нулевое значение, значит мышь Microsoft IntelliMouse не подключена к компьютеру. Определение величины сверткиКак мы уже говорили, колесо мыши Microsoft IntelliMouse вращается дискретно, как будто на нем есть засечки. При повороте колеса на каждую такую засечку приложение, получив от мыши сообщение, обычно свертывает документ на заранее определенное количество строк или на целую страницу. Величина свертки определяется настройкой драйвера мыши. По умолчанию каждый поворот колеса соответствует сдвигу на 3 строки. Вы, однако, можете установить другое значение, либо указать, что свертка должна выполняться постранично. Когда вы обрабатываете сообщения, поступающие от колеса мыши, величина и вид свертки должны определяться с учетом параметров, установленных для драйвера мыши. Способ определения величины свертки зависит от версии операционной системы. Определение величины свертки в среде Microsoft Windows 95 и Microsoft Windows NT версии 3.51В среде операционных систем Microsoft Windows 95 и Microsoft Windows NT версии 3.51 для определения величины свертки вначале необходимо зарегистрировать сообщение MSH_SCROLL_LINES: UINT uMSH_SCROLL_LINES = 0; uMSH_SCROLL_LINES = RegisterWindowMessage(MSH_SCROLL_LINES); Затем это сообщение посылается приложению MSWheel с помощью функции SendMessage: UINT uiScrollLines = 3; uiScrollLines = (BOOL)SendMessage(hwndMSHWheel, uMSH_SCROLL_LINES, 0, 0); Функция возвращает величину свертки в строках или значение WHEEL_PAGESCROLL, если в параметрах драйвера мыши задано, что при вращении колеса мыши должна выполняться постраничная свертка. Определение величины свертки в среде Microsoft Windows NT версии 4.0Если приложение работает в среде операционной системы Microsoft Windows NT версии 4.0, то оно должно определять величину свертки с помощью функции SystemParametersInfo: UINT uiScrollLines = 3; SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uiScrollLines, 0); Эта функция предназначена для определения различных системных параметров. В качестве первого параметра функции SystemParametersInfo передается значение SPI_GETWHEELSCROLLLINES, а в качестве третьего – адрес переменной типа UINT, в которую будет записана величина свертки. Сообщение MSH_MOUSEWHEELРабота мыши Microsoft IntelliMouse в среде операционных систем Microsoft Windows 95 и Microsoft Windows NT версии 3.51 обеспечивается приложением MSWheel, которое устанавливается с дискеты, входящей в комплект мыши. При повороте колеса приложение MSWheel посылает сообщение MSH_MOUSEWHEEL в функцию главного окна приложения, над которым находится курсор мыши. Перед тем как использовать это сообщение, его необходимо зарегистрировать функцией RegisterWindowMessage: UINT uMSH_MOUSEEHEEL = 0; uMSH_MOUSEEHEEL = RegisterWindowMessage(MSH_MOUSEWHEEL); Ниже мы привели парамтеры сообщения MSH_MOUSEWHEEL:
Значение угла поворота изменяется дискретно с шагом 120. Если это значение положительно, колесо поворачивается в сторону пользователя, если отрицательно – в сторону монитора компьютера (это правило может быть изменено пользователем соответствующей настройкой параметров драйвера мыши). Получив сообщение MSH_MOUSEWHEEL, функция главного окна приложения может обработать его самостоятельно или передать дочерним окнам. Сообщение WM_MOUSEWHEELСообщение WM_MOUSEWHEEL определено в операционной системе Microsoft Windows NT версии 4.0 и будет влкючено в новую версию операционной системы Microsoft Windows 95. По своему назначению оно аналогично сообщению MSH_MOUSEWHEEL, но имеет немного другие параметры:
Код виртуальной клавиши может иметь следующие значения:
Другие сообщения от мыши Microsoft IntelliMouseПомимо только что описанных сообщений MSH_MOUSEWHEEL и WM_MOUSEWHEEL, мышь Microsoft IntelliMouse может посылать такие же сообщения, как и обычная трехкнопочная мышь. Сообщения, возникающие когда пользователь нажимает или отжимает колесо, эквивалентны сообщениям от средней кнопки трехкнопочной мыши. Подробное описание параметров всех этих сообщений вы найдете в 11 томе «Библиотеки системного программиста», который называется «Операционная система Microsoft Windows для программиста». Приложение RTFPADВ 22 томе «Библиотеки системного программиста», который называется «Операционная система Windows 95 для программиста» мы привели исходные тексты приложения RTFPAD. Это приложение представляет собой текстовый редактор, способный работать с документами в формате RTF. Такой документ может содержать шрифтовое оформление. Для того чтобы продемонстрировать обработку сообщений от мыши Microsoft IntelliMouse, мы немного изменили приложение RTFPAD. В листинге 3.7 вы найдете исходный текст измененных функций WinMain и WndProc. Обратите внимание, что при инициализации приложения мы определяем версию операционной системы с тем чтобы приложение могло работать как в среде Microsoft Windows 95, так и в среде Microsoft NT версии 4.0. Листинг 3.7 (сокращенный). Файл rtfpad\rtfpad.с // ===================================================== // Редактор текста RTFPAD, способный работать // с мышью Microsoft IntelliMouse // // (C) Фролов А.В, 1996, 1997 // // E-mail: frolov@glas.apc.org // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ===================================================== // Это определение нужно для того, чтобы при компилляции // файла winuser.h были подключены определения // идентификаторов SPI_GETWHEELSCROLLLINES // и WM_MOUSEWHEEL #define _WIN32_WINNT 0x0400 // Еще один способ определения этих же идентификаторов //#ifndef SPI_GETWHEELSCROLLLINES //#define SPI_GETWHEELSCROLLLINES 104 //#endif //#ifndef WM_MOUSEWHEEL //#define WM_MOUSEWHEEL WM_MOUSELAST+1 //#endif #define STRICT #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <richedit.h> // Необходимо для определения значения константы // UINT_MAX, которая используется в файле zmouse.h #include <limits.h> #include "resource.h" #include "afxres.h" // Файл определений для IntelliMouse #include "zmouse.h" #include "rtfpad.h" // Код сообщения MSH_MOUSEEHEEL UINT uMSH_MOUSEEHEEL = 0; // Код сообщения MSH_SUPPORT UINT uMSH_SUPPORT = 0; // Код сообщения MSH_SCROLL_LINES UINT uMSH_SCROLL_LINES = 0; // Идентификатор окна для посылки сообщений // приложению MSWheel HWND hwndMSHWheel = NULL; // Флаг наличия мыши Microsoft IntelliMouse BOOL fWheel = FALSE; // Количество строк свертки UINT uiScrollLines = 3; // Структура для определения версии // операционной системы OSVERSIONINFO osv; HINSTANCE hInst; char szAppName[] = "RtfEditApp"; char szAppTitle[] = "Rich Text Editor RtfPad"; HWND hwndEdit; HINSTANCE hRTFLib; // ----------------------------------------------------- // Функция WinMain // ----------------------------------------------------- int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hWnd; MSG msg; hInst = hInstance; hWnd = FindWindow(szAppName, NULL); if(hWnd) { if(IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE); SetForegroundWindow(hWnd); return FALSE; } // Определяем версию операционной системы memset(&osv, 0, sizeof(OSVERSIONINFO)); osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osv); // Для Windows 95 и Windows NT версии 3.51 выполняем // регистрацию сообщений if( (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) || ((osv.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osv.dwMajorVersion < 4))) { // Регистрируем сообщение MSH_WHEELSUPPORT uMSH_SUPPORT = RegisterWindowMessage(MSH_WHEELSUPPORT); // Определяем наличие мыши Microsoft IntelliMouse hwndMSHWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); if(uMSH_SUPPORT != 0 && hwndMSHWheel != 0) { fWheel = (BOOL)SendMessage(hwndMSHWheel, uMSH_SUPPORT, 0, 0); } if(!fWheel) { MessageBox(NULL, "MS Wheel not supported", "Error message", MB_OK); } // Регистрируем сообщение MSH_MOUSEWHEEL uMSH_MOUSEEHEEL = RegisterWindowMessage(MSH_MOUSEWHEEL); if(!uMSH_MOUSEEHEEL) { MessageBox(NULL, "Error: RegisterWindowMessage", "Error message", MB_OK); return FALSE; } // Регистрируем сообщение MSH_SCROLL_LINES uMSH_SCROLL_LINES = RegisterWindowMessage(MSH_SCROLL_LINES); // Определяем количество строк свертки if(uMSH_SCROLL_LINES != 0 && hwndMSHWheel != 0) { uiScrollLines = (BOOL)SendMessage(hwndMSHWheel, uMSH_SCROLL_LINES, 0, 0); } } // Для Windows NT версии 4.0 применяем другую методику else { // Проверяем наличие мыши Microsoft IntelliPoint if(!GetSystemMetrics(SM_MOUSEWHEELPRESENT)) { MessageBox(NULL, "Microsoft IntelliMouse not found", "Error message", MB_OK); } // Определяем количество строк свертки SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uiScrollLines, 0); } hRTFLib = LoadLibrary("RICHED32.DLL"); if(!hRTFLib) return FALSE; memset(&wc, 0, sizeof(wc)); wc.cbSize = sizeof(WNDCLASSEX); wc.hIconSm = LoadImage(hInst, MAKEINTRESOURCE(IDI_APPICONSM), IMAGE_ICON, 16, 16, 0); wc.style = 0; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = LoadImage(hInst, MAKEINTRESOURCE(IDI_APPICON), IMAGE_ICON, 32, 32, 0); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wc.lpszMenuName = MAKEINTRESOURCE(IDR_APPMENU); wc.lpszClassName = szAppName; if(!RegisterClassEx(&wc)) if(!RegisterClass((LPWNDCLASS)&wc.style)) return FALSE; hWnd = CreateWindow(szAppName, szAppTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL); if(!hWnd) return(FALSE); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } // ----------------------------------------------------- // Функция WndProc // ----------------------------------------------------- LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Изменение положения колеса short zDelta; switch(msg) { HANDLE_MSG(hWnd, WM_CREATE, WndProc_OnCreate); HANDLE_MSG(hWnd, WM_DESTROY, WndProc_OnDestroy); HANDLE_MSG(hWnd, WM_COMMAND, WndProc_OnCommand); HANDLE_MSG(hWnd, WM_SIZE, WndProc_OnSize); HANDLE_MSG(hWnd, WM_SETFOCUS, WndProc_OnSetFocus); default: { if(msg == WM_MOUSEWHEEL) { zDelta = (short)HIWORD(wParam); if(zDelta < 0) if(uiScrollLines != WHEEL_PAGESCROLL) SendMessage(hwndEdit, EM_LINESCROLL, 0, uiScrollLines); else SendMessage(hwndEdit, EM_SCROLL, (WPARAM)(INT)SB_PAGEDOWN, 0); else if(uiScrollLines != WHEEL_PAGESCROLL) SendMessage(hwndEdit, EM_LINESCROLL, 0, -(LPARAM)uiScrollLines); else SendMessage(hwndEdit, EM_SCROLL, (WPARAM)(INT)SB_PAGEUP, 0); return 0L; } else if(msg == uMSH_MOUSEEHEEL) { zDelta = (short)wParam; if(zDelta < 0) if(uiScrollLines != WHEEL_PAGESCROLL) SendMessage(hwndEdit, EM_LINESCROLL, 0, uiScrollLines); else SendMessage(hwndEdit, EM_SCROLL, (WPARAM)(INT)SB_PAGEDOWN, 0); else if(uiScrollLines != WHEEL_PAGESCROLL) SendMessage(hwndEdit, EM_LINESCROLL, 0, -(LPARAM)uiScrollLines); else SendMessage(hwndEdit, EM_SCROLL, (WPARAM)(INT)SB_PAGEUP, 0); return 0L; } return(DefWindowProc(hWnd, msg, wParam, lParam)); } } } . . . При обработке сообщений от колеса мыши мы определяем угол, на который было повернуто колесо. Если этот угол положительный, содержимое окна редактора сворачивается вверх, если отрицательный – вниз. Величина свертки определяется в момент инициализации приложения. |