Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Практикум программирования на С++ под Windows #11


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

Практикум программирования на C++ под Windows
comp.soft.prog.cppwin
Выпуск #11
2001-01-15

*** СОБЫТИЯ ОТ ВНЕШНИХ УСТРОЙСТВ ***********************************

Устройства ввода - клавиатура, мышь - служат источником внешних событий, воспринимаемых системой. Какие-то из этих событий относятся и к нашей программе. На каждое событие системой создается сообщение (message, структура данных, описывающая событие), и помещается в очередь событий (message queue) приложения. Сообщения забираются из очереди по одному - это происходит в основном цикле обработки сообщений. После выборки очередного сообщения из очереди (GetMessage) определяется окно, к которому направлено это сообщение (DispatchMessage), и вызывается оконная процедура окна (напр., MainWndProc).

Мышь

Любые действия с мышью, происходящие над нашим окном, приведут к появлению набора сообщений со следующими именами:

  WM_MOUSEMOVE    Мышь сдвинулась
  WM_LBUTTONDOWN  Нажали левую кнопку мыши
  WM_LBUTTONUP    Отпустили левую кнопку мыши
Для последних двух сообщений есть версия для правой кнопки (WM_R...) и для средней кнопки (WM_M..., используется крайне редко). При обработке этих сообщений нас, как правило, интересует точка, в которой находится мышь.

  case WM_MOUSEMOVE: //Действия при движении мыши
    int x = LOWORD(lParam); //Координаты мыши в системе координат окна
    int y = HIWORD(lParam);
    if (wParam & MK_LBUTTON){ //Мышь движется с нажатой левой кнопкой
      ...
    }
    break;

Но если мы хотим отрисовать что-либо в обработчике мыши - даже просто поставить точку, - придется откуда-то брать экран - а это уже отрисовка по необходимости.

При работе с мышью часто используется прием "двойное нажатие" (double click). При этом последовательно выполняется два нажатия кнопки мыши с коротким интервалом между нажатиями. Это приводит к появлению сообщений (для левой кнопки):

  WM_LBUTTONDOWN   //Сначала происходит обычное нажатие
  WM_LBUTTONUP
  WM_LBUTTONDBLCLK //Второе нажатие опознается как двойное
  WM_LBUTTONUP

Текущие координаты мыши можно получить в любой момент - функцией GetCursorPos.

Клавиши клавиатуры

Если наше окно активно, оно принимает сообщения о нажатиях клавиш:

  WM_KEYDOWN  Нажата клавиша либо автоповтор
  WM_KEYUP    Клавиша отпущена
Важнейший параметр здесь - сама клавиша - это параметр wParam. Его можно сравнивать с константами VK_xxx (см. winuser.h):

  case WM_KEYDOWN:
    switch (wParam){
      case VK_UP:     ... break; //Обработка клавиши стрелка вверх
      case VK_DOWN:   ... break; // стрелка вниз
      case VK_ESCAPE: ... break; // Esc
    }
    break;

При обработке сообщений клавиатуры и мыши бывает важно знать состояние клавиш-регистров (Ctrl, Shift, Alt). В любом обработчике его можно получить вызовом:
  BOOL bShift = GetKeyState(VK_SHIFT) & 0x8000;
  BOOL bCtrl  = GetKeyState(VK_CONTROL) & 0x8000;

Нажатия алфавитно-цифровых клавиш кроме сообщений WM_KEYDOWN порождают сообщения WM_CHAR. В случае, когда нас интересуют печатаемые символы (например, в текстовом редакторе) мы можем обрабатывать их отдельно.

Если клавиша нажата в течение долгого времени, то система сама через равные промежутки времени генерирует сообщения о нажатии - происходит автоповтор. Можно выяснить, является ли клавиша реальным нажатием, или это только действие автоповтора:

  BOOL bAutoRepeat = (lParam & 0x40000000); //Признак автоповтора

Таймер

В том случае, когда в программе должно происходить продолжительное или периодическое действие и при этом не должен теряться контроль над действиями пользователя, мы используем такой ресурс как таймер. Таймер - это метроном, подающий сигналы (сообщения или вызовы заданной функции) через равные промежутки времени.

Как любой другой ресурс, таймер может быть создан и когда-нибудь он должен быть удален:

  UINT uTimer = SetTimer(hWnd, 1, 100, NULL); //Создаем таймер с номером 1
      // для окна hWnd с интервалом 100 мс, посылающий сообщения WM_TIMER
  ... //Теперь 10 раз в секунду окну приходит сообщение WM_TIMER
  KillTimer(hWnd, uTimer); //Уничтожаем таймер

Сообщения, приходящие от таймера, можно обрабатывать в оконной процедуре:

  case WM_TIMER: //Квант продолжительного (периодического) действия
    MessageBeep(-1); //Пищать 10 раз в секунду
    ...
    break;

Упражнения

(Конечно, в каждом упражнении нужно написать программу, выполняющую указанное)

  1. Нажатие на левую кнопку мыши привдит к рисованию точки
  2. Мышь при движении с нажатой левой кнопкой оставляет след
  3. Из точки (0,0) к мыши тянется линия. При движении мыши линия тянется
     за ней. (Используйте режим XOR для рисования и стирания линий)
  4. При нажатой клавише пробел каждые полсекунды раздается звуковой сигнал
  5. Программа завершается через 5 секунд после запуска

*** REAL LIFE ******************************************************

Помимо жизни виртуальной бывают у меня и радости в жизни реальной, физической. Короче говоря, сын родился. В ночь на 14-ое января, вес 4kg, рост 55cm. Звать Сашкой. Any questions?

Есть еще один вопрос, точнее просьба. Если вы хотите мне помочь, если вы москвич, если ХОРОШО соображаете в железе и популярном юзерском софте - будьте добры, напишите пожалуйста на мой e-mail. Нужен специалист - настройщик компьютеров - для небольшой услуги. Заранее спасибо.


*************************************************************************
Количество подписчиков: 7996
Архив Рассылки

Никита Зимин, г.Ижевск
Nikita_Zeemin@mail.ru



http://subscribe.ru/
E-mail: ask@subscribe.ru
Поиск

В избранное