P020 - Proste okienko w MS-Windows
Programy uruchomiono w środowisku Bloodshed Dev-C++ 4.9.9.2
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//--------------------------
// Koło informatyczne 2006/7
//--------------------------
// Program: P020-01
//--------------------------

#include <windows.h>

// Tutaj umieszczamy nazwę klasy, wg której powstanie nasze okno
// Jest to zmienna globalna.
//--------------------------------------------------------------

char ClassName[ ] = "SimpleWinClass";

// Procedura obsługująca wiadomości dla okna, wywoływana przez
// MS-Windows przy okazji różnych zdarzeń, które należy obsłużyć
//--------------------------------------------------------------

LRESULT CALLBACK WndProc(HWND h, UINT uMsg , WPARAM wP, LPARAM lP)
{
  if(uMsg == WM_DESTROY)
  {
    PostQuitMessage(0); return 0;
  }
  else return DefWindowProc(h,uMsg,wP,lP);
}
        

// W Windows główna funkcja, od której uruchamiany jest program,
// nazywa się WinMain zamiast main.
//--------------------------------------------------------------

int WINAPI WinMain (HINSTANCE hinst,
                    HINSTANCE hprevinst,
                    LPSTR     cmdLine,
                    int       cmdShow)

{
  WNDCLASSEX wc;  // struktura klasy okna
  MSG        ms;  // przechowuje wiadomości aplikacji
  HWND       h;   // Uchwyt naszego okna


// Ustawiamy kolejne pola struktury klasy okna

  wc.cbSize        = sizeof(WNDCLASSEX);
  wc.style         = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc   = WndProc;
  wc.cbClsExtra    = wc.cbWndExtra = 0;
  wc.hInstance     = hinst;
  wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = ClassName;
  wc.hIcon         = wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);

// Rejestrujemy klasę okna w Windows. Jeśli się to nie uda, kończymy program

  if(!RegisterClassEx(&wc)) return 0;

// Gdy klasa jest zarejestrowana, tworzymy na jej podstawie okno

  h = CreateWindowEx(0,                      // dodatkowe style okna, 0 oznacza ich brak
                     ClassName,              // adres tablicy char z nazwą klasy
                     "Nasze pierwsze okno",  // adres łańcucha z napisem tytułowym okna
                     WS_OVERLAPPEDWINDOW,    // styl okna
                     CW_USEDEFAULT,          // współrzędna X lewego górnego narożnika okna
                     CW_USEDEFAULT,          // współrzędna Y lewego górnego narożnika okna
                     300,                    // szerokość okna w pikselach, również może być CW_USEDEFAULT
                     200,                    // wysokość okna w pikselach, również może być CW_USEDEFAULT
                     0,                      // uchwyt nadrzędnego okna, jeśli istnieje
                     0,                      // uchwyt menu, jeśli istnieje
                     hinst,                  // uchwyt programu, który korzysta z okna
                     0                       // adres dodatkowych danych
                     );

// Utworzone okno wyświetlamy na ekranie

  ShowWindow(h, cmdShow);
    
// Uaktualniamy treść okna

  UpdateWindow(h);
    
// Rozpoczynamy pętlę obsługi wiadomości napływających do naszego okna.

  while(GetMessage(&ms, NULL, 0, 0))
  {
    TranslateMessage(&ms);
    DispatchMessage(&ms);
  }

// zwracamy wartość umieszczoną w polu wParam ostatniej wiadomości

  return ms.wParam;
}
Efekt uruchomienia programu
obrazek

Podane tutaj informacje pochodzą z bazy wiedzy dla systemu Windows stworzonej przez firmę Microsoft i udostępnionej darmowo w Internecie pod tym adresem:

http://msdn.microsoft.com

       Wyjaśnienie

Powyższy program wyjaśnia powód nie rozpoczynania nauki programowania od systemu Windows. Jednakże warto dokładnie przeczytać podane tutaj informacje, ponieważ opisane funkcje i struktury występują praktycznie w każdym programie okienkowym. Z drugiej strony nie musimy się wszystkiego dokładnie uczyć na pamięć. Wystarczy, iż wiemy, gdzie znaleźć odpowiednie wyjaśnienia i do czego służą opisane funkcje i struktury danych.

