Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Pierwsze Okno W Winapi


Rekomendowane odpowiedzi

Opublikowano

Nadszedł czas na stworzenie okna w naszym programie, czyli w funkcji WinMain. Nie jest to skomplikowane, ale dość długie w zapisie, dlatego nie przestraszcie się, jak zobaczycie długi kod.

 

Musimy mieć świadomość, że nasz program to proces, który może stworzyć własne okno i sterować nim, nasze okno nie jest programem, ale tylko elementem procesu. Każdy proces może stworzyć wiele różnych okien i wszystkie te okna, będą sterowane z jednego programu(procesu).

 

Klasa okna

 

Ale nie wszystko na raz, zacznijmy od początku. Najpierw musimy uzupełnić strukturę o nazwie WNDCLASSEX. Jest to struktura zawierająca informacje o klasie naszego okna. Spójrzmy na poniższy program:

 

#include <windows.h>

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)
{
 WNDCLASSEX wc;
//deklarujemy naszą strukturę klasy okna o nazwie wc
 //po zadeklarowaniu uzupełniamy ją informacjami

 wc.hInstance=hInst;
//uchwyt naszego procesu programu

 wc.lpszClassName= "Nazwa klasy okna";
//nazwa klasy naszego okna

 wc.lpfnWndProc=DefWindowProc;
//procedura obsługi dla klasy okna

 wc.style=CS_DBLCLKS;
//styl klasy okna

 wc.cbSize=sizeof(WNDCLASSEX);
//wielkość naszej klasy okna w pamięci
 //wygląd okna

 wc.hIcon=LoadIcon(0,IDI_APPLICATION);
//ikona okien

 wc.hIconSm=LoadIcon(0,IDI_APPLICATION);
//mała ikona okien

 wc.hCursor=LoadCursor(0,IDC_ARROW);
//kursor

 wc.lpszMenuName=0;
//menu w oknach utworzonych z tej klasy

 wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
//tło okna
 //dodatkowe dane

 wc.cbWndExtra=0;
 wc.cbClsExtra=0;

//rejestracja klasy w systemie

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

//kontynuacja programu

 return 0 ;
}

Jak już wcześniej powiedziałem, aby mieć okno, musimy stworzyć klasę onka WNDCLASSEX w naszym programie. Każde okno w windowsie musi należeć do jakiejś klasy okien, czyli takiego szablonu mówiącego jak okno ma się zachowywać. W swoim programie klasę okna nazwałem "wc". Po zadeklarowaniu klasy okna, możemy zająć się wypełnianiem danych w naszej klasie okna. Kolejno omówię elementy w strukturze WNDCLASSEX. Oto jej ciało:

 

struct WNDCLASSEX
{
 HINSTANCE hInstance;
 LPCSTR lpszClassName;
 WNDPROC lpfnWndProc;
 UNIT style;
 UNIT cbSize;
 HICON hIcon;
 HICON hIconSm;
 HCURSOR hCursor;
 LPCTSTR lpszMenuName;
 HBRUSH hbrBackground;
 INT cbWndExtra;
 INT cbClsExtra;
}

HINSTANCE hInstance

Jest to uchwyt do procesu, do którego ma należeć ta klasa. My oczywiście chcemy, żeby klasa należała do naszego programu, więc tej zmiennej przypisujemy uchwyt naszego programu, który pochodzi z pierwszego parametru naszej funkcji WinMain.

 

LPCSTR lpszClassName

Jest to nazwa naszej klasy okna, można ją nazwać jak tylko chcemy. Każda klasa okien w systemie musi mieć swoją unikatową, niepowtarzalną nazwę i tu ją ustalamy.

 

WNDPROC lpfnWndProc

Jest to nazwa funkcji, która będzie obsługiwać komunikaty przychodzące do okien utworzonych z tej klasy. O pisaniu takich funkcji będzie po następnej lekcji. Narazie przypiszmy tej klasie, domyślną funkcję "DefWindowProc", która wszystkie komunikaty obsługuje domyślnie za nas.

 

UNIT style

Tutaj przypisujemy styl okien, utworzonych z tej klasy. Możemy nie podawać domyślego stylu, przypisując 0. Przydatnym stylem może być CS_DBLCLKS, dzięki temu stylowi nasze okna utworzone z tej klasy, mogą obsługiwać podwójne kliknięcie. Więcej stylów poznasz w kolejnej lekcji.

 

UNIT cbSize

Tutaj przypisujemy wielkość naszej klasy w pamięci. Należy użyć operatora sizeof, aby uzyskać wilekość struktury WNDCLASSEX.

 

HICON hIcon

