Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W przykładach w tej sekcji opisano sposób wykonywania następujących zadań:
- Tworzenie okna głównego
- Tworzenie, wyliczanie i określanie rozmiaru okien podrzędnych
- Niszczenie Okna
- Używanie warstwowych okien
Tworzenie okna głównego
Pierwsze okno tworzone przez aplikację jest zazwyczaj głównym oknem. Tworzysz okno główne, używając funkcji CreateWindowEx, określając klasę okna, nazwę okna, style okien, rozmiar, pozycję, uchwyt menu, uchwyt instancji oraz dane tworzenia. Główne okno należy do klasy okien zdefiniowanej przez aplikację, więc należy zarejestrować klasę okien i podać procedurę okna dla klasy przed utworzeniem okna głównego.
Większość aplikacji zazwyczaj używa stylu WS_OVERLAPPEDWINDOW do utworzenia okna głównego. Ten styl zapewnia oknu pasek tytułu, menu okna, obramowanie regulacyjne oraz przyciski minimalizowania i maksymalizowania. Funkcja CreateWindowEx zwraca uchwyt, który jednoznacznie identyfikuje okno.
Poniższy przykład tworzy główne okno należące do klasy okna zdefiniowanego przez aplikację. Nazwa okna, okno główne, pojawi się na pasku tytułu okna. Łącząc style WS_VSCROLL i WS_HSCROLL z stylem WS_OVERLAPPEDWINDOW, aplikacja tworzy główne okno z poziomymi i pionowymi paskami przewijania oprócz składników dostarczonych przez styl WS_OVERLAPPEDWINDOW. Cztery wystąpienia stałej CW_USEDEFAULT ustawiają początkowy rozmiar i położenie okna na wartości domyślne zdefiniowane przez system. Określając null zamiast uchwytu menu, okno będzie miało menu zdefiniowane dla klasy okna.
HINSTANCE hinst;
HWND hwndMain;
// Create the main window.
hwndMain = CreateWindowEx(
0, // no extended styles
"MainWClass", // class name
"Main Window", // window name
WS_OVERLAPPEDWINDOW | // overlapped window
WS_HSCROLL | // horizontal scroll bar
WS_VSCROLL, // vertical scroll bar
CW_USEDEFAULT, // default horizontal position
CW_USEDEFAULT, // default vertical position
CW_USEDEFAULT, // default width
CW_USEDEFAULT, // default height
(HWND) NULL, // no parent or owner window
(HMENU) NULL, // class menu used
hinst, // instance handle
NULL); // no window creation data
if (!hwndMain)
return FALSE;
// Show the window using the flag specified by the program
// that started the application, and send the application
// a WM_PAINT message.
ShowWindow(hwndMain, SW_SHOWDEFAULT);
UpdateWindow(hwndMain);
Zwróć uwagę, że poprzedni przykład wywołuje funkcję ShowWindow po utworzeniu okna głównego. Dzieje się tak, ponieważ system nie wyświetla automatycznie okna głównego po jego utworzeniu. Poprzez przekazanie flagi SW_SHOWDEFAULT do ShowWindow, aplikacja umożliwia programowi, który ją uruchomił, ustawienie początkowego stanu wyświetlania głównego okna. Funkcja UpdateWindow wysyła okno z pierwszym komunikatem WM_PAINT.
Tworzenie, wyliczanie i określanie rozmiaru systemu Windows podrzędnego
Obszar klienta okna można podzielić na różne obszary funkcjonalne przy użyciu okien podrzędnych. Tworzenie okna podrzędnego przypomina tworzenie okna głównego — używasz funkcji CreateWindowEx. Aby utworzyć okno klasy okien zdefiniowanej przez aplikację, należy zarejestrować klasę okien i podać procedurę okna przed utworzeniem okna podrzędnego. Należy podać okno podrzędne w stylu WS_CHILD i określić okno nadrzędne dla okna podrzędnego podczas jego tworzenia.
Poniższy przykład dzieli obszar klienta głównego okna aplikacji na trzy obszary funkcjonalne, tworząc trzy okna podrzędne o równym rozmiarze. Każde okno podrzędne ma taką samą wysokość jak obszar użytkowy okna głównego, ale każde z nich ma jedną trzecią jego szerokości. Okno główne tworzy okna podrzędne w odpowiedzi na komunikat WM_CREATE, który okno główne otrzymuje podczas procesu tworzenia własnego okna. Ponieważ każde okno podrzędne ma styl WS_BORDER, każda z nich ma cienką krawędź liniową. Ponadto, ponieważ styl WS_VISIBLE nie jest określony, każde okno podrzędne jest początkowo ukryte. Zauważ również, że każde okno podrzędne ma przypisany identyfikator okna podrzędnego.
Główne okno ustala rozmiary i umieszcza okna podrzędne w odpowiedzi na komunikat WM_SIZE, który główne okno otrzymuje po zmianie rozmiaru. W odpowiedzi na WM_SIZEokno główne pobiera wymiary obszaru klienta przy użyciu funkcji GetClientRect, a następnie przekazuje wymiary do funkcji EnumChildWindows. EnumChildWindows przekazuje dojście do każdego okna podrzędnego, z kolei do funkcji wywołania zwrotnego zdefiniowanej przez aplikację EnumChildProc. Ta funkcja ustawia rozmiary i pozycje każdego okna podrzędnego przez wywołanie funkcji MoveWindow; rozmiar i położenie są oparte na wymiarach obszaru klienta okna głównego i identyfikatora okna podrzędnego. Następnie EnumChildProc wywołuje funkcję ShowWindow, aby okno było widoczne.
#define ID_FIRSTCHILD 100
#define ID_SECONDCHILD 101
#define ID_THIRDCHILD 102
LONG APIENTRY MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
RECT rcClient;
int i;
switch(uMsg)
{
case WM_CREATE: // creating main window
// Create three invisible child windows.
for (i = 0; i < 3; i++)
{
CreateWindowEx(0,
"ChildWClass",
(LPCTSTR) NULL,
WS_CHILD | WS_BORDER,
0,0,0,0,
hwnd,
(HMENU) (int) (ID_FIRSTCHILD + i),
hinst,
NULL);
}
return 0;
case WM_SIZE: // main window changed size
// Get the dimensions of the main window's client
// area, and enumerate the child windows. Pass the
// dimensions to the child windows during enumeration.
GetClientRect(hwnd, &rcClient);
EnumChildWindows(hwnd, EnumChildProc, (LPARAM) &rcClient);
return 0;
// Process other messages.
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
{
LPRECT rcParent;
int i, idChild;
// Retrieve the child-window identifier. Use it to set the
// position of the child window.
idChild = GetWindowLong(hwndChild, GWL_ID);
if (idChild == ID_FIRSTCHILD)
i = 0;
else if (idChild == ID_SECONDCHILD)
i = 1;
else
i = 2;
// Size and position the child window.
rcParent = (LPRECT) lParam;
MoveWindow(hwndChild,
(rcParent->right / 3) * i,
0,
rcParent->right / 3,
rcParent->bottom,
TRUE);
// Make sure the child window is visible.
ShowWindow(hwndChild, SW_SHOW);
return TRUE;
}
Niszczenie okna
Aby zniszczyć okno, możesz użyć funkcji DestroyWindow. Zazwyczaj aplikacja wysyła komunikat WM_CLOSE przed zniszczeniem okna, dając oknu możliwość zwrócenia się do użytkownika o potwierdzenie przed jego zniszczeniem. Okno z elementem menu automatycznie odbiera komunikat WM_CLOSE, gdy użytkownik kliknie opcję Zamknij w menu okna. Jeśli użytkownik potwierdzi, że okno powinno zostać zniszczone, aplikacja wywołuje DestroyWindow. System wysyła komunikat WM_DESTROY do okna po usunięciu go z ekranu. W odpowiedzi na WM_DESTROYokno zapisuje swoje dane i zwalnia wszystkie przydzielone zasoby. Główne okno kończy przetwarzanie WM_DESTROY przez wywołanie funkcji PostQuitMessage w celu zamknięcia aplikacji.
W poniższym przykładzie pokazano, jak wyświetlić monit o potwierdzenie użytkownika przed zniszczeniem okna. W odpowiedzi na WM_CLOSEzostanie wyświetlone okno dialogowe zawierające przyciski Tak, Niei Anuluj. Jeśli użytkownik kliknie tak, zostanie wywołana DestroyWindow; w przeciwnym razie okno nie zostanie zniszczone. Ponieważ aplikacja obsługuje komunikat WM_CLOSE, 0 jest zwracana we wszystkich przypadkach. Ponieważ zniszczone okno jest głównym oknem, przykład wywołuje PostQuitMessage w odpowiedzi na WM_DESTROY.
case WM_CLOSE:
// Create the message box. If the user clicks
// the Yes button, destroy the main window.
if (MessageBox(hwnd, szConfirm, szAppName, MB_YESNOCANCEL) == IDYES)
DestroyWindow(hwndMain);
return 0;
case WM_DESTROY:
// Post the WM_QUIT message to
// quit the application terminate.
PostQuitMessage(0);
return 0;
Korzystanie z warstwowych okien
Aby okno dialogowe było wyświetlane jako przezroczyste okno, najpierw utwórz okno dialogowe tak jak zwykle. Następnie na WM_INITDIALOGustaw warstwowy bit rozszerzonego stylu okna i wywołaj SetLayeredWindowAttributes z żądaną wartością alfa. Kod może wyglądać następująco:
// Set WS_EX_LAYERED on this window
SetWindowLong(hwnd,
GWL_EXSTYLE,
GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
// Make this window 70% alpha
SetLayeredWindowAttributes(hwnd, 0, (255 * 70) / 100, LWA_ALPHA);
Należy pamiętać, że trzeci parametr SetLayeredWindowAttributes jest wartością, która waha się od 0 do 255, a 0 sprawia, że okno jest całkowicie przezroczyste i 255, dzięki czemu jest całkowicie nieprzezroczyste. Ten parametr naśladuje bardziej wszechstronną funkcję BLENDFUNCTION z funkcji AlphaBlend .
Aby to okno było całkowicie nieprzezroczyste, usuń bit WS_EX_LAYERED, wywołując SetWindowLong, a następnie poproś okno o ponowne odmalowanie. Usunięcie bitu danych jest pożądane, aby dać znać systemowi, że może zwolnić część pamięci skojarzonej z warstwowaniem i przekierowaniem. Kod może wyglądać następująco:
// Remove WS_EX_LAYERED from this window styles
SetWindowLong(hwnd,
GWL_EXSTYLE,
GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
// Ask the window and its children to repaint
RedrawWindow(hwnd,
NULL,
NULL,
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
Aby można było używać warstwowych okien podrzędnych, aplikacja musi zadeklarować zgodność z Windows 8 w manifeście.
W przypadku systemu Windows 10/11 można uwzględnić ten fragment kodu zgodności w sekcji app.manifest, aby działał pod systemem Windows 10.
...
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 GUID -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
...
Więcej informacji na temat modyfikowania manifestu aplikacji można znaleźć tutaj: Manifesty aplikacji