Zadaniem naszego programu jest utworzenie jednego prostego, pustego okna aplikacji, które będzie posiadało typowe zachowania okienkowe (na przykład możliwość przesuwania po ekranie, skalowania, sprowadzania na pasek zadań, itp.). W tym celu musimy wykonać następujące kroki:

  1. Zainicjować pola specjalnej struktury danych, zwanej strukturą klasy okna.
  2. Wykorzystać strukturę klasy okna do rejestracji tej klasy w systemie MS-Windows. Gdy klasa zostanie zarejestrowana, struktura klasy okna nie będzie już potrzebna i można ją wykorzystać do rejestracji innej klasy okna. Klasa okna definiuje parametry okienka - jego wygląd, kolory, menu itp.
  3. Po rejestracji należy utworzyć okno na podstawie klasy.
  4. Utworzone okno należy wyświetlić na ekranie i odświeżyć.
  5. Następnie w pętli należy sprawdzać wiadomości nadchodzące od Windows i wysyłać je do specjalnej procedury, zwanej procedurą okna, w której zostaną obsłużone. Pętla jest wykonywana dotąd, aż skończą się wiadomości dla naszego programu - wszystkie utworzone przezeń okna zostaną zamknięte. Wtedy kończymy funkcję WinMain.

Struktura klasy okna

Do rejestracji klasy okna wykorzystywana jest struktura typu WNDCLASSEX, która posiada następującą deklarację:

typedef struct
{
  UINT      cbSize;
  UINT      style;
  WNDPROC   lpfnWndProc;
  int       cbClsExtra;
  int       cbWndExtra;
  HINSTANCE hInstance;
  HICON     hIcon;
  HCURSOR   hCursor;
  HBRUSH    hbrBackground;
  LPCTSTR   lpszMenuName;
  LPCTSTR   lpszClassName;
  HICON     hIconSm;
} WNDCLASSEX, *PWNDCLASSEX;

W definicji pól tej struktury występuje wiele nowych typów danych, zdefiniowanych specjalnie na potrzeby systemu MS-Windows.

UINT    - 32-bitowa liczba całkowita bez znaku, odpowiednik C++ to unsigned int.
WNDPROC  - adres procedury okna, czyli procedury obsługującej napływające dla niego wiadomości.
HINSTANCE  - uchwyt programu
HICON  - uchwyt ikony
HCURSOR  - uchwyt kursora
HBRUSH  - uchwyt pędzla.
LPCTSTR  - długi wskaźnik tablicy znaków zakończonych kodem 0

Poszczególne pola struktury WNDCLASSEX posiadają następujące przeznaczenia:

cbSize - określa rozmiar w bajtach struktury WNDCLASSEX. Rozmiar ten otrzymamy z sizeof(WNDCLASSEX).
style - określa style okna, które mogą być dowolną kombinacją (za pomocą operatora | ) stałych:
CS_BYTEALIGNCLIENT -

Wyrównuje obszar roboczy okna do granicy bajtu w kierunku x. Styl ten wpływa na szerokość okna oraz jego położenie poziome na ekranie monitora.

CS_BYTEALIGNWINDOW -

Wyrównuje okno do granicy bajtu w kierunku x. Styl ten wpływa na szerokość okna oraz jego położenie poziome na ekranie monitora.

CS_CLASSDC -

Przydziela jeden wspólny kontekst graficzny dla wszystkich okien w tej klasie. Ponieważ klasy okien są zależne od procesów, to możliwe jest utworzenie okien tej samej klasy przez wiele wątków danej aplikacji. Możliwe również jest jednoczesna próba użycia w wątkach tego samego kontekstu graficznego. Gdy tak się stanie, system zezwoli tylko jednemu wątkowi na ukończenie jego operacji graficznych.

CS_DBLCLKS -

Wysyła wiadomość o podwójnym kliknięciu myszką do procedury okna, gdy kursor myszki znajduje się w obszarze okna zbudowanego na podstawie tej klasy.

CS_DROPSHADOW -

