Programın çalışmaya devam etmesi ve kullanıcının ana program penceresi ile işlem yapabilmesi için, kullanıcının modal diyalog kutusu ile ilgili işlemleri gerçekleştirip kutuyu kapatması veya iptal etmesi gerekir. Uygulamalar modal diyalog kutularını bir menü seçeneği tıklandığında ek bilgi elde etmek üzere kullanırlar.
Modal diyalog kutuları DialogBox() fonksiyonu ile oluşturulur.
Modal diyalog kutusu açık kaldığı sürece, kullanıcının ana program penceresi ile işlem yapabilmesi mümkün değildir.
Modal diyalog kutusu, bir pencere menüsü, bir başlık çubuğu ve kalın bir sınır çizgisi olan bir açılır penceredir. Bu özellikleri içermesi içn modal diyalog kutusu WS_POPUP, WS_SYSMENU, WS_CAPTION, ve DS_MODALFRAME özellikleri ile tanımlanmalıdır. Diyalog kutusu kendi kendisini devre dışı bırakmasına neden olacak WS_CHILD özelliği ile tanımlanmamalıdır.
Diyalog kutularını oluşturmak için öncelikle programı oluşturan proje altında bir resource dosyası ve bununla birlikte çalışan bir başlık dosyası tanımlamak gerekir.
Resource dosyası bir Windows uygulamasının .exe uzantılı dosyasına eklenmek üzere oluşturulan bir ikili sistem veri dosyasıdır. Uygulamalar, resource dosyaları .exe dosyalara direk olarak kopya ederek veya derledikten sonra ekleyebilirler.
Windows uygulamalarına resource içeriği eklemek için:
Şimdiye kadar kullandığımız proje içine aşağıda gösterildiği şekilde resource.rc ve resource.h adlı 2 adet dosya eklemeye çalışalım:
1. Code::Blocks IDE içinde proje açık iken aşağıdaki resimde gösterilen File-New-Empty File menü seçeneğine tıklayın:
2. Karşınıza gelen pencereden "Evet" butonuna basın.
3. Kayıt türü bölümünden "Windows resource files" seçeneğini seçin:
4. Dosya adı bölümüne "resource.rc" ifadesini yazın:
5. Karşınıza gelen pencereden "OK" butonuna basın.
6. Code::Blocks IDE içinde projenin görünümü aşağıdaki resimde gösterildiği hale gelir:
Bu işlem için bir önceki dosyayı oluşturmak için gösterilen aşamaların aynısı gerçekleştirilir. Sadece, 4 ncü safhada farklı işlem yapılır.
4. Kayıt türü bölümünden "All files(*.*) seçeneğini seçin, Dosya adı bölümüne "resource.h" ifadesini yazın:
Artık, projede aşağıda gösterilen 3 adet dosya vardır:
Projemize diyalog kutularını ve diğer bildirimleri ekleyebiliriz.
Uygulamalar bir modal diyalog kutusu oluşturmak için aşağıdaki fonksiyonlardan birini kullanır:
DialogBox(): Bu fonksiyon, bir resource dosyası içinde yer alan bir diyalog kutusu şablonunun adını veya tanımlayıcısını kullanarak bir modal diyalog kutusu oluşturur.
DialogBoxIndirect(): Bu fonksiyon, bir diyalog kutusu şablonunu içeren bir bellek nesnesinin Handle değerini kullanarak bir modal diyalog kutusu oluşturur.
Modal bir diyalog kutusu oluşturulduğunda, sistem kutuyu aktif pencere olarak belirler. Diyalog kutusu mesaj işlem fonksiyonu EndDialog() fonksiyonunu çağırana veya sistem başka bir uygulamanın penceresini aktif hale getirene kadar, diyalog kutusu aktif olarak kalır. Diyalog kutusu kapatılmadığı sürece diyalog kutusunu barındıran ana program penceresi aktif hale gelmez.
Modal diyalog kutusu devreye girdiğinde, diyalog kutusu mesaj işlem fonksiyonu kullanıcı tarafından yapılan girişlere gerekli işlemleri yapmak üzere devreye girer. Diyalog kutusu mesaj işlem fonksiyonu, program ana pencere mesaj işlem fonksiyonuna benzer, ancak aşağıda gösterilen özelliklerde farklılıklar gösterir:
Bütün diyalog kutusu mesaj işlem fonksiyonlarının genel yapısı aşağıdaki şekildedir:
BOOL CALLBACK DlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// Diğer mesajlar
default:
return FALSE;
}
}
Şimdi, programımıza bir modal diyalog kutusu eklemeye çalışalım:
resource.rc
#include "resource.h"
IDD_VERIBOX DIALOG 70, 10, 200, 60
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Ana Başlık Değiştirme"
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_EDIT, 10, 10, 180, 14
DEFPUSHBUTTON "&OK", IDOK, 30, 35, 50, 14
PUSHBUTTON "&Cancel", IDCANCEL, 120, 35, 50, 14
END
IDR_MENU MENU
BEGIN
POPUP "&İşlemler"
BEGIN
MENUITEM "&Başlık değiştirme", IDM_BASLIK_DEG
MENUITEM "&Çıkış", IDM_CIKIS
END
END
.rc uzantılı bir resource metin dosyasında kullanılan ifadeler 3 gruba ayrılır:
resource.rc dosyasında, IDD_VERIBOX tanımlayıcısı ve DIALOG ifadesi ile bir adet diyalog kutusu ve IDR_MENU tanımlayıcısı ve MENU ifadesi ile bir adet menü tanımlanmıştır. Daha önce, menü tanımlamalarını direk olarak main.c dosyası içinde tanımlamıştık.
Diyalog kutusu içinde, STYLE, CAPTION ve FONT ifadeleri ile diyalog özellikleri, EDITTEXT, DEFPUSHBUTTON ve PUSHBUTTON ifadeleri ile diyalog kutusu içinde bir adet EDIT ve 2 adet BUTTON kontrolu bildirimi yapılmıştır.
Menü tanımlaması içinde, POPUP ifadesi ile açılır bir menü ve bu menü altında MENUITEM ifadeleri ile 2 adet menü seçeneği tanımlanmıştır.
DIALOG, EDITTEXT, DEFPUSHBUTTON ve PUSHBUTTON ifadeleri ile birlikte kullanılan 4 sayının ilki x koordinat, ikincisi y koordinat, üçüncüsü genişlik ve dördüncüsü yükseklik değerlerini göstermektedir. Değerler piksel değil FONT ifadesi ile birlikte kullanılan büyüklük değerine bağlı olarak değişen büyüklüklerdir.
resource.h
#include <windows.h>
#define IDD_VERIBOX 301
#define IDR_MENU 401
#define IDC_STATIC01 101
#define IDC_EDIT 201
#define IDM_BASLIK_DEG 11
#define IDM_CIKIS 12
Resource dosya kullanımı ile birlikte, önceden main.c dosyası içindeki makroların tanımı artık resource.h dosyası içinde yapılmaktadır. Ayrıca, resource.rc dosyası içinde kullanılan makroların tanımları da burada yapılmaktadır.
main.c
Aşağıdaki ilk 2 satır programın başına global değerler olarak eklenir. Son satır ise, WinMain() fonksiyonu içindeki pencere sınıf bildiriminin menüsünü belirlemek üzere eklenir.
#include "resource.h"
char cdizi[200];
wincl.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); /* Menünün ana pencereye atanması */
WindowProcedure() fonksiyonu içinde renkli olarak gösterilen satırlar ile WM_COMMAND mesajına işlem yapılarak IDM_BASLIK_DEG menü seçeneği ile modal bir diyalog kutusu oluşturulur.
Ayrıca, modal diyalog kutusuna gelen mesajlara işlem yapmak üzere, WndProcDlg() isimli mesaj işlem fonksiyonu oluşturulur.
LRESULT CALLBACK WindowProcedure (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
hwndStatic01 = CreateWindowEx(0, "STATIC", "Statik kontrol",
WS_CHILD | WS_VISIBLE | SS_LEFT, 20, 180, 500, 20,
hwnd, (HMENU) IDC_STATIC01, NULL, NULL);
break;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_BASLIK_DEG:
if (DialogBox(ghInst, MAKEINTRESOURCE(IDD_VERIBOX), hwnd,
(DLGPROC)WndProcDlg)==IDOK) {
SetWindowText(hwnd, cdizi);
SetWindowText(hwndStatic01, "Pencere başlığı değiştirildi.");
}
else {
SetWindowText(hwndStatic01, "Başlık değiştirme iptal edildi.");
}
break;
case IDM_CIKIS:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
BOOL CALLBACK WndProcDlg(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SetWindowText(hwndStatic01, "Diyalog penceresi oluşturuldu.");
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (!GetDlgItemText(hwndDlg, IDC_EDIT, cdizi, 200)) *cdizi=0;
case IDCANCEL:
EndDialog(hwndDlg, wParam);
return TRUE;
}
break;
}
return FALSE;
}
Bildirimi winuser.h dosyası içinde yapılan ve bir tamsayı değeri resource tipinde bir değere çeviren MAKEINTRESOURCE makrosunun tanımı aşağıdaki ilk satırda genel yapısı ise ikinci satırda verilmiştir:
#define MAKEINTRESOURCE(i) (LPSTR)((DWORD)((WORD)(i)))
LPTSTR MAKEINTRESOURCE (WORD wInteger);
wInteger parametresi çevirilecek değeri gösterir.
Program derleme safhasında resource.rc dosyası derlenerek elde edilen resource.res dosyası .exe dosyaya eklenir.
Program çalıştığında:
Programın çalışan en son halinde yer alan dosyalar aşağıdadır:
resource.rc
#include "resource.h"
IDD_VERIBOX DIALOG 70, 10, 200, 60
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Ana Başlık Değiştirme"
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_EDIT, 10, 10, 180, 14
DEFPUSHBUTTON "&OK", IDOK, 30, 35, 50, 14
PUSHBUTTON "&Cancel", IDCANCEL, 120, 35, 50, 14
END
IDR_MENU MENU
BEGIN
POPUP "&İşlemler"
BEGIN
MENUITEM "&Başlık değiştirme", IDM_BASLIK_DEG
MENUITEM "&Çıkış", IDM_CIKIS
END
END
resource.h
#include <windows.h>
#define IDD_VERIBOX 301
#define IDR_MENU 401
#define IDC_STATIC01 101
#define IDC_EDIT 201
#define IDM_BASLIK_DEG 11
#define IDM_CIKIS 12
main.c
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK WndProcDlg(HWND, UINT, WPARAM, LPARAM);
char szClassName[ ] = "WinAPIWindowsApp";
HINSTANCE ghInst;
char cdizi[200];
HWND hwndStatic01;
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
HWND hwndMain;
MSG messages;
WNDCLASSEX wincl;
ghInst = hThisInstance;
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
if (!RegisterClassEx (&wincl)) return 0;
hwndMain = CreateWindowEx (0, szClassName, "WinAPI Temel Program",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
if (!hwndMain) return 0;
ShowWindow (hwndMain, nCmdShow);
UpdateWindow(hwndMain);
while (GetMessage (&messages, NULL, 0, 0) > 0) {
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
LRESULT CALLBACK WindowProcedure (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
hwndStatic01 = CreateWindowEx(0, "STATIC", "Statik kontrol",
WS_CHILD | WS_VISIBLE | SS_LEFT, 20, 180, 500, 20,
hwnd, (HMENU) IDC_STATIC01, NULL, NULL);
break;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_BASLIK_DEG:
if (DialogBox(ghInst, MAKEINTRESOURCE(IDD_VERIBOX), hwnd,
(DLGPROC)WndProcDlg)==IDOK) {
SetWindowText(hwnd, cdizi);
SetWindowText(hwndStatic01, "Pencere başlığı değiştirildi.");
}
else {
SetWindowText(hwndStatic01, "Başlık değiştirme iptal edildi.");
}
break;
case IDM_CIKIS:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
BOOL CALLBACK WndProcDlg(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
SetWindowText(hwndStatic01, "Diyalog penceresi oluşturuldu.");
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (!GetDlgItemText(hwndDlg, IDC_EDIT, cdizi, 200)) *cdizi=0;
case IDCANCEL:
EndDialog(hwndDlg, wParam);
return TRUE;
}
break;
}
return FALSE;
}
Program çalıştığında karşınıza gelecek ekran görüntüsü aşağıdadır: