![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Генерация сообщений таймера
Последним сообщением, которое мы обсудим в этой главе, будет 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.
|