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


API Windows en C

Les timers.

Par CGi

Le 22 mai 2009




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é 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.


Mise en oeuvre :

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

    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) que l'on lui attribut. 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é au timer du timer. (Si le timer n'avait pas été associé à une fenêtre, nous aurions été contrains 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 nous avons vu 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.

        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.

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.

Code complet :

resource.h :


#define IDM_START_1   101
#define IDM_STOP_1    102
#define IDM_START_2   103
#define IDM_STOP_2    104
#define IDM_QUIT      105


resource.rc :

#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

winmain.c :

#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);
    }
}

A 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ésiter pas à consulter le site de msdn pour plus d'informations sur les timers


A vos PC.

CGi



Sommaire



C/C++
  Les pointeurs du C/C++.   Les listes chaînées.             Liste simple.             Liste triée.             Liste double.   Les arbres.   Les tas.   Le C orienté objets ?

  1 - La fenêtre principale.   2 - Contrôles et messages.   3 - Les commandes.   4 - Dialogue std.   5 - Contexte de périph.   6 - Dessiner.   7 - Les ressources.   8 - Dialogue perso.   9 - Dialogue comm.   10 - Les accélérateurs.

Assembleur
  Assembleur sous Visual C++.

C++ BUILDER
  Trucs et astuces.   Composant.   TRichEdit.   TDrawGrid.   Application MDI.   TThread.   wxWidgets.   Style Win XP.

  Première application.   Construire un menu.   Dessiner.   Sisers, Timers...   Dialogues standards.   Dialogues perso.

DotNet
  Composant C# Builder.   Contrôle WinForm.   Application MDI.

Java
  Applet java.





Copyright 2002-2020 CGi - Tous droits réservés CGi. Toutes reproduction, utilisation ou diffusion de ce document par quelque moyen que ce soit autre que pour un usage personnel doit faire l'objet d'une autorisation écrite de la part de l'auteur, propriétaire des droits intellectuels.
Les codes sources de ce document sont fournis en l'état. L'utilisateur les utilise à ses risques et périls, sans garantie d'aucune sorte de la part de l'auteur. L'auteur n'est responsable d'aucun dommage subi par l'utilisateur pouvant résulter de l'utilisation ou de la distribution des codes sources de ce document.
De la même façon, l'auteur n'est en aucun cas responsable d'une quelconque perte de revenus ou de profits, ou de données, ou de tous dommages directs ou indirects, susceptibles de survenir du fait de l'utilisation des codes sources de ce document, quand bien même l'auteur aurait été averti de la possibilité de tels dommages. L'utilisation des codes sources de ce document vaut acceptation par l'utilisateur des termes de la licence ci-dessus.