C++ & C# Programming page
 

 

# Úvod
# Tvůrci
# C++
# C#
# Linky





Ukázkový program Watch

V krátkém článku bych chtěl ukázat naprogramování utilitky zvané Watch, neboli Hodinky. Dopředu říkám, že nejde o převratnou aplikaci, ale pouze o malou ukázku práce s Timerem, GDI grafikou, časem a podobně.

Celá aplikace je vystavěna na základním vzoru, který vám na požádání vytvoří Visual Studio 2003. Nehodlám se zde zdržovat popisem, protože na toto téma bylo napsáno již docela velké množství stránek. Moje zaměření je psát návody na konkrétní aplikace a konkrétní funkce pro zkušenější programátory se základní znalostí C++.

No a nyní se již pustíme do práce. Zde je kód na obsluhu dialogu Hodinky:
LRESULT CALLBACK Hodinky(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
     HDC hdc;  // deklarace grafiky
     PAINTSTRUCT ps;
     int xPosNew; // nove pozice mysi
     int yPosNew;
     switch (message) 
    {
     case WM_INITDIALOG:
          SetTimer(hDlg, 2, 1000, NULL); // zapnuti timeru na aktualizaci casu
          return TRUE; 
     case WM_PAINT:
          hdc = BeginPaint(hDlg, &ps); // zahajeni grafiky
          DrawBackground(hDlg, hdc); // vykresleni pozadi
          DrawDisplay(hDlg, hdc, 10, 10);  // vykresleni cisel
          EndPaint(hDlg, &ps);  // ukonceni grafiky
          break; 
     case WM_LBUTTONDOWN: 
          SetTimer(hDlg, 1, 10, NULL); // zahajeni timeru, posouvajici okno pri tazeni mysi
          break; 
     case WM_LBUTTONUP: 
          KillTimer(hDlg, 1); // ukonceni tahani okna
          xPos = -1; // priprava na dalsi tahani 
          yPos = -1; 
          break; 
     case WM_TIMER: 
          if(wParam == 1) // 1 - posun okna, 2 - obnoveni casu
          { 
               POINT Poloha; 
               GetCursorPos(&Poloha); // zjisteni pozice mysi
               xPosNew = Poloha.x; 
               yPosNew = Poloha.y; 
               if( xPos == -1) // promenna je prazdna, musime ji napravit 
               {
                     xPos = xPosNew;  // toto nastaveni probehne jen pri zahajeni tahani okna
                    yPos = yPosNew; 
               }
                    RECT rc; 
                    GetWindowRect(hDlg, &rc); // zjisteni pozice okna
                    SetWindowPos(hDlg, HWND_TOP, rc.left - (xPos - xPosNew), rc.top - (yPos - yPosNew), 0, 0, SWP_NOSIZE);
                    xPos = xPosNew; // aktualizace polohy mysi
                    yPos = yPosNew; 
               } else { 
                    ::InvalidateRect(hDlg, NULL, TRUE); // obnoveni grafiky
                    ::UpdateWindow(hDlg); // ... tato procedura obnoveni se pouziva standartne
                }
                break;
     // pokracovani obsluhy

Myslím si, že tato část je docela jasná. Ti, kteří však přes to chtějí trochu té teorie, mohou číst dál, jinak přeskočte.
Tahání okna:
Globálně deklarované proměnné xPos a yPos uchovávají staré pozice myši, které byly zjištěny u minulého průchozu přes tuto funkci. Nově získané pozice xPosNew a yPosNew jsou použity k rozdílu a vznikne nám vzdálenost, o jakou se posunul kurzor myši. Toho je potom využito ve výpočtu nové pozice okna.
Timery jsou použity k průběžnému posunu okna, když je levé tlačítko puštěno, timer je uvolněn a tahání ukončeno.

Další část kódu se bude týkat grafických funkcí, které jsem použil v předchozím výpisu zdrojáku.

Vykreslení černého pozadí přes okno.
void DrawBackground(HWND hWnd, HDC hdc)
{
     RECT rect; 
     GetClientRect(hWnd, &rect);  // ziskani oblasti okna
     HBRUSH hBrush; 
     hBrush = CreateSolidBrush(RGB(0,0,0)); 
     FillRect(hdc, &rect, hBrush); // vykresleni do okna cernou barvou
     DeleteObject(hBrush); // nezapominejte mazat objekty!
}
Tato funkce snad nepotřebuje vysvětlování...

void DrawDisplay(HWND hWnd, HDC hdc, int X, int Y)

     RECT rect; 
     rect.left = X; // nastaveni zelene oblasti - display 
     rect.right = X + 49; 
     rect.top = Y;
     rect.bottom = Y + 13; 

     HBRUSH hBrush;  // vyplneni zadane oblastni
     hBrush = CreateSolidBrush(RGB(0,130,0)); 
     FillRect(hdc, &rect, hBrush); 
     DeleteObject(hBrush); 

     HBITMAP hBitmap; // vykresleni dvou ':' mezi cislama
     BITMAP bitmap; 
     hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_NUM_dot)); // nacteni bitmapy
     GetObject(hBitmap, sizeof(BITMAP), &bitmap); 
     DrawState(hdc, NULL, NULL, (LPARAM)hBitmap, 0, X+14, Y, 100, 100, DST_BITMAP);  // 1. dvojtecka
     DrawState(hdc, NULL, NULL, (LPARAM)hBitmap, 0, X+32, Y, 100, 100, DST_BITMAP);  // 2. dvojtecka
     DeleteObject(hBitmap); // a zas to uklidnime...

     GetLocalTime(&SysTime); // hodny pane windows, date nam cas? :o)
     // HODINY 
     DrawDigit(hWnd, hdc, X, Y, SysTime.wHour / 10); 
     DrawDigit(hWnd, hdc, X+7, Y, RekniJednotky(SysTime.wHour)); 
     // MINUTY 
     DrawDigit(hWnd, hdc, X+17, Y, SysTime.wMinute / 10); 
     DrawDigit(hWnd, hdc, X+24, Y, RekniJednotky(SysTime.wMinute));
      // VTERINY
      DrawDigit(hWnd, hdc, X+34, Y, SysTime.wSecond / 10); 
     DrawDigit(hWnd, hdc, X+42, Y, RekniJednotky(SysTime.wSecond));
}

