IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

API Windows en C

Les timers

Les Timers. ?

Article lu   fois.

L'auteur

Profil ProSite personnel

I. Introduction

Vous avez surement entendu parler des Timers, mais vous ne savez pas trop comment les mettre en œuvre. Cet article va vous monter qu'il n'y a rien de bien compliqué. Un timer est un système qui envoie un signal régulier à une fréquence déterminée, tel le métronome du musicien. Dans l'exemple nous utiliserons deux timers pour faire clignoter deux rectangles dessinés sur une fenêtre. Pourquoi deux, pour bien montrer la façon de les différencier. Ils auront une fréquence différente. Ils pourront être démarrés ou arrêtés depuis le menu de l'application.

Image non disponible

II. Mise en oeuvre

Pour créer un timer, il suffit d'appeler la fonction SetTimer

 
Sélectionnez
1.
    SetTimer(hwnd, ID_TIMER_1, 1000, NULL);
  • Le premier paramètre étant le handle de fenêtre à laquelle il est associé.
  • Le second étant un identificateur (constante numérique) qu'on lui attribue.
  • Le troisième étant le temps en millisecondes de son tempo.
  • Le quatrième que nous n'utiliserons pas est un pointeur sur une fonction de rappel qui est appelée à chaque signal de tempo.

Dans l'exemple nous utiliserons le message qui est envoyé à la fenêtre associée au timer. (Si le timer n'avait pas été associé à une fenêtre, nous aurions été contraints d'utiliser la fonction de rappel.) Ce message est WM_TIMER, il se traite comme les autres messages Windows dans la procédure de fenêtre, comme ceux que nous avons vus dans les autres chapitres. Ce message dans son paramètre wParam contient l'identificateur du timer qui envoie le message, identificateur que l'on avait passé en deuxième paramètre à SetTimer et qui permet donc de savoir de quel timer il s'agit.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        case WM_TIMER:
            if(wParam == ID_TIMER_1)
              {
               /* action */
              }

            if(wParam == ID_TIMER_2)
              {
               /* action */
              }

Quand vous ne voulez plus du Timer, il suffit de le détruire avec la fonction KillTimer avec comme paramètre le handle de fenêtre et l'identificateur du timer.

 
Sélectionnez
1.
KillTimer(hwnd,ID_TIMER_1);

Pour illustrer l'exemple nos timers feront basculer de true à false et vice versa deux variables booléennes nommées T1 et T2. Ces variables permettront ensuite l'affichage ou non des rectangles dans le traitement du message WM_PAINT. Les timers sont démarrés ou arrêtés depuis les commandes du menu.

III. Code complet

III-A. resource.h

 
Sélectionnez
1.
2.
3.
4.
5.
#define IDM_START_1   101
#define IDM_STOP_1    102
#define IDM_START_2   103
#define IDM_STOP_2    104
#define IDM_QUIT      105

III-B. resource.rc

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
#include <windows.h>

#include "resource.h"

LEMENU MENU
BEGIN
  POPUP "Fichier"
    BEGIN
       MENUITEM "Start Timer 1", IDM_START_1
       MENUITEM "Stop Timer 1", IDM_STOP_1
       MENUITEM SEPARATOR
       MENUITEM "Start Timer 2", IDM_START_2
       MENUITEM "Stop Timer 2", IDM_STOP_2
       MENUITEM SEPARATOR
       MENUITEM "Quitter", IDM_QUIT
    END
END

III-C. winmain.c

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
#include <windows.h>
#include "resource.h"

#define ID_TIMER_1  1
#define ID_TIMER_2  2

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

WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
                                                                   int nCmdShow)
{
    HWND hwnd;
    MSG msg;
    WNDCLASS wc;

    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
    wc.lpszMenuName =  "LEMENU";
    wc.lpszClassName = "MaWinClass";

    if(!RegisterClass(&wc)) return FALSE;

    hwnd = CreateWindow("MaWinClass", "Timers", WS_OVERLAPPED | WS_SYSMENU,
                                        CW_USEDEFAULT, CW_USEDEFAULT, 400, 260,
                                                   NULL, NULL, hInstance, NULL);
    if (!hwnd) return FALSE;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;

}
/******************************************************************************/


LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static BOOL T1 = TRUE;
    static BOOL T2 = TRUE;

    switch (uMsg)
    {
        case WM_CREATE:

            return 0;

        case WM_COMMAND:
            switch (LOWORD(wParam))
             {
               case IDM_QUIT :
                   PostMessage(hwnd, WM_CLOSE,0,0);
                   break;

               case IDM_START_1 :
                   SetTimer(hwnd,ID_TIMER_1,1000,NULL);
                   break;

               case IDM_START_2 :
                   SetTimer(hwnd,ID_TIMER_2,500,NULL);
                   break;

               case IDM_STOP_1 :
                   KillTimer(hwnd,ID_TIMER_1);
                   T1 = TRUE;
                   InvalidateRect(hwnd,NULL,TRUE);
                   break;

               case IDM_STOP_2 :
                   KillTimer(hwnd,ID_TIMER_2);
                   T2 = TRUE;
                   InvalidateRect(hwnd,NULL,TRUE);
                   break;
             }

            return 0;

        case WM_TIMER:
            if(wParam == ID_TIMER_1)
              {
               T1 = !T1;
               InvalidateRect(hwnd,NULL,TRUE);
              }

            if(wParam == ID_TIMER_2)
              {
               T2 = !T2;
               InvalidateRect(hwnd,NULL,TRUE);
              }

            return 0;

        case WM_PAINT :
            {
              HBRUSH hbNew, hbrOld;
              PAINTSTRUCT ps;
              HDC hdc = BeginPaint(hwnd, &ps);

              hbNew = CreateSolidBrush(0x000000FF);
              hbrOld = SelectObject(hdc,hbNew);

              if(T1) Rectangle(hdc, 30, 20, 180, 170);

              SelectObject(hdc,hbrOld);
              DeleteObject(hbNew);

              hbNew = CreateSolidBrush(0x00007F00);
              hbrOld = SelectObject(hdc,hbNew);

              if(T2) Rectangle(hdc, 210, 20, 360, 170);

              SelectObject(hdc,hbrOld);
              DeleteObject(hbNew);

              EndPaint(hwnd, &ps);
              return 0;
            }

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

À savoir que si le timer n'est pas associé à une fenêtre, c'est la valeur de retour de SetTimer qui sert d'identificateur à passer à KillTimer pour le détruire. Il est possible de changer la fréquence d'un timer déjà démarré par un second appel à SetTimer. N'hésitez pas à consulter le site de msdn pour plus d'informations sur les timers

À vos PC.

CGi

Retour au sommaire.

Copyright © 2009 CGi. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.