Windows API

Modeless Diyalog Kutuları

► Diyalog Kutuları

Modeless diyalog kutusu açık kalsa bile kullanıcı ana program penceresi ile ilgili işlemleri yapabilir.

Modeless diyalog kutusu, bir pencere menüsü, bir başlık çubuğu ve ince bir sınır çizgisi olan bir açılır penceredir. Bu özellikleri içermesi içn modeless diyalog kutusu WS_POPUP, WS_SYSMENU, WS_CAPTION, ve WS_BORDER özellikleri ile tanımlanmalıdır. WS_VISIBLE özelliği ile tanımlanmadığı sürece, sistem diyalog kutusunu otomatik olarak ekranda göstermez.

Uygulamalar bir modeless diyalog kutusu oluşturmak için aşağıdaki fonksiyonlardan birini kullanır:

CreateDialog(): Bu fonksiyon, bir resource dosyası içinde yer alan bir diyalog kutusu şablonunun adını veya tanımlayıcısını kullanarak bir modeless diyalog kutusu oluşturur.

CreateDialogIndirect(): Bu fonksiyon, bir diyalog kutusu şablonunu içeren bir bellek nesnesinin Handle değerini kullanarak bir modeless diyalog kutusu oluşturur.

CreateDialog() veya CreateDialogIndirect() fonksiyonları modeless bir diyalog kutusu oluşturduklarında, dialog kutusuna ait bir pencere Handle değeri geri döndürürler. Programlar, bu Handle değerini ShowWindow() fonksiyonuna geçirerek diyalog kutusunu ekranda gösterirler.

Modeless bir diyalog kutusu ana penceresini devre dışı bırakmaz ve mesaj yollamaz. Diyalog kutusu oluşturulduğunda, sistem kutuyu aktif pencere olarak belirler, kullanıcı veya sistem aktif pencereyi istediği zaman değiştirebilir. Diyalog kutusu aktif özelliğini kaybetse bile, ana program penceresinin üzerinde kalır.

Program, kullanıcı tarafından yapılan giriş işlemlerine karşılık olarak oluşturulan mesajları alma ve diyalog kutusuna iletme işini yürütürler. Uygulamalar genelde bu işlem için ana mesaj döngüsünü kullanırlar. Kullanıcının diyalog kutusu üzerindeki kontroller arasında klavye ile hareket etmek ve işlem yapmak için IsDialogMessage() fonksiyonu kullanılır.

Modeless diyalog kutusu, programa bir değer geri döndürmez, ancak diyalog kutusu mesaj işlem fonksiyonu SendMessage() fonkisyonu ile ana pencereye bilgi gönderebilir.

Uygulamalar sona ermeden önce DestroyWindow() fonksiyonunu kullanarak bütün modeless diyalog kutularını yok etmelidir. Genel olarak, diyalog kutusu mesaj işlem fonksiyonu içinde iptal içerikli kullanıcı girişlerine karşılık olarak DestroyWindow() fonksiyonu ile diyalog kutuları yok edilir, ancak diyalog kutularının yok edilmediği durumlar göz önüne alınarak uygulamaların DestroyWindow() fonksiyonunu çağırması gerekir.

Diyalog kutusu kendini yok ettiğinde, diyalog kutusuna tahsis edilen global bir pencere Hanle değerine NULL değeri atanır.

Diyalog kutusu mesaj işlem fonksiyonu modeless bir diyalog kutusunu yok etmek için EndDialog() fonksiyonunu çağırmaz.

  • Diyalog kutusu DefWindowProc() fonksiyonunu çağırmaz. Bunun yerine, mesajlara işlem yaptığında TRUE, yapmadığında ise FALSE bir değer geri verir.
  • Sistem, diyalog kutusu mesaj işlem fonksiyonuna WM_CREATE mesajı yollamaz. Bunun yerine, diyalog kutusunu oluşturduğunda, WM_INITDIALOG mesajı gönderir.

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 modeless bir diyalog kutusu eklemeye çalışalım:

resource.rc ve resource.h dosyaları, modal diyalog kutusu oluşturmada kullandığımız dosyalarla aynıdır.

main.c

Aşağıdaki ilk satır programın başına global değer olarak eklenir. Diğer satırlarda yer alan ana program mesaj döngüsünde, diyalog kutusu açık değilse (IsWindow() fonksiyonu ile kontrol edilir) veya mesaj diyalog kutusu ile ilgili değilse (IsDialogMessage() fonksiyonu ile kontrol edilir), mesaj ana pencere veya mevcutsa diğer pencerelerin mesaj işlem fonksiyonlarına gönderilir.

