Windows API

Menüler

Menü, bir program içinde kullanıcı tarafından seçilmek üzere ve seçildiğinde belirli işlemler yapılan bir seçenek listesidir. Kullanıcı bir menü seçeneğine tıkladığında, program bir komutu yerine getirir veya bir alt menü açar.

Program menü sisteminde, en üst seviyede bir ana menü yer alır. Ana menüde yer alan menü seçenekleri içinde de tekrar alt menüler yer alabilir. Tıklandığında bir komut yerine getiren menü seçenekleri komut seçeneği olarak isimlendirilir.

Ana menü içinden tıklandığında açılan alt menülere açılır menü adı verilir. Ana menü altında açılan bu menüler içinde de ana menü içinde bulunan seçenekler yer almaktadır.

Şimdi, programımıza bir ana menü ve bir fare sağ tuş menüsü eklemeye çalışalım:

Aşağıdaki satırlar programın başına global değerler olarak eklenir:

/* Ana ve sağ fare tuşu menüsü için tanımlayıcı makro bildirimleri */
#define IDM_DOSYA_YENI 11
#define IDM_DOSYA_AC 12
#define IDM_DOSYA_KAYDET 13
#define IDM_DOSYA_CIKIS 14

#define IDM_DUZEN_KES 21
#define IDM_DUZEN_KOPYALA 22
#define IDM_DUZEN_YAPISTIR 23
#define IDM_DUZEN_SIL 24

/* Ana ve sağ fare tuşu menüsü için Handle değerleri */
HMENU hMenuAna, hMenuAlt01, hMenuAlt02;
HMENU hMenuPopup;

WindowProcedure() fonksiyonu içinde renkli olarak gösterilen satırlar ile bir ana menü ve bir fare sağ tuş menüsü oluşturulur. WM_COMMAND mesajına işlem yapılarak menü seçenekleri ile ilgili işlemler belirlenir:

LRESULT CALLBACK WindowProcedure (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
  POINT point;
  
  switch (message)
  { 
    case WM_CREATE:

         hwndStatic01 = CreateWindowEx(0, "STATIC", "Statik kontrol",
                                WS_CHILD | WS_VISIBLE | SS_LEFT, 20, 120, 300, 20,
                                hwnd, (HMENU) IDC_STATIC01, NULL, NULL);
	
         hMenuAna = CreateMenu();
         hMenuAlt01 = CreateMenu();
         hMenuAlt02 = CreateMenu();

         AppendMenu(hMenuAlt01, MF_STRING, IDM_DOSYA_YENI, "&Yeni");
         AppendMenu(hMenuAlt01, MF_STRING, IDM_DOSYA_AC, "&Aç");
         AppendMenu(hMenuAlt01, MF_STRING, IDM_DOSYA_KAYDET, "&Kaydet");
         AppendMenu(hMenuAlt01, MF_STRING, IDM_DOSYA_CIKIS, "&Çıkış");
         AppendMenu(hMenuAna, MF_POPUP, (UINT_PTR)hMenuAlt01, "&Dosya");

         AppendMenu(hMenuAlt02, MF_STRING, IDM_DUZEN_KES, "&Kes");
         AppendMenu(hMenuAlt02, MF_STRING, IDM_DUZEN_KOPYALA, "&Kopyala");
         AppendMenu(hMenuAlt02, MF_STRING, IDM_DUZEN_YAPISTIR, "&Yapıştır");
         AppendMenu(hMenuAlt02, MF_STRING, IDM_DUZEN_SIL, "&Sil");
         AppendMenu(hMenuAna, MF_POPUP, (UINT_PTR)hMenuAlt02, "&Düzen");

         SetMenu(hwnd, hMenuAna);
		 
         hMenuPopup = CreatePopupMenu(); 		 

         AppendMenu(hMenuPopup, MF_STRING, IDM_DOSYA_YENI, "&Yeni");
         AppendMenu(hMenuPopup, MF_STRING, IDM_DOSYA_AC, "&Aç");
         AppendMenu(hMenuPopup, MF_STRING, IDM_DOSYA_KAYDET, "&Kaydet");
         AppendMenu(hMenuPopup, MF_STRING, IDM_DOSYA_CIKIS, "&Çıkış");
		 
         break;

    case WM_COMMAND:

         switch(LOWORD(wParam)) {
             case IDM_DOSYA_YENI:
                 SetWindowText(hwndStatic01, "Yeni dosya açıldı.");
                 break;			 
             case IDM_DOSYA_AC:
                 SetWindowText(hwndStatic01, "Bir dosya açıldı.");
                 break;			 
             case IDM_DOSYA_KAYDET:
                 SetWindowText(hwndStatic01, "Dosya kaydedildi.");
                 break;
             case IDM_DOSYA_CIKIS:
                 SendMessage(hwnd, WM_CLOSE, 0, 0);
                 break;
             case IDM_DUZEN_KES:
                 SetWindowText(hwndStatic01, "Kesme işlemi gerçekleştirildi.");
                 break;			 
             case IDM_DUZEN_KOPYALA:
                 SetWindowText(hwndStatic01, "Kopyalama işlemi gerçekleştirildi.");
                 break;			 
             case IDM_DUZEN_YAPISTIR:
                 SetWindowText(hwndStatic01, "Yapıştırma işlemi gerçekleştirildi.");
                 break;
             case IDM_DUZEN_SIL:
                 SetWindowText(hwndStatic01, "Silme işlemi gerçekleştirildi.");
                 break;				 
         }
		   
         break;
		  
    case WM_RBUTTONUP:
	
         point.x = LOWORD(lParam);
         point.y = HIWORD(lParam);
         ClientToScreen(hwnd, &point);
         TrackPopupMenu(hMenuPopup, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
         
         break;
		 
    case WM_DESTROY:
         PostQuitMessage (0);
         break;
		 
    default:                 
         return DefWindowProc (hwnd, message, wParam, lParam);
  }

  return 0;
}

WM_COMMAND : 273 sayı değerine karşılık gelen mesaj, aşağıdaki 3 işlemden birisi gerçekleştiğinde oluşturulur:

1. Bir kontrol ana penceresine bir bildirim mesajı gönderdiğinde,

2. Kullanıcı bir menüden bir seçenek seçtiğinde,

3. Bir kısayol tuşuna basıldığında

lParam ve wParam parametreleri yukarıdaki seçeneklere göre farklı değerler alır.

Bir kontrolün ana penceresine bir bildirim göndermesi durumunda, wParam parametresinin üst WORD değeri (HIWORD(wParam)) kontrol tanımlı bildirim kodunu, alt WORD değeri (LOWORD(wParam)) kontrol tanımlayıcı değerini içerir. lParam parametresi ise kontrol pencere Handle değerini içerir.

Bir menü seçeneği seçildiğinde, wParam parametresinin üst WORD değeri sıfır, alt WORD değeri menü tanımlayıcısını (IDM_*) içerir. lParam parametresi ise sıfır değerini içerir.

Kısayol tuşuna basıldığında, wParam parametresinin üst WORD değeri 1, alt WORD değeri kısayol tuşu tanımlayıcısını (IDM_*) içerir. lParam parametresi ise sıfır değerini içerir.

Dönüş değeri

Eğer program bu mesaja işlem yaparsa, sıfır değeri geri vermesi gerekir.

WM_RBUTTONUP : 517 sayı değerine karşılık gelen mesaj kullanıcı pencere kullanım alanında fare sağ tuşunu bıraktığında oluşturulur. wParam parametresi SHIFT ve CTRL tuşları ile fare tuşlarının basılı olup olmadığını gösterir ve bu değerlerin birleşiminden oluşabilir. lParam parametresinin düşük word değeri pencere kullanım alanının sol üst köşesine göre farenin x koordinatını ve yüksek word değeri y koordinatını gösterir.

Program çalıştığında:

  • 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.
  • CreateMenu() fonksiyonu ile bir ana menü ve bu ana menü altında 2 adet alt menü oluşturulur.
  • AppendMenu() fonksiyonu ile hMenuAlt01 ve hMenuAlt02 menülerine 4'er adet seçenek ve menüler ana menüye eklenir.
  • SetMenu() fonksiyonu ile hMenuAna ana menüsünü program ana penceresine atar.
  • CreatePopupMenu() fonksiyonu ile hMenuPopup adlı bir fare sağ tuş menüsü oluşturulur ve AppendMenu() fonksiyonu ile hMenuAlt01 menüsü seçeneklerinin aynısı yeni menüye eklenir.
  • Ana menü veya sağ fare tuşu menüaü seçenekleri tarafından ana pencereye gönderilen bildirim mesajlarına işlem yapmak üzere ana pencere mesaj işlem fonksiyonu içinde oluşturulan WM_COMMAND seçeneği altında menü seçeneklerine uygun olarak Static kontrol penceresine bir metin yazılır:
  • WM_RBUTTONUP seçeneği altında:
    • lParam ve wParam parametrelerinde bulunan fare koordinat değerleri POINT yapı elemanlarına aktarılır.
    • ClientToScreen() fonksiyonu ile program penceresine göre elde edilen koordinatlar ekran koordinatlarına çevrilir.
    • Kullanıcı sağ fare tuşuna bastığında, TrackPopupMenu() fonksiyonu ile tanımlanan koordinatlarda sağ fare tuşu menüsü ekranda gösterilir ve hangi menü seçeneğine tıklandığı takip edilir.

Programın çalışan en son hali aşağıdadır:

#include <windows.h>

#define IDC_STATIC01 101
#define IDM_DOSYA_YENI 11
#define IDM_DOSYA_AC 12
#define IDM_DOSYA_KAYDET 13
#define IDM_DOSYA_CIKIS 14

#define IDM_DUZEN_KES 21
#define IDM_DUZEN_KOPYALA 22
#define IDM_DUZEN_YAPISTIR 23
#define IDM_DUZEN_SIL 24

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

char szClassName[ ] = "WinAPIWindowsApp";
HINSTANCE ghInst;

HWND hwndStatic01;
HMENU hMenuAna, hMenuAlt01, hMenuAlt02;
HMENU hMenuPopup;

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 = NULL; 
  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)
{
  POINT point;
  
  switch (message)
  { 
    case WM_CREATE:

         hwndStatic01 = CreateWindowEx(0, "STATIC", "Statik kontrol",
                                WS_CHILD | WS_VISIBLE | SS_LEFT, 20, 120, 300, 20,
                                hwnd, (HMENU) IDC_STATIC01, NULL, NULL);
	
         hMenuAna = CreateMenu();
         hMenuAlt01 = CreateMenu();
         hMenuAlt02 = CreateMenu();

         AppendMenu(hMenuAlt01, MF_STRING, IDM_DOSYA_YENI, "&Yeni");
         AppendMenu(hMenuAlt01, MF_STRING, IDM_DOSYA_AC, "&Aç");
         AppendMenu(hMenuAlt01, MF_STRING, IDM_DOSYA_KAYDET, "&Kaydet");
         AppendMenu(hMenuAlt01, MF_STRING, IDM_DOSYA_CIKIS, "&Çıkış");
         AppendMenu(hMenuAna, MF_POPUP, (UINT_PTR)hMenuAlt01, "&Dosya");

         AppendMenu(hMenuAlt02, MF_STRING, IDM_DUZEN_KES, "&Kes");
         AppendMenu(hMenuAlt02, MF_STRING, IDM_DUZEN_KOPYALA, "&Kopyala");
         AppendMenu(hMenuAlt02, MF_STRING, IDM_DUZEN_YAPISTIR, "&Yapıştır");
         AppendMenu(hMenuAlt02, MF_STRING, IDM_DUZEN_SIL, "&Sil");
         AppendMenu(hMenuAna, MF_POPUP, (UINT_PTR)hMenuAlt02, "&Düzen");

         SetMenu(hwnd, hMenuAna);
		 
         hMenuPopup = CreatePopupMenu(); 		 

         AppendMenu(hMenuPopup, MF_STRING, IDM_DOSYA_YENI, "&Yeni");
         AppendMenu(hMenuPopup, MF_STRING, IDM_DOSYA_AC, "&Aç");
         AppendMenu(hMenuPopup, MF_STRING, IDM_DOSYA_KAYDET, "&Kaydet");
         AppendMenu(hMenuPopup, MF_STRING, IDM_DOSYA_CIKIS, "&Çıkış");
		 
         break;

    case WM_COMMAND:

         switch(LOWORD(wParam)) {
             case IDM_DOSYA_YENI:
                 SetWindowText(hwndStatic01, "Yeni dosya açıldı.");
                 break;			 
             case IDM_DOSYA_AC:
                 SetWindowText(hwndStatic01, "Bir dosya açıldı.");
                 break;			 
             case IDM_DOSYA_KAYDET:
                 SetWindowText(hwndStatic01, "Dosya kaydedildi.");
                 break;
             case IDM_DOSYA_CIKIS:
                 SendMessage(hwnd, WM_CLOSE, 0, 0);
                 break;
             case IDM_DUZEN_KES:
                 SetWindowText(hwndStatic01, "Kesme işlemi gerçekleştirildi.");
                 break;			 
             case IDM_DUZEN_KOPYALA:
                 SetWindowText(hwndStatic01, "Kopyalama işlemi gerçekleştirildi.");
                 break;			 
             case IDM_DUZEN_YAPISTIR:
                 SetWindowText(hwndStatic01, "Yapıştırma işlemi gerçekleştirildi.");
                 break;
             case IDM_DUZEN_SIL:
                 SetWindowText(hwndStatic01, "Silme işlemi gerçekleştirildi.");
                 break;				 
         }
		   
         break;
		  
    case WM_RBUTTONUP:
	
         point.x = LOWORD(lParam);
         point.y = HIWORD(lParam);
         ClientToScreen(hwnd, &point);
         TrackPopupMenu(hMenuPopup, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
         
         break;
		 
    case WM_DESTROY:
         PostQuitMessage (0);
         break;
		 
    default:                 
         return DefWindowProc (hwnd, message, wParam, lParam);
  }

  return 0;
}

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