UINT SetTimer(HWND hwnd, UINT nID, UINT wLength, TIMEPROC lpTFunc);

где hwnd – дескриптор окна, nID  -идентификатор устанавливаемого таймера( можно использовать несколько таймеров), wLength – временной интервал в миллисекундах, lpTFunc – функция обработки сообщений таймера. Если TFunc = NULL, то для обработки сообщений таймера будет вызываться оконная функция. Для отключения таймера вызывается функция

BOOL KillTimer(HWND hwnd, UINT nID);

где nID – идентификатор таймера, а hwnd – дескриптор окна, использующего таймер.

Пример работы с таймером. Модифицируем каркас приложения таким образом, чтобы в окно выводились день недели, месяц, число, время и год. Если в главной программе каркаса приложения  после вызова функции                     ShowWindow(hwnd, nWinMode); осуществить  вызов  функции (подпрограммы) установки таймера

SetTimer(hwnd, 1, 1000, NULL);

а после цикла обработки сообщений

KillTimer(hwnd, 1);

то с помощью  следующей оконной функции  в окно будут выводиться  день недели, месяц, число, время и год.

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] = ‘’;

            InvalidateRect(hwnd, NULL, 1);

            break;

    case WM_DESTROY:

            PostQuitMessage(0);                           //сообщение о завершении

            break;

    default:                                                        //обработка остальных сообщений

            return DefWindowProc(hwnd, message, wParam, lParam);

  }

  return 0;

}

            Пример генерации сообщений. Разработаем программу, которая выводит на экран вращающиеся квадраты. Квадраты выводятся в буфер памяти, в котором будет храниться растровое изображение. Совместимость этого буфера с контекстом устройства достигается с помощью вызова функции

           

memdc= CreateCompatibleDC(hdc);

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

           

Сначала оконная функция вычисляет ширину и высоту окна, а затем создает контекст устройства , совместного с контекстом hdc:

            hdc  = GetDC(hdc);

memdc= CreateCompatibleDC(hdc);

            hbit = SelectObject(memdc,hbit);

здесь вызов SelectObject() осуществляет  загрузку объекта. Память, определенная контекстом устройства memdc, очищается (очистка соответствует закраске окна белым цветом) с помощью вызова функции

           

            PatBlt (memdc,0,0,maxX,maxY,PATCOPY);

после чего освобождается устройство hdc и вывод осуществляется в memdc.

            При обработке сообщений таймера оконная функция записывает изображение в буфер и генерирует сообщение WM_PAINT с помощью вызова функции:

            InvalidateRect (hwnd,NULL,1);

Для обработки сообщений WM_PAINT содержимое буфера копируется в область вывода, определенное устройством hdc

hdc = BeginPaint(hwnd,&paintstruct);

BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);

EndPaint (hwnd,&paintstruct);

            Приведем текст программы, выводящей на экран  вращающиеся квадраты.

#include <windows.h>

#include <string.h>

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);

char szwinname[] = "MyWindow";

int maxX,maxY;

int i=0;

POINT pnts[4];

HDC memdc;

HBITMAP hbit;

int WINAPI WinMain(HINSTANCE hthisinst, HINSTANCE hprevinst,

                                    LPSTR lpszargs, int nwinmode)

{

 HWND hwnd;

 MSG msg;

 WNDCLASS wcl;

 HACCEL haccel;

 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, "SQUARE",

        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        HWND_DESKTOP, NULL, hthisinst, NULL);

              haccel=LoadAccelerators(hthisinst,NULL);

        ShowWindow(hwnd,nwinmode);

              UpdateWindow(hwnd);

       SetTimer(hwnd,1,1000,NULL);

              while(GetMessage(&msg,NULL,0,0))

        {

             if(!TranslateAccelerator(hwnd,haccel,&msg))

             {

                   TranslateMessage(&msg);

                   DispatchMessage(&msg);

             }

        }

       KillTimer(hwnd,1);

       return msg.wParam;

}

LRESULT CALLBACK WindowFunc(HWND hwnd,

                                    UINT message,

                                    WPARAM wParam,

                                    LPARAM lParam)

{

HDC hdc;

double phi;

double r= sqrt(2.)*GetSystemMetrics(SM_CXSCREEN)/8;

int j,k, xC, yC;

PAINTSTRUCT paintstruct;

switch(message)

{

       case WM_CREATE:

             maxX= GetSystemMetrics(SM_CXSCREEN);

             maxY= GetSystemMetrics(SM_CYSCREEN);

             hdc = GetDC (hwnd);

             memdc = CreateCompatibleDC(hdc);

             hbit =  CreateCompatibleBitmap(hdc,maxX,maxY);

             SelectObject(memdc,hbit);

             PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

             ReleaseDC(hwnd,hdc);

             break;

      case WM_TIMER:

             PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

             phi=i*(2*3.14159)/32; i=(i+1)%32;

         for (j=0;j<4;j++)

         for (k=0;k<4;k++)

         {

             xC=k*maxX/4+maxX/8; yC=j*maxY/4+ maxY/8;

                   pnts[0].x= xC + r*cos(phi);

                   pnts[0].y= yC + r*sin(phi);

                   pnts[1].x= xC — r*sin(phi);

                   pnts[1].y= yC + r*cos(phi);

                   pnts[2].x= xC — r*cos(phi);

                   pnts[2].y= yC — r*sin(phi);

                   pnts[3].x= xC + r*sin(phi);

                   pnts[3].y= yC — r*cos(phi);

         Polygon(memdc,pnts,4);

      }

         InvalidateRect(hwnd,NULL,1);

      break;

       case WM_PAINT:

             hdc = BeginPaint(hwnd,&paintstruct);

             BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);

             EndPaint(hwnd,&paintstruct);

             break;

       case WM_DESTROY:

             DeleteDC(memdc);

             PostQuitMessage(0);

             break;

       default:

             return DefWindowProc(hwnd,message,wParam,lParam);

}

return 0;

}

            Сначала на экран будут выведено 16 примыкающих друг к другу квадратов. Через каждую секунду изображение будет обновляться.  На рис. 2.12 приведено изображение, выведенное через несколько секунд.

Рис. 2.12. Вращающиеся квадраты

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

            Тем не менее, в большинстве случаев целесообразно записывать изображение в буфер, содержимое которого будет выводиться на экран при получении сообщения WM_PAINT. Это связано с тем, что сообщение WM_PAINT будет приходить во всех случаях, когда окно или его часть закрывается  окном другого приложения, а также при изменении размеров окна.