Windows Formunda sistem menüsünü yönetmek

C#, VB.NET, ASP.NET Add comments

Windows ortamında geliÅŸtirdiÄŸimiz desktop tabanlı exe programındaki her formun task barında standart pencere yönetim menüsü çıkar. Pencerenin ikonu tıklandığında, title bar veya taskbar saÄŸ tıklandığında görünen bu sistem menüsü formun türüne göre farklılık gösterse de genellikle, Restore, Move, Size, Minimize, Maximize ve Close eventleri içerir. Uygulamalarımızda bu menüyü yönetmek isteyebiliriz örneÄŸin oradaki default menüden bazılarını disable etme ihtiyacı doÄŸabilir veya birçok programda gördüğümüz “About” bölümünü ekleyebiliriz. Sistem menüsünü yönetmek için .NET plaftormunda özel bir kütüphane bulunmamaktadır. Bunu saÄŸlamak için Windows API’si kullanılır.
Sistem menüsü yönetimi için Windows API’sindeki GetSystemMenu() fonksiyonu çaÄŸrılır. Bu fonskiyon, çalışan pencereye ait System Menu’nun kopyasını döndürür. Bu menü üzerinde deÄŸiÅŸiklik veya ekleme yapmak için AppendMenu(), InsertMenu() metodları kullanılır. user32.dll API’sini projeye dahil edip ilgili fonksiyonları kullanalım.

using System.Runtime.InteropServices;
...
[DllImport("user32.dll")]
private static extern int GetSystemMenu(int hwnd, int bRevert);

[DllImport("user32.dll")]
private static extern int AppendMenu(int hMenu, int Flagsw, int IDNewItem, string lpNewItem);

private void Form1_Load(object sender, EventArgs e)
{
    //System menu'sünü handle edelim
    int systemMenu = GetSystemMenu(this.Handle.ToInt32(), 0);

    //Bir separator ekleyelim
    AppendMenu(systemMenu, 0xA00, 0, null);

    //Hakkında menüsünü ekleyelim
    AppendMenu(systemMenu, 0, 100, "&Hakkında");
}//Form1_Load

Menüdeki “Hakkında” bölümüne ait bir click event yazmak için WndProc() metodu override edilir. Bu metod, menüden gelecek mesajları dinler. Gelen mesaj, “Hakkında” bölümüyle ilgiliyse bunu Hakkinda_Click metoduyla iliÅŸkilendirilir. Aslında bu bölümde açıklama yapılacak bir durum olmadığı için doÄŸrudan kodu vermemiz daha yönlendirici olacaktır.

protected override void WndProc(ref System.Windows.Forms.Message m)
{
    base.WndProc(ref m);

    if (m.Msg == 0x112) // WM_SYSCOMMAND
        WmSysCommand(m.WParam.ToInt32());
}//WndProc

private void WmSysCommand(int wParam)
{
    if (wParam == 100) //Menüye ait ID bilgisi
    {
        Hakkinda_Click(this, new EventArgs());
    }
}//WmSysCommand

private void Hakkinda_Click(object sender, System.EventArgs e)
{
    MessageBox.Show("Hakkında Bölümü");
}//Hakkinda_Click

Penceredeki Close buttonunu disable etmek
Konuyla ilgili olarak en çok ihtiyaç duyulan iÅŸlemlerden biri de sistem menüsündeki “X Close” bölümünü kapatmaktır. .NET’teki Form class’ının ControlBox property’sini false olarak set edebiliriz ancak bu durumda maximize, minimize buttonlarını da görünmez yapmış oluruz. Sistem menüsünden bir bölümü kaldırmak için API’nin RemoveMenuItem() metodu kullanılır. Bu metoda parametre olarak disable edilecek item’in index numarası verilir. “Close” bölümü, menünün en son elemanı olduÄŸu için menünün eleman sayısının 1 eksiÄŸi bu menünün indexini verecektir. Menünün item sayısını GetMenuItemCount() fonksiyonunu döndürür. Disable, remove iÅŸlemi yapıldıktan sonra menüyü yeniden oluÅŸturmak için DrawMenuBar() metodu kullanılır.

[DllImport("user32")]
public static extern int GetMenuItemCount(int systemMenu);

[DllImport("user32")]
public static extern int RemoveMenu(int systemMenu, int itemPosition, int flag);

[DllImport("user32")]
public static extern int DrawMenuBar(int currentWindow);

private void Form1_Load(object sender, EventArgs e)
{
    //System menu'sünü handle edelim
    int systemMenu = GetSystemMenu(this.Handle.ToInt32(), 0);

    //Sistem menüsündeki Item sayısını alalım
    int itemCount = GetMenuItemCount(systemMenu);

    //Menudeki "Close" bölümünü disable edelim
    const Int32 MF_BYPOSITION = 0x400;
    const Int32 MF_REMOVE = 0x1000;

    RemoveMenu(systemMenu, itemCount - 1, MF_BYPOSITION | MF_REMOVE);

    //Uygulamadaki menu barı yeniden çizdirelim
    DrawMenuBar(this.Handle.ToInt32());
}//Form1_Load

Bu iÅŸlem sayesinde Close menüsüne disable etmiÅŸ olduk ancak kullanıcı bu pencereyi ALT+F4 kısa yoluyla yine kapatabilir. Bunu yönetmek için Form’un Form1_FormClosing eventini kullanabiliriz.

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    DialogResult result;
    //Formu kapatmaya çalışırken uyarı verelim.
    result = MessageBox.Show("Uygulamadan çıkmak istediğinize emin misiniz?", "Uygulamadan Çıkış ?", MessageBoxButtons.OKCancel);

    //Kullanıcının yanıtını okuyalım
    //OK düğmesini tıklamışsa
    if (result == System.Windows.Forms.DialogResult.OK)
    {
        //Uygulamayı kapat
        e.Cancel = false;
    }
    else //Cancel düğmesini tıklamışsa
    {
        //Uygulamayı açık bırak
        e.Cancel = true;
    }

}//Form1_FormClosing

6 Responses to “Windows Formunda sistem menüsünü yönetmek”

  1. Bora Says:

    Hocam FormBorderStyle ayarını none olarak seçtiğimizde sistem menüsü görünmüyor. Bu yazdıklarınızı uygulasak görünür mü? Kolay gelsin.

  2. Ahmet Kaymaz Says:

    Merhaba Bora,

    formun hem FormBorderStyle özelliğini None yapman hem de sistem menüsünü görünmesini istemenin mantığı nedir. Yani tam olarak ne yapmak istiyorsun. Çünkü bu seçenek doğal olarak title bar, maximize,minimize,close buttonlarını görünmez yapacaktır.

  3. Burak DILSEN Says:

    tesekkurler. o kadar ingilizce sayfa aradim bir tane dokuman bulamadim bu sorun ile ilgili. gokte ararken yerde bulduk

  4. Murat MerdoÄŸan Says:

    Hocam Slmlar,
    Yukarıdaki sistem menusundekı klasık mavi bar yerıne nasıl istediğimiz rengi verebilir veya arka plana nasıl resim ekleyebiliriz?
    Saygılar
    Kolay Gelsin

  5. Ahmet Kaymaz Says:

    Sevgili Murat,

    o kadarıyla ilgilenmedim hiç :) . Fakat API’lerle çözüleceÄŸine inanıyorum.

  6. Murat MerdoÄŸan Says:

    Hocam teşekkür ederim ilgilendiğiniz için
    Kolay Gelsin.

Leave a Reply


+ 5 = 12

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS GiriÅŸ