Jest to uchwyt ikony dla naszych okien utworzonych z tej klasy. Rozmiar tej ikony powinien wynosić co najmniej 32x32 piksele. Zwykle ikona ta jest wyświetlana tylko w pasku, który pojawi się po naciśnięciu Alt+Tab. Uchwyt można uzyskać używając funkcji LoadIcon. Jeżeli używamy standardowej systemowej ikony, pierwszego parametru nie podajemy(0), natomiast drugi ma być numerem systemowej ikony. Oto kilka najpopularnieszych ikon systemowych: IDI_APPLICATION, IDI_QUESTION, IDI_ASTERISK, IDI_HAND, IDI_EXCLAMATION, IDI_WINLOGO(tylko w win95/98). Więcej na temat ikon będzie w innej lekcji.

 

HICON hIconSm

Jest to uchwyt do małej ikony okna. Te mniejsze ikony są pokazywane na paskach tytułowych w oknach utworzonych z tej klasy, oraz na pasku zadań Windows. Zwykle tu podajemy uchwyt do tej samej ikony co hIcon lub podejemy 0, co także oznacza użycie uchwytu z hIcon. Nawet gdy ikony nie będą się zgadzać swoimi rozmiarami z zalecanymi, Windows i tak odpowiednio przeskaluje ikony i dopasuje je do swoich wymagań.

 

HCURSOR hCursor

Uchwyt kursora na okna utworzone z tej klasy. Uchwyt możemy uzyskać używając funkcji LoadCursor. Podobna jest ona do funkcji LoadIcon, ale ta służy do załadowania kursora. W przypadku standardowego systemowego kursora, należy pominąc(podać 0) pierwszy argument, natomiast w drugim podać numer kursora. Standardową strzałką jest IDC_ARROW.

 

LPCTSTR lpszMenuName

Jest to nazwa zasobu menu w oknach utworzonych z tej klasy. Na temat robienia menu będzie w innej lekcji. Poza tym, menu na oknie możemy umieścić jeszcze w innym miejscu.

 

HBRUSH hbrBackground

Jest to uchwyt do pędzla z tłem okna. Do uzyskania takiego uchwytu możemy użyć funkcji GetStockObject, jako parametr przyjmuje ona gotowy pędzel. Funkcję należy rzutować na obiekt typu HBRUSH(pędzel). Przykładowe pędzle: BLACK_BRUSH, WHITE_BRUSH, COLOR_BTNFACE. Więcej na ten temat pędzli w dziale poświęconym GDI.

 

INT cbWndExtra

Określa ilość dodatkowej pamięci w bajtach, dla każdego okna utworzonego z tej klasy. Zwykle dodatkowa ilość nie jest potrzebna.

 

INT cbClsExtra

Określa ilość dodatkowej pamięci w bajtach dla naszej klasy. Oczywiście dodatkowa pamięć nie jest nam potrzebna.

 

Po wypełnieniu klasy należy ją zarejestrować w systemie, aby Windows widział, że została utworzona nowa klasa okna w naszym programie. Do rejestracji służy Funkcja RegisterClassEx. Jako parametr przyjmuje adres struktury klasy, którą będziemy rejestrować, adres uzyskujemy poprzez użycie operatora "&". Zwraca ona 1, jeżeli rejestracja się powiedzie, natomiast 0 jeżeli się nie powiedzie.

 

Utworzenie okna

 

Mamy już klasę naszego okna, ale to dopiero pół sukcesu, dopiero teraz możemy utworzyć nasze okno w pamięci. Aby utworzyć okno potrzeba nam będzie nowa zmienna HWND. Jest to właśnie uchwyt naszego okna, czyli jego numer, po którym będziemy mogli się do niego odwoływać. Teraz wystarczy stworzyć okno funkcją CreateWindowEx.

#include <windows.h>

CONST CHAR ClassName[]="Klasa naszego okna";
//deklaracja globalnej nazwy naszej klasy, lepiej tak robić


INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)
{

//struktura klasy okna

 WNDCLASSEX wc;
 wc.hInstance=hInst;
 wc.lpszClassName=ClassName;
//używamy globalnej nazwy dla naszej klasy

 wc.lpfnWndProc=DefWindowProc;
 wc.style=CS_DBLCLKS;
 wc.cbSize=sizeof(WNDCLASSEX);
 wc.hIcon=LoadIcon(0,IDI_APPLICATION);
 wc.hIconSm=0;
 wc.hCursor=LoadCursor(0,IDC_ARROW);
 wc.lpszMenuName=0;
 wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 wc.cbWndExtra=0;
 wc.cbClsExtra=0;
 if(RegisterClassEx(&wc)==0) return 0;
//rejestracja klasy w systemie


//tworzenie okna o nazwie Okno przy uzyciu funkcji CreateWindowEx

 HWND Okno=CreateWindowEx(0,ClassName,"Tytuł okna",WS_OVERLAPPEDWINDOW,50,50,100,100,0,0,hInst,0);
 return 0;
}

Typ HWND to uchwyt okna naszego programu, jak pamiętasz, jest to numer okna w systemie. Po deklaracji uchwytu okna należy je zainicjować. Do tworzenia okna(inicjacji), służy funkcja CreateWindowEx. Funkcja pobiera 12 parametrów okna. Tak wygląda jej deklaracja:

HWND CreateWindowEx
(
 DWORD dwExStyle,
//rozszerzony styl okna

 LPCTSTR lpClassName,
//nazwa klasy okna do jakiej ma należeć okno

 LPCTSTR lpWindowName,
//tytuł okna, będzie wyświetlany na pasku tytułu

 DWORD dwStyle,
//podstawowy styl okna

 INT x,
//współrzędna x okna w pikselach

 INT y,
//współrzędna y okna w pikselach

 INT nWidth,
//szerokość okna w pikselach

 INT nHeight,
//wysokość okna w pikselach

 HWND hWndParent,
//uchwyt okna rodzica, ma być to główne okno, naszym rodzicem będzie pulpit, więc podajemy 0

 HMENU hMenu,
//uchwyt do menu okna, drugi sposób zrobienia menu, o którym wcześniej wspominałem

 HINSTANCE hInstance,
//uchwyt procesu do którego ma należeć nasze okno, podajemy tu uchwyt swojego programu

 LPVOID lpParam
//wskaźnik na dodatkowe informacje, które zostaną przekazane z komunikatem tworzącym okno

);

 

DWORD dwExStyle

Styl rozszerzony okna, o stylach będzie w następnej lekcji.

 

LPCTSTR lpClassName

Nazwa klasy do jakiej ma należeć okno. Tutaj powinniśmy podać nazwę klasy, którą przed chwilą utworzyliśmy dla naszego programu. To co napisaliśmy w wc.lpszClassName piszemy także tutaj.

 

LPCTSTR lpWindowName

Tytuł okna, który będzie widoczny na pasku tytułowym okna. Istnieje możliwość poźniejszej zmiany funkcją SetWindowText.

 

DWORD dwStyle

Podstawowy styl okna, o stylach będzie w następnej lekcji.

 

INT x

Współrzędna x okna na pulpicie(w pikselach) lub oknie rodzica.

 

INT y

Współrzędna y okna na puplicie(w pikselach) lub oknie rodzica.

 

INT nWidth

Szerokośc okna(w pikselach).

 

INT nHeight

Wysokość okna(w pikselach).

 

HWND hWndParent

Uchwyt okna rodzica, czyli okna z którego utworzone jest okno. Jeżeli tworzymy normlane okno w programie(takie które znajduje się na pulpicie) należy podać 0(lub HWND_DESKTOP), rodzicem takiego okna będzie domyślnie pulpit. Jeżeli podamy tu uchyt do innego okna, to nasze okno zostanie utworzone wewnątrz tego podanego okna.

 

HMENU hMenu

Menu okna. Podajemy 0, bo nie mamy menu. O tworzeniu menu będzie w następnych lekcjach.

 

HINSTANCE hInstance

Uchwyt procesu do którego ma należeć okno. Oczywiste jest, że podajemy numer naszego programu hInst.

 

LPVOID lpParam

Dodatkowe dane, których nie mamy.

 

Po wywołaniu funckcji inicjującej okno(CreateWindowEx), zwróci ona uchwyt do nowo utworzonego okna. Jeżeli fucnkja zwróci pusty uchwyt(0), oznacza to, że coś się nie powiodło.

 

Pokazanie okna na ekranie

 

Mamy już zainicjowane okno w pamięci. Można skompilować projekt i zobaczymy, że nadal nic się nie pokazuje. Okno, które utworzyliśmy, mamy w pamięci, jednak aby je zobaczyć musimy je pokazać. Możemy to zrobić na 2 sposoby:

 

1) Poprzez wywołanie funkcji ShowWindow.

 

Po utworzeniu okna funkcją CreateWindowEx, używamy funkcji ShowWindow. Oto jej deklaracja:

 

INT ShowWindow
(
 HWND hWnd,
//uchwyt modyfikowanego okna

 INT Show
//rodzaj stanu widoczności okna

);

Nazwa funkcji ShowWindow(), jest trochę myląca, gdyż nie służy jedynie pokazywaniu okna, ale zmienianiu stanu widoczności tego okna. Pierwszym parametrem jest uchwyt okna, które modyfikujemy, natomiast drugim sposób wyświetlenia okna. Oto kilka możliwości wyświetlenia okna:

SW_SHOW - pokazanie okna w normalnych rozmiarach,

SW_HIDE - schowanie okna(nie mylić ze zminimalizowaniem), jest ono nie widoczne z poziomu użytkownika, domyślnie każde okno po uzyciu funkcji CreateWindowEx, ma ten status,

SW_MAXIMIZE - okno jest zmaksymalizowane,

SW_MINIMIZE - okno jest zminimalizowane,

SW_RESTORE - przywrócenie oknu standardowych rozmiarów(tych z fucnkji CreateWindowEx).

 

Aby okno było widoczne należy nadać mu stan widoczności(SW_SHOW), wywołujemy funkcje:

 

...

ShowWindow(Okno,SW_SHOW);
//pokazanie okna

 

...

 

Oczywiście dzięki tej funkcji możemy także schować pokazywane okno, czy zmaksymalizować lub zminimalizować:

...
ShowWindow(Okno,SW_HIDE);
//schowanie okna

...

...
ShowWindow(Okno,SW_MAXIMIZE);
//zmaksymalizowanie okna

...

...
ShowWindow(Okno,SW_MINIMIZE);
//zminimalizowanie okna

...

Tutaj trzeba też powiedzieć o ostatnim parametrze funkcji WinMain, otóż jest to właśnie ten sposób wyświetlenia okna, tyle, że to system przekazuje sposób wyświetlenia, zwykle jest to SW_SHOW. Ja osobiście radzę właśnie stosować wyświetlanie według tego parametru WinMain, ponieważ nasz program będzie bardziej powiązany z systemem. No chyba, że już bardzo chcemy sami określić w jaki sposób ma nam się pokazać okno.

 

#include <windows.h>

CONST CHAR ClassName[]="Klasa naszego okna";

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)
{
 WNDCLASSEX wc;
 wc.hInstance=hInst;
 wc.lpszClassName=ClassName;
 wc.lpfnWndProc=DefWindowProc;
 wc.style=CS_DBLCLKS;
 wc.cbSize=sizeof(WNDCLASSEX);
 wc.hIcon=LoadIcon(0,IDI_APPLICATION);
 wc.hIconSm=0;
 wc.hCursor=LoadCursor(0,IDC_ARROW);
 wc.lpszMenuName=0;
 wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 wc.cbWndExtra=0;
 wc.cbClsExtra=0;
 if(RegisterClassEx(&wc)==0) return 0;

HWND Okno=CreateWindowEx(0,ClassName,"Tytuł okna",WS_OVERLAPPEDWINDOW,50,50,100,100,0,0,hInst,0);
 ShowWindow(Okno,nShow);
//pokazujemy okno, używamy ostatniego parametru z funkcji WinMain

 return0;
}

2) Poprzez dodanie stylu WS_VISIBLE.

 

Innym sposobem pokazanie okna jest dodanie stylu WS_VISIBLE w funkcji CreateWindowEx. Ten styl powoduje, że odrazu po zainicjowaniu okno przyjmie status SW_SHOW(widoczny). Styl ten dodaje się w czwartym parametrze funkcji, łączy się go z istniejącymi używając operatora sumy bitowej |. Takie okno zawsze po utworzeniu będzie widoczne.

 

#include <windows.h>

 

CONST CHAR ClassName[]="Klasa naszego okna";

 

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR lStart,INT nShow)

{

WNDCLASSEX wc;

wc.hInstance=hInst;

wc.lpszClassName=ClassName;

wc.lpfnWndProc=DefWindowProc;

wc.style=CS_DBLCLKS;

wc.cbSize=sizeof(WNDCLASSEX);

wc.hIcon=LoadIcon(0,IDI_APPLICATION);

wc.hIconSm=0;

wc.hCursor=LoadCursor(0,IDC_ARROW);

wc.lpszMenuName=0;

wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);

wc.cbWndExtra=0;

wc.cbClsExtra=0;

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

HWND Okno=CreateWindowEx(0,ClassName,"Tytuł okna",WS_OVERLAPPEDWINDOW|WS_VISIBLE,50,50,100,100,0,0,hInst,0);

 

//w czwartym parametrze jest dodany styl WS_VISIBLE

 

return0;

}

[/code]

Teraz po skompilowaniu projektu, w którym mamy pokazane okno, na moment powinniśmy zobaczyć mignięcie naszego okna.

 

Copyright by www.winapi.rox.pl

9989.jpg

"Głupców nie sieją, sami się rodzą"

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...