Možná by bylo dobré vysvětlit operace na konci, při kterých se předává funkci DrawDigit číslici, kterou má zobrazit. Funkce bere pouze čísla od 0 do 9, a protože hodin, minut i vteřin je více než 9, je třeba získat číslo z místa desítek. Toho je docíleno celočíselným dělením, které probíhá, když int je dělen intem.
Na tomto systému pracuje i funkce RekniJednotky. (vystup = vstup - vstup / 10 * 10; )

Vykreslení čísla: DrawDigit
void DrawDigit(HWND hWnd, HDC hdc, int X, int Y, int cislo)

     HBITMAP hBitmap; 
     switch( cislo )
     { 
          case 1: 
               hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_NUM_1)); 
               break; 
          // no a to parkrat opakovat...
          // Neni to sice estetiky spravne, nebo prilis programatorske ale rychlejsi nez neco vymyslet ;)
     }
 
     BITMAP bitmap;
     GetObject(hBitmap, sizeof(BITMAP), &bitmap); 
     DrawState(hdc, NULL, NULL, (LPARAM)hBitmap, 0, X, Y, 100, 100, DST_BITMAP); // vykresleni obrazku na ziskane pozice X a Y
     DeleteObject(hBitmap); 
}

Tak, to je asi vše z mojí strany. Všechny použité funkce jsou popsány. Doufám, že se aspoň někomu tento návod hodí, přece jen neobsahuje velký rozsah funkcí.

A tady slibovaný zdrojový kód: [ ZDE ]



Správce sekce: Dejvino



14.2 2005

C++: pridano par odkazu na clanky o OpenGL, IRC, POP3 a BMP
14.8 2004

C++: přidán klient pro Internet Relay Chat (IRC)
11.7 2004

C++: opravil jsem zdrojak WebServeru, byla tam navic jedna funkce kterou jsem nepridal a mnoho zacatecniku by si s tim nemuselo vedet rady...
27.6 2004

Vytvořen IRC kanál #c-prog na serveru Quakenet
10.6 2004

C++: přidán program WebServer, stojí za prohlédnutí!
5.6 2004

C++: přidán článek o CheckBoxu
29.5 2004

C++: přidán program WinSock Mail
28.5 2004

C#: přidán program DNStoIP
Vaše IP je 54.92.170.142
Stránka byla načtena za 0.01377 sekund.