W Windows XP: umożliwia rzucanie cienia przez okno. Efekt ten jest stosowany zwykle przez małe okna, które na krótko pojawiają się na ekranie - np. okna podpowiedzi lub menu, aby stworzyć wrażenie trójwymiarowości.

CS_GLOBALCLASS -

Określa, iż dana klasa okien jest globalną klasą aplikacji.

CS_HREDRAW -

Przerysowuje całe okno przy zmianie szerokości obszaru roboczego użytkownika.

CS_NOCLOSE -

Wyłącza przycisk zamykania okna na pasku tytułowym.

CS_OWNDC -

Przydziela oddzielny kontekst graficzny dla każdego okna w tej klasie.

CS_PARENTDC -

Ustawia prostokąt obcinania okna potomnego do prostokąta obcinania okna nadrzędnego. Dzięki temu okno potomne może rysować po swoim oknie nadrzędnym.

CS_SAVEBITS -

Zachowuje w postaci bitmapy część obrazu ekranu zakrytego przez okno tej klasy. Gdy okno zostanie usunięte, system wykorzysta zapamiętany obraz do przywrócenia ekranu.

Styl ten jest użyteczny dla małych okienek (menu, okna dialogowe, itp.), które są wyświetlane przez krótki okres czasu, a następnie usuwane. Styl ten zwiększa czas wymagany na wyświetlenie okna, ponieważ system musi najpierw przydzielić pamięć na obrazek.

CS_VREDRAW -

Przerysowuje całe okno przy zmianie wysokości obszaru roboczego.

lpfnWndProc -

adres procedury okna, która przetwarza i obsługuje wiadomości systemowe napływające dla okna utworzonego na podstawie tej klasy.

cbClsExtra -

określa liczbę bajtów, którą należy dodatkowo zarezerwować za strukturą klasy okna. System inicjuje te bajty na zero.

cbWndExtra -

określa liczbę dodatkowych bajtów, które należy zarezerwować za egzemplarzem okna. System inicjuje te bajty na zero. 

hInstance -

uchwyt programu zawierającego procedurę okna dla tej klasy.

hIcon -

uchwyt ikony klasy. Musi to być uchwyt do zasobu ikon. Jeśli będzie zawierać NULL, to system udostępni standardową ikonę.

hCursor -

uchwyt kursora klasy. Musi to być uchwyt do zasobu kursora. Jeśli będzie zawierać NULL, to aplikacja musi osobiście ustawić kształt kursora w momencie, gdy kursor myszki pojawia się ponad okienkiem aplikacji.

hbrBackground -

uchwyt pędzla tła klasy. Pole to może być uchwytem do fizycznego pędzla stosowanego do malowania tła lub może być wartością koloru. Stałe koloru wymienione są poniżej. Jeśli stosujemy stałą koloru, to należy dokonać rzutowania typu (HBRUSH):
COLOR_ACTIVEBORDER - kolor aktywnej ramki okna
COLOR_ACTIVECAPTION - kolor aktywnego tytułu okna
COLOR_APPWORKSPACE - kolor obszaru roboczego aplikacji
COLOR_BACKGROUND - kolor tła
COLOR_BTNFACE - kolor przycisków
COLOR_BTNSHADOW - kolor cienia przycisków
COLOR_BTNTEXT - kolor tekstu przycisków
COLOR_CAPTIONTEXT - kolor tekstu tytułu okna
COLOR_GRAYTEXT - kolor zablokowanego tekstu
COLOR_HIGHLIGHT - kolor wyróżnienia
COLOR_HIGHLIGHTTEXT - kolor wyróżnionego tekstu
COLOR_INACTIVEBORDER - kolor nieaktywnej ramki
COLOR_INACTIVECAPTION - kolor nieaktywnego tytułu
COLOR_MENU - kolor menu
COLOR_MENUTEXT - kolor tekstu menu
COLOR_SCROLLBAR - kolor paska przewijania
COLOR_WINDOW - kolor okna
COLOR_WINDOWFRAME - kolor ramki okna

