Рассмотрим сообщения, посылаемые родительским окном комбинированным спискам

Для управления списком “combobox” используется набор сообщений, аналогичный набору сообщений для списка “listbox” и редактора текста “edit”. Функция SendMessage, посылающая сообщения списку, возвращает значение, которое зависит от выполняемой функции, или коды ошибок.

  • В файле windows.h определены сообщения, специально предназначенные для работы со списком “combobox”.Символические имена этих сообщений имеют префикс CB_.

 

Полосы прокрутки (класс scrollbar)

В отличие от других дочерних окон управления, посылающих родительскому окну сообщения, полосы прокрутки не посылают сообщения WM_COMMAND. Вместо этого они, также как и полосы прокрутки окна, посылают ему сообщения WM_VSCROLLи WM_HSCROLL.

  • При обработке сообщений полос прокрутки приложению с помощью параметра lParam может различать сообщения полос прокрутки окна и полос прокрутки – элементов управления. Для полос прокрутки окна lParam равен NULL, а для полос – элементов управления он является дескриптором этих полос прокрутки, другими словами дескриптором дочернего окна
  • Значения же старшего и младшего слов параметра wParam для полос прокрутки окна и для полос прокрутки – дочерних окон имеют одинаковый смысл.

Замечание.Полосы прокрутки – элементы управления можно сделать любого размера. Для того чтобы создать элементы управления с теми же стандартными размерами, что и полосы прокрутки окна, можно использовать функцию GetSystemMetrics:

  • вызов GetSystemMetrics(SM_CYHSCROLL) выдает высоту горизонтальной полосы прокрутки,
  • а вызов GetSystemMetrics(SM_CXVSCROLL) – ширину вертикальной полосы прокрутки.

Для полос прокрутки – элементов управления также можно установить диапазон и текущее положение с помощью тех же вызовов функция, что и для полос прокрутки окна:

SetScrollRange(hWndScroll,SB_CTL,iNewMin,iNewMax,bRedraw);

Полосы прокрутки – элементы управления могут обрабатывать сообщения клавиатуры, но только в том случае, если они имеют фокус ввода. Если необходимо, чтобы полоса прокрутки управления получала фокус ввода, когда на полосе прокрутки происходит щелчок мыши, то следует включить идентификатор WS_TABSTOP в параметр стиля дочернего окна управления при вызове функции CreateWindow.

Приведем пример обработки сообщений от полосы прокрутки – дочернего окна управления. Пусть в окне hWnd создано дочернее окно управления hWndScroll – вертикальная линейка прокрутки, и для нее установлены диапазон и текущее положение бегунка:

static int min_sb=1,max_sb=100,pos_sb=20;

SetScrollRange(hWndScroll,SB_CTL,min_sb,max_sb,TRUE);

SetScrollPos(hWndScroll,SB_CTL,pos_sb,TRUE);

Рассмотрим фрагмент оконной функции, демонстрирующий возможную обработку действий пользователя с этой вертикальной линейкой прокрутки:

case WM_VSCROLL:

{

// произведенное действие

int nScrollCode=(int)LOWORD(wParam);

// текущая позиция

short int nPos=(short int)HIWORD(wParam);

// дескриптор полосы просмотра или NULL

HWND hwndScrollBar=(HWND)lParam;

 

int old_pos_sb=pos_sb;

switch(nScrollCode)

{

case SB_PAGEDOWN: pos_sb+=10; break;

case SB_PAGEUP: pos_sb-=10; break;

case SB_LINEDOWN: pos_sb+=1; break;

case SB_LINEUP: pos_sb-=1; break;

case SB_THUMBPOSITION: pos_sb=nPos; break;

case SB_THUMBTRACK: pos_sb=nPos; break;

default: return 0l;

}

if(pos_sb<min_sb) pos_sb=min_sb;

if(pos_sb>max_sb) pos_sb=max_sb;

if(old_pos_sb!=pos_sb)

SetScrollPos(hWndScroll,SB_CTL,pos_sb,TRUE);

}; return 0l;

 

Создание элементов управления визуально

Для добавления визуального диалогового окна используется контекстное меню на папке ресурсов – добавить, диалоговое окно.

Если создали окно, его ID по умолчанию: IDD_DIALOG1

Тогда программное создание окна:

DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, Dialog1);

где hInst – дескриптор приложения, MAKEINTRESOURCE(IDD_DIALOG1) – создание окна на основе визуального представления, hWnd – окно-владелец, Dialog1 – оконная процедура.

 

Тема: Работа с таймерами в Windows

 

Таймер в Windows является устройством, которое периодически извещает приложение о том, что истек заданный интервал времени.

Приложение сообщает системе Windows интервал времени, а затем Windows с помощью таймера периодически посылает приложению сообщения WM_TIMER, сигнализируя об истечении интервала времени.

Возможные случаи применения таймеров в Windows:

· Режим автосохранения –программа сохраняет результаты работы пользователя на диске, когда истекает заданный интервал времени.

· Поддержка обновления информации о состоянии – программа использует таймер для вывода на экран обновляемой в реальном времени, постоянно меняющейся информации, связанной либо с системными ресурсами, либо с процессом выполнения отдельной задачи.

· Завершение демонстрационных версий программ – некоторые демонстрационные версии программ рассчитаны на свое завершение через какое-либо заданное время после запуска. Таймер сигнализирует таким приложениям, когда их время истекает.

· Задание темпа изменения – графические объекты в играх или окна с информацией в обучающих программах могут нуждаться в задании установленного темпа изменения.

Сообщения от таймера

Присоединить таймер к программе можно при помощи вызова функции SetTimer. Одним из параметров этой функции является целое значение, задающее интервал в миллисекундах, по истечении которого Windows периодически посылает программе сообщения WM_TIMER.

Для остановки потока сообщений от таймера приложение должно вызвать функцию KillTimer. Вызов KillTimer очищает очередь сообщений от всех необработанных сообщений WM_TIMER.

Сообщения таймера ставятся в обычную очередь сообщений и обрабатываются как все остальные сообщения. Поэтому, если приложение задает функции SetTimer интервал 1000 миллисекунд, то ему не гарантируется получение сообщения каждую секунду (интервал будет колебаться). Если приложение занято больше чем секунду, то оно вообще не получит ни одного сообщения WM_TIMER в течение этого времени.

Варианты использования таймера

Таймер можно использовать одним из трех способов, в зависимости от параметров функции SetTimer.

Первый способ

При этом способе Windows посылает сообщения WM_TIMER требуемой оконной процедуре приложения. Вызов функции SetTimer в этом случае имеет такой вид:

SetTimer(hWnd, iTimerID, dwTimer, NULL);Параметры функции:

· hWnd – дескриптор того окна, чья оконная процедура будет получать сообщения WM_TIMER.

· iTimerID - идентификатор таймера, целое число, значение которого должно быть отлично от нуля. Можно задавать номера произвольно, начиная с 1.

· dwTimer – это 32-разрядное беззнаковое целое, которое задает интервал в миллисекундах.

· NULL – неиспользуемый в этом способе параметр.

Поток сообщений WM_TIMER можно в любое время остановить (даже во время обработки сообщения WM_TIMER), вызвав функцию:

KillTimer(hWnd, iTimerID);

Вторым параметром здесь является тот же идентификатор таймера, который использовался при вызове функции SetTimer.

Замечание. Приложение должно перед завершением работы уничтожить все активные таймеры.

Когда оконная процедура получает сообщение WM_TIMER, wParam равен значению идентификатора таймера, а lParam равен 0.

Если приложению необходимо несколько таймеров, для каждого из них необходимо использовать свой идентификатор, например:

#define TIMER_SEC 1 #define TIMER_MIN 2 ... SetTimer(hWnd, TIMER_SEC,1000,NULL); SetTimer(hWnd, TIMER_MIN,60000,NULL);

Значение параметра wParam позволяют различать передаваемые в оконную процедуру сообщения WM_TIMER.

Код для обработки сообщения WM_TIMER при нескольких таймерах для одного окна следующий:

case WM_TIMER:{ UINT wTimerID = wParam; switch(wTimerID) { // действия происходят один раз в секунду case TIMER_SEC: . . . break; // действия происходят один раз в минуту case TIMER_MIN: . . . break; }}; return 0;

Замечание. Для того чтобы установить новое время срабатывания для существующего таймера, следует уничтожить таймер функций KillTimer и снова установить его функцией SetTimer.

Второй способ

С помощью второго способа Windows посылает сообщения другой функции этого же приложения.

Функция, которая будет получать эти таймерные сообщения, называется функцией обратного вызова (call-back). Эта функция приложения, которую вызывает непосредственно Windows. Приложение сообщает Windows адрес этой функции, а позже Windows вызывает ее.

Как и оконная процедура, функция обратного вызова должна определяться как CALLBACK, поскольку Windows вызывает ее вне кодового пространства программы. Параметры функции обратного вызова и ее возвращаемое значение зависят от назначения функции обратного вызова.

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

Если для таймерной функции обратного вызова выбрано имя TimerProc, тогда эта функция должна иметь следующее определение (она будет обрабатывать только сообщения WM_TIMER):

void CALLBACK TimerProc(HWND hWnd,UINT iMsg,UINT iTimerID,DWORD dwTime){ // обработка сообщений WM_TIMER . . .}Параметры функции:

· hWnd – дескриптор окна, задаваемый при вызове функции SetTimer.

· iMsg всегда будет равен WM_TIMER, т.к. Windows будет посылать функции TimerProc только сообщения WM_TIMER.

· iTimerID – это идентификатор таймера.

· dwTime – системное время.

При использовании функции обратного вызова для обработки сообщений WM_TIMER (второй способ использования таймера), четвертый параметр функции SetTimer заменяется адресом функции обратного вызова:

SetTimer(hWnd,1,1000,(TIMERPROC)TimerProc);

Третий способ

Третий способ установки таймера напоминает второй, за исключением того, что параметр hWnd функции SetTimer устанавливается NULL, а второй параметр (обычно идентификатор таймера) игнорируется. Функция возвращает ID таймера (возвращаемое функцией значение будет равно NULL, если таймер недоступен):

UINT iTimerID=SetTimer(NULL,0,1000,(TIMERPROC)TimerProc);

Первый параметр функции KillTimer при удалении установленного таймера также должен быть равен NULL. Идентификатор таймера должен быть равен значению, возвращаемому функцией SetTimer:

KillTimer(NULL, iTimerID);

Такой метод установки таймера используется редко. Он удобен, если в программе в разное время делается много вызовов функции SetTimer, и при этом не запоминаются те таймерные идентификаторы, которые уже использовались.


Задания

0. Создать приложение, помогающее определить, как одеться в зависимости от погоды:

1. Создать оконное приложение, которое спрашивает имя и выводит текст: «Введенное_имя? Не, не знаю такого»

2. Создать оконное приложение-калькулятор для операций +, -

3. Создать оконное приложение «убегающая кнопка», в котором при перемещении мышки в направлении кнопки, кнопка перемещается (либо от указателя мыши, либо в случайном направлении).

4. Добавить в приложение-калькулятор (задача 2) таймер, который через 2 минут после запуска сообщает «Я устал» и закрывает программу

5. Создать приложение, осуществляющее пересчет валюты в рубли по установленному в константах курсу. Элементы управления: поле для ввода суммы; список для выбора валюты (доллары, евро, гривны); флажок для указания: в/из – в рубли или из рублей нужно осуществить перевод. При закрытии запросить подтверждение на выход.

6. Сделать приложение, в котором вводится набор значений, которые отображаются в список. По нажатию на кнопку выводится среднее значение, минимальное и максимальное. Добавить кнопку удалить, которая удаляет из списка выбранное значение. Пример формы (без кнопки удалить):

7. Написать программу, которая будет позволять осуществлять бронь места в самолете:

8. Написать программу, которая позволяла бы осуществлять расчет стоимости компьютера с выбором: объема оперативной памяти (поле для ввода); видеокартой (выпадающий список); звуковой картой (список); оптической мышкой и клавиатурой (2 группы radio); роутером (checkbox).

9. Разработать программу, которая будет играть в игру крестики-нолики с размером поля 3х3, 4х4. Выбор варианта игры (3х3 или 4х4) осуществить с помощью выпадающего списка, а выбор начального символа – с помощью радио-группы. Добавить меню, в котором предусмотреть 2 пункта: выход и начало новой игры.

10. Разработать программу, которая загадывает число от 0 до 100, а затем производит диалоговое общение с пользователем с просьбой ввести число и указывает, больше, меньше или равно введенное число относительно загаданного. Например, загадано компьютером число 35. Если пользователь вводит 20, компьютер сообщает «больше», и т.д. пока человек не отгадает загаданное число. Предусмотреть установку с помощью меню и вспомогательных диалоговых окон диапазоны чисел и количество попыток для отгадывания