- •Московская финансово-промышленная академия
- •Содержание
- •Глава 1. Модель программирования приложений
- •1.1. Потребительские свойства Windows
- •1.2. Процессы в Windows и потоковая многозадачность
- •1.3. Динамические библиотеки
- •1.4. Программное обеспечение для создания Win-приложений
- •Спецификация префиксов венгерской нотации
- •Глава 2. Обзор возможностей программирования
- •2.1. Общий взгляд на программирование в Windows
- •2.2. Взаимодействие Windows с программой
- •2.3. Win32 api: прикладной интерфейс для Windows
- •2.4. Компоненты окна
- •2.5. Основы приложений Windows
- •2.6. Каркас приложения Windows
- •2.7. Определение класса окна
- •Значения параметра lpszName
- •Наиболее употребляемые макросы для встроенных курсоров
- •Типы системных кистей
- •2.8. Создание окна
- •Наиболее распространенные стили
- •Параметры способа отображения nHow
- •2.9. Цикл обработки сообщений
- •2.10. Оконная функция
- •Типы префиксов
- •Глава 3. Обработка сообщений Windows
- •3.1. Что такое сообщения?
- •3.2. Обработка нажатая клавиш
- •Битовая карта lParam
- •3.3. Обработка сообщений wm_paint
- •3.4. Обработка сообщений «мыши»
- •3.5. Генерация сообщения wm_paint
- •3.6. Генерация сообщений таймера
- •Глава 4. Ресурсы и меню
- •4.1. Окна сообщений MessageBox
- •Значения функции MessageBox
- •Значения wMbType
- •4.2. Представляем меню
- •4.3. Использование ресурсов
- •Параметры menu
- •Параметры элементов меню
- •4.4. Включение меню в программу. Обработка команд
- •4.5. Включение акселераторов сменю
- •4.6. Загрузка таблицы акселераторов
- •Глава 5. Создание диалогов
- •5.1. Взаимодействие Win-диалогов с пользователем
- •5.2. Модальные диалоги: обработка сообщений
- •5.3. Активизация и создание простейшего диалога
- •5.4. Определение ресурсов диалога
- •Стили диалога
- •5.5. Оконная функция диалога
- •5.6. Основы работы со списками
- •Типы сообщений
- •5.7. Инициализация списка и выбор элементов
- •5.8. Окно ввода
- •5.9. Использование немодального диалога
- •Глава 6. Графические образы, иконки и курсоры
- •6.1. Иконка и курсор
- •6.2. Определение малой иконки
- •6.3. Работа с растровыми изображениями
- •Значения параметра dwRaster
- •6.4. Работа с несколькими растровыми изображениями
- •Глава 7. Более подробно об элементах управления
- •7.1. Работа с контрольными переключателями
- •7.2. Статические элементы
- •7.3. Работа с селекторными кнопками
- •7.4. Линейки прокрутки
3.6. Генерация сообщений таймера
Последним сообщением, которое мы обсудим в этой главе, будет WM_TIMER. В Windows-программах можно устанавливать таймер, который с заданной периодичностью будет посылать программе сообщение WM_TIMER. Использование таймера является хорошим способом время от времени «будить» Вашу программу. Это может быть полезным в том случае, если Ваша программа выполняется как фоновое приложение.
Основные функции. Для установки таймера нужно использовать функцию API SetTimer():
UINT SetTimer(HWND hwnd, UINT nID, UINT wLength,
TIMEPROC lpTFunc);
Параметр hwnd является дескриптором окна, которое собирается использовать таймер. Параметр nID – идентификатор устанавливаемого таймера (одновременно могут использоваться несколько таймеров). Параметр wLength задает временной интервал для таймера в миллисекундах. Функция, указатель на которую задается параметром lpTFunc, является процедурой, определенной в программе и вызываемой при обработке прерываний таймера. Эта функция должна быть определена как VOID CALLBACK и имеет такие же параметры, как и оконная функция. Однако, если значение lpTFunc равно NULL, как это чаще всего и бывает, для обработки сообщений таймера будет вызываться оконная функция. В этом случае каждый раз по истечении заданного временного интервала в очередь сообщений программы будет помещаться сообщение WM_TIMER, а оконная функция программы должна будет обрабатывать его так же, как и остальные сообщения. Такой подход используется в следующем примере. Функция SetTimer() в случае успешного завершения возвращает значение nID, в противном случае возвращается 0.
Будучи установлен, таймер будет посылать сообщения до тех пор, пока программа не завершится или не вызовет функцию API KillTimer():
BOOL KillTimer(HWND hwnd, UINT nID);
Здесь hwnd является дескриптором окна, использующего таймер, а nID – идентификатором этого таймера.
Каждый раз при поступлении сообщения WM_TIMER параметр wParam содержит идентификатор таймера, a lParam – адрес функции таймера (если он был задан при установке таймера). В следующем примере значение IParam будет NULL.
Дополнительные функции. Для программирования с использованием таймера нам потребуется специальная структура типа tm, предоставляемая операционной системой
struct tm *newtime,
адрес которой помещается в указатель newtime.
Кроме того, нужна переменная t типа time_t:
time_t t.
Функция time(NULL)позволяет получить новое время, которое имеет тип time_t:
t = time(NULL).
Новое время можно поместить в структуру типа tm (в соответствующее её поле), адрес которой помещен в указатель newtime, с помощью функции localtime :
newtime=localtime(&t).
Единственным аргументом функции localtime является адрес переменной t типа time_t.
Из структуры типа tm время можно поместить в буфер вывода, используя функции strcpy и asctime:
strcpy(str,asctime(newtime)).
Следует учесть, что в конце этой информации Windows поместит символы «возврат каретки» \r и «новая строка» \n . Эти символы желательно удалить, поставив в конце информации обычный символ «конец строки»:
str[strlen(str)-1] = '\0' .
Пример 3-5. Приведенная ниже программа использует таймер для создания часов. Для получения текущей даты и времени она вызывает стандартные функции «C» или «C++». Каждый раз при получении сообщения таймера – примерно раз в секунду – изображение, отображающее время, обновляется. Таким образом, время указывается с точностью до одной секунды.
// Программа-часы
#include <Windows.h>
#include <String.h>
#include <Stdio.h>
#include <Time.h>
LRESULT CALLBACK WindowFunc(HWND, UINT,
WPARAM, LPARAM);
char szWinName[]="МоеОкно"; // Имя класса окна
char str[80]=""; // Буфер для строки вывода
int X=1, Y=1; // Координаты строки на экране
int WINAPI WinMain(HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWinMode)
{
HWND hwnd;
MSG msg;
WNDCLASS wcl; // Определить класс окна
wcl.hInstance=hThisInst; // Дескриптор приложения
wcl.lpszClassName=szWinName; // Имя класса окна
wcl.lpfnWndProc=WindowFunc; // Функция окна
wcl.style=0; // Стиль по умолчанию
wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION);// Иконка
wcl.hCursor=LoadCursor(NULL,IDC_ARROW); // Курсор
wcl.lpszMenuName=NULL; // Без меню
wcl.cbClsExtra=0; // Без дополнительной информации
wcl.cbWndExtra=0;
wcl.hbrBackground=
(HBRUSH)GetStockObject(WHITE_BRUSH); //Белый фон
if(!RegisterClass(&wcl)) // Регистрируем класс окна
return 0;
hwnd=CreateWindow(szWinName, // Создать окно
"Программа-часы",
WS_OVERLAPPEDWINDOW, // Стиль окна
CW_USEDEFAULT, // x-координата
CW_USEDEFAULT, // y-координата
CW_USEDEFAULT, // Ширина
CW_USEDEFAULT, // Высота
HWND_DESKTOP, // Нет родител. окна
NULL, // Нет меню
hThisInst,// Дескриптор приложения
NULL); // Нет дополнит. аргументов
ShowWindow (hwnd, nWinMode); // Показать окно
SetTimer(hwnd,1,1000,NULL); // Устан. таймер 1 сек.
UpdateWindow(hwnd); // Перерисовать содержимое
while(GetMessage(&msg,NULL,0,0)) // Запустить цикл
{ // обработки сообщений
TranslateMessage(&msg); //Разреш. исп-е клавиатуры
DispatchMessage (&msg); // Вернуть управл. Windows
}
KillTimer(hwnd,1); // Освободить таймер
return msg.wParam;
}
// Следующая функция вызывается операционной
// системой Windows и получает в качестве
// параметров сообщения из очереди сообщений
// данного приложения
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT paintstruct;
struct tm *newtime;
time_t t;
switch(message)
{
case WM_PAINT: // Перерисовка рабочей области
hdc=BeginPaint(hwnd,&paintstruct);// Получить DC
TextOut(hdc,X,Y,str,strlen(str));//Вывести буфер
EndPaint(hwnd, &paintstruct); // Освободить DC
break;
case WM_TIMER: // Очередной временной интервал
t = time(NULL); // Получить новое время
newtime=localtime(&t); // Новое время - в буфер
strcpy(str,asctime(newtime));
str[strlen(str)-1] = '\0'; // Удалить \r\n
InvalidateRect(hwnd,NULL,1); // Перерисов. экран
break;
case WM_DESTROY: // Завершение программы
PostQuitMessage(0);
break;
default:
// Все сообщения, не обрабатываемые в
// данной функции, направляются на обработку
// по умолчанию
return DefWindowProc(hwnd,message,
wParam,lParam);
}
return 0;
}
Пример вывода этой программы показан на рис. 3.3.