Jeśli pole to zawiera wartość NULL, to aplikacja musi samodzielnie zamalowywać tło okna przy każdym żądaniu malowania obszaru roboczego.

lpszMenuName -

wskaźnik nazwy menu klasy. Jeśli pole zawiera NULL, to okna zbudowane na podstawie tej klasy nie będą posiadały żadnego menu.

lpszClassName -

wskaźnik nazwy klasy.

hIconSm -

wskaźnik małej ikony związanej z klasą okna. Jeśli pole zawiera NULL, system przeszuka zasoby ikon określone przez pole hIcon i tam dobierze odpowiednią ikonę.

Rejestracja nowej klasy okna

Gdy struktura WNDCLASSEX zostanie wypełniona odpowiednimi danymi, używamy jej do rejestracji klasy za pomocą funkcji:

ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx);
lpwcx - wskaźnik powyżej opisanej struktury WNDCLASSEX.

Jeśli wywołanie funkcji się powiedzie, to zwracana jest specjalna wartość identyfikująca jednoznacznie rejestrowaną klasę. W przeciwnym razie zwracane jest 0, co właśnie sprawdza nasz program.

Tworzenie okna

Gdy klasa okna zostanie zarejestrowana w systemie Windows, można na jej podstawie tworzyć okna robocze aplikacji. Do tego celu wykorzystujemy funkcję:

HWND CreateWindowEx
(      
  DWORD     dwExStyle,
  LPCTSTR   lpClassName,
  LPCTSTR   lpWindowName,
  DWORD     dwStyle,
  int       x,
  int       y,
  int       nWidth,
  int       nHeight,
  HWND      hWndParent,
  HMENU     hMenu,
  HINSTANCE hInstance,
  LPVOID    lpParam
);
dwExStyle - określa rozszerzone style okna dla tworzonego okna. Ponieważ w tym programie nie wykorzystujemy tego parametru, a jest on dosyć rozbudowany, opiszemy go, gdy stanie się potrzebny.
lpClassName - wskaźnik tablicy znaków zakończonych kodem 0, zawierających nazwę klasy.
lpWindowName - wskaźnik tekstu będącego tytułem okna.
dwStyle - określa styl tworzonego okna. Parametr może być dowolną kombinacją następujących styli:
WS_BORDER - tworzy okno z cienką linią ramki
WS_CAPTION - tworzy okno z paskiem tytułowym
WS_CHILD - tworzy okno podrzędne. Okno zawierające ten styl nie może posiadać paska menu. Również ten styl nie może występować razem ze stylem WS_POPUP.
WS_CHILDWINDOW - to samo co WS_CHILD.
WS_CLIPCHILDREN - z operacji graficznych okna będą wyłączone obszary przykryte przez okna potomne.
WS_CLIPSIBLINGS - powoduje wyłączenie z operacji graficznych dla okien potomnych obszarów zakrytych przez inne okna potomne. Jeśli ten styl nie jest ustawiony, to okna potomne mogą rysować po przykrywającym je obszarze innego okna potomnego.
WS_DISABLED - tworzy okno, które jest początkowo zablokowane. Zablokowane okno nie może odczytywać danych od użytkownika.
WS_DLGFRAME - tworzy okno posiadające krawędź w stylu typowym dla okienek dialogowych. 
WS_GROUP - określa pierwszą kontrolkę w grupie kontrolek.
WS_HSCROLL - tworzy okno z poziomym paskiem przewijania.
WS_ICONIC - tworzy okno, które początkowo jest zminimalizowane do ikony. To samo co WS_MINIMIZE.
WS_MAXIMIZE - tworzy okno pierwotnie zmaksymalizowane
WS_MAXIMIZEBOX - tworzy okno z przyciskiem maksymalizacji.
WS_MINIMIZE - tworzy okno, które początkowo jest zminimalizowane do ikony. To samo co WS_ICONIC.
WS_MINIMIZEBOX - tworzy okno z przyciskiem minimalizacji.
WS_OVERLAPPED - tworzy okno, które może być przykrywane innymi oknami. Okno takie posiada pasek tytułowy oraz brzeg.
WS_OVERLAPPEDWINDOW - tworzy okno zakrywalne z ustawionymi stylami WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX, oraz WS_MAXIMIZEBOX.
WS_POPUP - tworzy wyskakujące okno.
WS_POPUPWINDOW - tworzy okno wyskakujące z ustawionymi stylami WS_BORDER, WS_POPUP i WS_SYSMENU.
WS_SIZEBOX - tworzy okno z brzegiem zawierającym ikonę skalowania.
WS_SYSMENU - tworzy okno z przyciskiem menu systemowego na pasku tytułowym. Styl WS_CAPTION również musi być dołączony.
WS_TABSTOP - Określa kontrolkę otrzymującą skupienie przy naciśnięciu klawisza TAB, Naciskanie klawisza TAB zmienia skupienie klawiatury na następną kontrolkę z ustawionym stylem WS_TABSTOP.
WS_THICKFRAME - tworzy okienko ze skalowalnym brzegiem - to samo co WS_SIZEBOX.
WS_TILED - to samo co WS_OVERLAPPED
WS_TILEDWINDOW - to samo co WS_OVERLAPPEDWINDOW
WS_VISIBLE - tworzy okno pierwotnie widoczne. Styl ten można włączać i wyłączać wykorzystując funkcje API ShowWindow lub SetWindowPos.
WS_VSCROLL - tworzy okno z pionowym paskiem przewijania.
x,y - określają początkową pozycję okna na ekranie. Współrzędne x i y odnoszą się do lewego górnego narożnika okna. W obu przypadkach można zastosować stałą CW_USEDEFAULT.
nWidth, nHeight - szerokość i wysokość okna.
hWndParent - jeśli tworzone okno jest własnością innego okna, to tutaj umieszczamy uchwyt właściciela
hMenu - uchwyt menu okna. Jeśli okno nie posiada menu, wpisujemy tutaj NULL.
hInstance - uchwyt programu, z którym jest skojarzone to okno
lpParam - wskaźnik wartości do przekazania do okna poprzez pole lpCreateParams struktury CREATESTRUCT, która jest wskazywana przez parametr lParam wiadomości WM_CREATE. Wiadomość jest wysyłana do tworzonego okna przez tą funkcję zanim zakończy ona swoje działanie.

Funkcja zwraca uchwyt do utworzonego okna. Uchwyt ten należy zapamiętać w osobnej zmiennej, ponieważ korzystają z niego funkcje obsługujące okno.

Pokazywanie okna na ekranie

Po utworzeniu okna pokazujemy je na ekranie za pomocą funkcji:

BOOL ShowWindow
(      
    HWND hWnd,
    int  nCmdShow
);
hWnd - uchwyt okna
nCmdShow - określa sposób wyświetlenia okna. Przy pierwszym wywołaniu okna aplikacji parametr ten powinien przyjąć wartość otrzymaną przez funkcję WinMain w parametrze  cmdShow. W kolejnych wywołaniach można stosować poniższe stałe:
SW_FORCEMINIMIZE - minimalizuje okno. Tą opcję zwykle stosujemy przy minimalizowaniu okna z innego wątku.
SW_HIDE - ukrywa to okno i aktywizuje kolejne okienko na pulpicie
SW_MAXIMIZE - maksymalizuje okno
SW_MINIMIZE - minimalizuje okno i aktywuje następne okno ze sterty ekranu
SW_RESTORE - aktywuje i wyświetla okno.
SW_SHOW - aktywuje okno i wyświetla je w bieżących rozmiarach i na bieżącej pozycji.
SW_SHOWDEFAULT - ustawia stan pokazywania okna na podstawie wartości SW_... określonej w strukturze STARTUPINFO, przekazanej do funkcji CreateProcess przez program, który uruchomił tą aplikację.
SW_SHOWMAXIMIZED - aktywuje okno i wyświetla je jako zmaksymalizowane
SW_SHOWMINIMIZED - aktywuje okno i wyświetla je jako zminimalizowane
SW_SHOWMINNOACTIVE - wyświetla okno jako zminimalizowane. Różni się od SW_SHOWMINIMIZED tym, iż okno nie jest aktywowane
SW_SHOWNA - wyświetla okno w bieżących rozmiarach i na bieżącej pozycji. Nie aktywuje okna.
SW_SHOWNOACTIVATE - wyświetla okno w jego ostatnich rozmiarach i na jego ostatniej pozycji. Nie aktywuje okna.
SW_SHOWNORMAL - aktywuje i wyświetla okno. Tą stałą aplikacja powinna wybrać przy pierwszym wyświetleniu okna.

Uaktualnienie obszaru roboczego okna

Wyświetlone na ekranie okno zwykle uaktualniamy za pomocą funkcji:

BOOL UpdateWindow(HWND hWnd);

Funkcja powoduje odświeżenie obszaru roboczego (client area) określonego okna przez wysłanie do niego wiadomości WM_PAINT. Wiadomość jest obsługiwana w procedurze okna.

Pobieranie wiadomości z kolejki

Gdy w systemie Windows pojawi się zdarzenie związane z naszym oknem, zostaje do niego wysłana odpowiednia wiadomość. System magazynuje wiadomości dla różnych okien na specjalnej kolejce. Do pobierania wiadomości wykorzystujemy funkcję:

BOOL GetMessage
(      
  LPMSG lpMsg,
  HWND  hWnd,
  UINT  wMsgFilterMin,
  UINT  wMsgFilterMax
);
lpMsg - wskaźnik struktury MSG, w której zostanie umieszczona wiadomość z kolejki wiadomości danego wątku. Struktura MSG jest następująca:
typedef struct
{
    HWND   hwnd;
    UINT   message;
    WPARAM wParam;
    LPARAM lParam;
    DWORD  time;
    POINT  pt;
} MSG, *PMSG;
hwnd - uchwyt okna, którego procedura otrzyma wiadomość. Jeśli wiadomość odnosi się do wątku, to pole zawiera NULL.
message - określa identyfikator wiadomości.
wParam - dodatkowa informacja związana z wiadomością - pole 16 bitowe
lParam - dodatkowa informacja związana z wiadomością - pole 32 bitowe
time - określa czas wysłania wiadomości
pt - określa pozycję kursora we współrzędnych ekranu w czasie wysłania wiadomości.
hWnd - uchwyt okna, dla którego wiadomości należy pobrać. Okno musi należeć do bieżącego wątku. Jeśli hWnd zawiera NULL, to funkcja GetMessage pobierze wiadomości dla wszystkich okien należących do bieżącego wątku.
wMsgFilterMin - określa najniższą wartość wiadomości do pobrania.
wMsgFilterMax - określa największą wartość wiadomości do pobrania. Jeśli oba parametry mają wartość 0, to GetMessage pobiera wszystkie wiadomości. Parametry te stosuje się zwykle do filtrowania wiadomości pochodzących od klawiatury i myszy.

Funkcja zwraca wartość 0 po odebraniu wiadomości WM_QUIT. W pozostałych przypadkach wartość jest niezerowa.

Przekształcanie wiadomości klawiatury

Naciśnięcie lub zwolnienie dowolnego klawisza powoduje wysłanie wiadomości o tzw. klawiszach wirtualnych. Wiadomości te umożliwiają przetwarzanie dosłownie wszystkich klawiszy. Jeśli w naszym oknie interesują nas jedynie klawisze znakowe (czyli takie, które produkują litery, cyfry i znaki), to możemy przetłumaczyć wiadomości klawiszy wirtualnych na klawisze znakowe za pomocą funkcji:

BOOL TranslateMessage(const MSG *lpMsg);

Rozsyłanie wiadomości do okna

Pobraną z kolejki wiadomość rozsyłamy do odpowiedniego okna za pomocą funkcji:

LRESULT DispatchMessage(const MSG *lpmsg);

Wiadomość trafia do procedury okna. Wartość zwrotna jest wartością zwróconą przez procedurę okna. Najczęściej się ją ignoruje.

Analiza programu

char ClassName[ ] = "SimpleWinClass";
Nazwa klasy okna, wg której Windows będzie budowało okna naszej aplikacji.
LRESULT CALLBACK WndProc
  (
  HWND h,    // uchwyt okna
  UINT uMsg, // kod wiadomości
  WPARAM wP, // parametr 16-bitowy
  LPARAM lP  // parametr 32-bitowy
  )
{
  if(uMsg == WM_DESTROY)
  {
    PostQuitMessage(0); return 0;
  }
  else return DefWindowProc(h,uMsg,wP,lP);
}
Do obsługi zdarzeń musimy przygotować specjalną funkcję zwaną procedurą okna.

Na podstawie kodu wiadomości procedura okna wykonuje odpowiednie działanie - np. wywołuje inne funkcje w programie użytkownika.

W przypadku naszej procedury okna obsługiwana jest tylko jedna wiadomość:
WM_DESTROY - zamknięcie okna.

Po otrzymaniu tej wiadomości wywoływana jest funkcja PostQuitMessage() informująca system, iż wątek chce zakończyć swoje działanie. Następnie kończymy działanie zwracając 0.

Dla wszystkich pozostałych wiadomości, których nie obsługuje nasza procedura okna, wywołujemy funkcję DefWindowProc przekazując jej wszystkie otrzymane parametry. Funkcja ta dokona standardowej obsługi wiadomości (tzn. większość z nich po prostu zignoruje).

  int WINAPI WinMain
    (
    HINSTANCE hinst,     // uchwyt aplikacji
    HINSTANCE hprevinst, // obecnie prawie zawsze NULL
    LPSTR     cmdLine,   // wskaźnik wiersza poleceń
                         // uruchamiającego ten program
    int       cmdShow)   // określa początkowy sposób
                         // wyświetlania okna
{
Funkcja WinMain jest punktem startowym aplikacji okienkowej.
  WNDCLASSEX wc;  // struktura klasy okna
  MSG        ms;  // przechowuje wiadomości aplikacji
  HWND       h;   // Uchwyt naszego okna
Tutaj definiujemy trzy zmienne używane w naszej aplikacji.
  wc.cbSize        = sizeof(WNDCLASSEX);
  wc.style         = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc   = WndProc;
  wc.cbClsExtra    = wc.cbWndExtra = 0;
  wc.hInstance     = hinst;
  wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = ClassName;
  wc.hIcon         = wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);

Pierwszą rzeczą w naszej aplikacji jest ustawienie pól struktury WNDCLASSEX, która posłuży do zarejestrowania w systemie Windows nowej klasy okienek - naszej klasy.

    if(!RegisterClassEx(&wc)) return 0;
Rejestrujemy klasę okna wykorzystując wypełnioną strukturę WNDCLASSEX. Jeśli rejestracja się nie uda, to natychmiast kończymy program.
    h = CreateWindowEx(0, ClassName, "Nasze pierwsze okno",
          WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
          300, 200, 0, 0, hinst, 0);
Na podstawie zarejestrowanej klasy tworzymy okno. Zwróć uwagę, iż do funkcji CreateWindowEx przekazuje się nazwę klasy oraz różne parametry dla tworzonego okna. Funkcja zwraca uchwyt utworzonego okna, który możemy przekazywać różnym funkcjom operującym na okienku.
    ShowWindow(h, cmdShow);
Gdy okno jest utworzone, możemy je umieścić na ekranie.
    UpdateWindow(h);
Następnie odświeżamy jego zawartość.
    while(GetMessage(&ms, NULL, 0, 0))
    {
        TranslateMessage(&ms);
        DispatchMessage(&ms);
    }
Tworzymy pętlę odczytującą wiadomości z systemu, przeznaczone dla naszej aplikacji. Pętla wykonywana jest do momentu otrzymania wartości 0 z funkcji GetMessage - oznacza to, iż wszystkie wątki aplikacji zakończyły działanie i nie ma dla nich już wiadomości w kolejce.

Wewnątrz pętli wywołujemy dwie funkcje przetwarzamy otrzymaną wiadomość i przesyłamy ją do procedury okna.

    return ms.wParam;
}
Kończąc zwracamy parametr wParam (16-bitowy) zawarty w strukturze otrzymanej wiadomości przez ostatnie wywołanie funkcji GetMessage().


   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2024 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe