Menggunakan Windows
Contoh di bagian ini menjelaskan cara melakukan tugas berikut:
- Membuat Jendela Utama
- Membuat, Menghitung, dan Mengukur Jendela Anak
- Menghancurkan Jendela
- Menggunakan Windows Berlapis
Membuat Jendela Utama
Jendela pertama yang dibuat aplikasi biasanya merupakan jendela utama. Anda membuat jendela utama dengan menggunakan fungsi CreateWindowEx , menentukan kelas jendela, nama jendela, gaya jendela, ukuran, posisi, handel menu, handel instans, dan data pembuatan. Jendela utama milik kelas jendela yang ditentukan aplikasi, jadi Anda harus mendaftarkan kelas jendela dan menyediakan prosedur jendela untuk kelas sebelum membuat jendela utama.
Sebagian besar aplikasi biasanya menggunakan gaya WS_OVERLAPPEDWINDOW untuk membuat jendela utama. Gaya ini memberi jendela bilah judul, menu jendela, batas ukuran, dan meminimalkan dan memaksimalkan tombol. Fungsi CreateWindowEx mengembalikan handel yang secara unik mengidentifikasi jendela.
Contoh berikut membuat jendela utama milik kelas jendela yang ditentukan aplikasi. Nama jendela, Jendela Utama, akan muncul di bilah judul jendela. Dengan menggabungkan gaya WS_VSCROLL dan WS_HSCROLL dengan gaya WS_OVERLAPPEDWINDOW, aplikasi membuat jendela utama dengan bilah gulir horizontal dan vertikal selain komponen yang disediakan oleh gaya WS_OVERLAPPEDWINDOW. Empat kemunculan konstanta CW_USEDEFAULT mengatur ukuran awal dan posisi jendela ke nilai default yang ditentukan sistem. Dengan menentukan NULL alih-alih handel menu, jendela akan memiliki menu yang ditentukan untuk kelas jendela.
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);
Perhatikan bahwa contoh sebelumnya memanggil fungsi ShowWindow setelah membuat jendela utama. Ini dilakukan karena sistem tidak secara otomatis menampilkan jendela utama setelah membuatnya. Dengan meneruskan bendera SW_SHOWDEFAULT ke ShowWindow, aplikasi memungkinkan program yang memulai aplikasi untuk mengatur status peragaan awal jendela utama. Fungsi UpdateWindow mengirimkan jendela pesan WM_PAINT pertamanya.
Membuat, Menghitung, dan Mengukur Jendela Anak
Anda dapat membagi area klien jendela menjadi area fungsi yang berbeda dengan menggunakan jendela anak. Membuat jendela anak seperti membuat jendela utama—Anda menggunakan fungsi CreateWindowEx. Untuk membuat jendela kelas jendela yang ditentukan aplikasi, Anda harus mendaftarkan kelas jendela dan menyediakan prosedur jendela sebelum membuat jendela anak. Anda harus memberi jendela anak gaya WS_CHILD dan menentukan jendela induk untuk jendela anak saat Anda membuatnya.
Contoh berikut membagi area klien jendela utama aplikasi menjadi tiga area fungsi dengan membuat tiga jendela anak dengan ukuran yang sama. Setiap jendela anak memiliki tinggi yang sama dengan area klien jendela utama, tetapi masing-masing memiliki lebar sepertiga. Jendela utama membuat jendela anak sebagai respons terhadap pesan WM_CREATE , yang diterima jendela utama selama proses pembuatan jendelanya sendiri. Karena setiap jendela anak memiliki gaya WS_BORDER , masing-masing memiliki batas garis tipis. Selain itu , karena gaya WS_VISIBLE tidak ditentukan, setiap jendela anak awalnya disembunyikan. Perhatikan juga bahwa setiap jendela anak diberi pengidentifikasi jendela anak.
Ukuran jendela utama dan memposisikan jendela anak sebagai respons terhadap pesan WM_SIZE , yang diterima jendela utama ketika ukurannya berubah. Sebagai respons terhadap WM_SIZE, jendela utama mengambil dimensi area kliennya dengan menggunakan fungsi GetClientRect dan kemudian meneruskan dimensi ke fungsi EnumChildWindows. EnumChildWindows meneruskan handel ke setiap jendela anak, pada gilirannya, ke fungsi panggilan balik EnumChildProc yang ditentukan aplikasi. Ukuran fungsi ini dan memposisikan setiap jendela anak dengan memanggil fungsi MoveWindow ; ukuran dan posisi didasarkan pada dimensi area klien jendela utama dan pengidentifikasi jendela anak. Setelah itu, EnumChildProc memanggil fungsi ShowWindow untuk membuat jendela terlihat.
#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;
}
Menghancurkan Jendela
Anda dapat menggunakan fungsi DestroyWindow untuk menghancurkan jendela. Biasanya, aplikasi mengirim pesan WM_CLOSE sebelum menghancurkan jendela, memberi jendela kesempatan untuk meminta konfirmasi kepada pengguna sebelum jendela dihancurkan. Jendela yang menyertakan menu jendela secara otomatis menerima pesan WM_CLOSE saat pengguna mengklik Tutup dari menu jendela. Jika pengguna mengonfirmasi bahwa jendela harus dihancurkan, aplikasi memanggil DestroyWindow. Sistem mengirim pesan WM_DESTROY ke jendela setelah menghapusnya dari layar. Sebagai respons terhadap WM_DESTROY, jendela menyimpan datanya dan membebaskan sumber daya apa pun yang dialokasikannya. Jendela utama menyimpulkan pemrosesan WM_DESTROY dengan memanggil fungsi PostQuitMessage untuk keluar dari aplikasi.
Contoh berikut menunjukkan cara meminta konfirmasi pengguna sebelum menghancurkan jendela. Sebagai respons terhadap WM_CLOSE, kotak dialog ditampilkan yang berisi tombol Ya, Tidak, dan Batal. Jika pengguna mengklik Ya, DestroyWindow dipanggil; jika tidak, jendela tidak dihancurkan. Karena aplikasi menangani pesan WM_CLOSE , 0
dikembalikan dalam semua kasus. Karena jendela yang dihancurkan adalah jendela utama, contoh memanggil PostQuitMessage sebagai respons terhadap 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;
Menggunakan Windows Berlapis
Untuk membuat kotak dialog muncul sebagai jendela tembus, pertama-tama buat dialog seperti biasa. Kemudian, pada WM_INITDIALOG, atur bit berlapis dari gaya jendela yang diperluas dan panggil SetLayeredWindowAttributes dengan nilai alfa yang diinginkan. Kode mungkin terlihat seperti ini:
// 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);
Perhatikan bahwa parameter ketiga SetLayeredWindowAttributes adalah nilai yang berkisar dari 0 hingga 255, dengan 0 membuat jendela benar-benar transparan dan 255 membuatnya benar-benar buram. Parameter ini meniru BLENDFUNCTION yang lebih serbaguna dari fungsi AlphaBlend.
Untuk membuat jendela ini benar-benar buram lagi, hapus bit WS_EX_LAYERED dengan memanggil SetWindowLong lalu minta jendela untuk mengecat ulang. Menghapus bit diinginkan untuk memberi tahu sistem bahwa ia dapat membebaskan beberapa memori yang terkait dengan lapisan dan pengalihan. Kode mungkin terlihat seperti ini:
// 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);
Untuk menggunakan jendela anak berlapis, aplikasi harus mendeklarasikan dirinya Windows 8-aware dalam manifes.
Untuk windows 10/11, seseorang dapat menyertakan cuplikan kompatibilitas ini di dalamnya app.manifest
untuk membuatnya sadar Windows 10 :
...
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 GUID -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
...
Selengkapnya tentang memodifikasi manifes aplikasi dapat dibaca di sini: Manifes aplikasi