HWND hwndDialog = NULL;

while (GetMessage (&messages, NULL, 0, 0) > 0) {
   if (!IsWindow(hwndDialog) || !IsDialogMessage(hwndDialog, &messages)) {
       TranslateMessage(&messages);
       DispatchMessage(&messages);
   }
}	

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 altında CreateDialog() fonksiyonu ile modeless bir diyalog kutusu oluşturulur ve ShowWindow() fonksiyonu ile ekranda gösterilir.

Ayrıca, modeless 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 (!IsWindow(hwndDialog)) {
                     hwndDialog = CreateDialog (ghInst, MAKEINTRESOURCE(IDD_VERIBOX), 
                                                hwnd, (DLGPROC)WndProcDlg);
                     ShowWindow(hwndDialog, SW_SHOW);
                 } 
                 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."); 
          return TRUE;
		  
     case WM_COMMAND: 
          switch (LOWORD(wParam)) { 
             case IDOK: 
                if (!GetDlgItemText(hwndDlg, IDC_EDIT, cdizi, 200)) *cdizi=0; 
                SetWindowText(GetWindow(hwndDlg, GW_OWNER), cdizi);
                SetWindowText(hwndStatic01, "Ana pencere başlığı değiştirildi.");
                return TRUE;
 
             case IDCANCEL: 
                DestroyWindow(hwndDlg);
                SetWindowText(hwndStatic01, "Başlık değiştirme iptal edildi.");
                hwndDialog = NULL;
                return TRUE; 
          } 
          break;
  } 
  return FALSE; 
}

Program derleme safhasında resource.rc dosyası derlenerek elde edilen resource.res dosyası .exe dosyaya eklenir.

Program çalıştığında:

  • Program ana penceresi oluşturulmadan önce, MAKEINTRESOURCE(IDR_MENU) komutu ile resource dosya içinde bildirimi yapılan menü ana pencereye atanır.
  • Program penceresi oluşturulur oluşturulmaz WM_CREATE mesajı mesaj işlem fonksiyonuna gönderilir. switch yapısının bu seçeneği altında CreateWindowEx() fonksiyonu ile bir adet Static kontrol oluşturulur.
  • IDM_BASLIK_DEG menü seçeneği tıklandığında, modeless bir diyalog kutusu oluşturulur. Eğer diyalog kutusundaki Edit kontrolu içine bir karakter dizisi girilir ve OK tuşuna basılırsa, girilen karakter dizisi program ana pencere başlığı yerine yazılır.
  • Ayrıca, diyalog kutusu oluşturulduğunda WM_INITDIALOG mesajı ve diyalog kutusu ile yapılan işlem mesajları WndProcDlg() fonksiyonuna gönderilir. İşlemlerle ilgili bilgiler Static kontrol penceresine yazılır.
    • IDOK seçeneği altında GetWindow() fonksiyonu ile ana pencere Handle değeri alınarak, ana pencere başlığı değiştirilir.
    • IDCANCEL seçeneği altında diyalog penceresi yok edilerek, diyalog penceresi global Handle değerine NULL bir değer atanır.

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 hwndDialog = NULL;
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) {
    if (!IsWindow(hwndDialog) || !IsDialogMessage(hwndDialog, &messages)) {
        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 (!IsWindow(hwndDialog)) {
                     hwndDialog = CreateDialog (ghInst, MAKEINTRESOURCE(IDD_VERIBOX), 
                                                hwnd, (DLGPROC)WndProcDlg);
                     ShowWindow(hwndDialog, SW_SHOW);                     
                 } 
                 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."); 
          return TRUE;
		  
     case WM_COMMAND: 
          switch (LOWORD(wParam)) { 
             case IDOK: 
                if (!GetDlgItemText(hwndDlg, IDC_EDIT, cdizi, 200)) *cdizi=0; 
                SetWindowText(GetWindow(hwndDlg, GW_OWNER), cdizi); 
                SetWindowText(hwndStatic01, "Ana pencere başlığı değiştirildi.");
                return TRUE;
 
             case IDCANCEL: 
                DestroyWindow(hwndDlg);
                SetWindowText(hwndStatic01, "Başlık değiştirme iptal edildi.");
                hwndDialog = NULL; 
                return TRUE; 
          } 
          break;
  } 
  return FALSE; 
}

Program çalıştığında karşınıza gelecek ekran görüntüsü aşağıdadır: