destroy window fonksiyonu

2 Temmuz 2013 Salı Unknown 0 yorum

destroy window fonksiyonu

işletim

            CreateWindow fonksiyonu pencereyi yarattıktan sonra pencereye ilişkin bütün bilgileri dinamik olarak tahsis ettiği içsel bir yapıda saklar. Aslında CreateWindow fonksiyonunun vermiş olduğu bu geri dönüş değeri bu içsel yapının başlangıç adresidir. DestroyWindow fonksiyonu pencereyi ekrandan görüntüsel olarak siler ve CreateWindow fonksiyonu tarafından dinamik olarak oluşturulmuş olan bu içsel yapıyı da free hale getirir. DestroyWindow fonksiyonu DefWindowProc tarafından WM_CLOSE mesajına karşı otomatik olarak çağırılır. Tabii istenildiği zaman programın ana penceresi kapatılmak isteniyorsa DestroyWindow programcı tarafından çağırılmalıdır. DestroyWindow pencere görüntüsü ekrandan sildikten sonra programcıyı haberdar etmek için WM_DESTROY mesajını gönderir. DestroyWindow aynı zamanda pencerenin bütün alt pencerelerini de DestroyWindow fonksiyonunu çağırarak siler. WM_DESTROY mesajı geldiğinde pencere ve alt pencereler ekranda görünür değildir, ancak bunlara ilişkin veri yapıları hala durmaktadır.

BOOL DestroyWindow(HWND hWnd);

Fonksiyon silinecek pencerenin handle değerini parametre olarak alır.

WM_CREATE Mesajı

            Bu mesaj CreateWindow fonksiyonu tarafından pencerenin yaratıldığını bildirmek amacıyla gönderilir. Pencere yaratıldığında yapılmak istenen ilk işlemler WM_CREATE mesajı işlenerek yapılabilirler. WM_CREATE mesajı gönderildiğinde pencere henüz görünür değildir(henüz CreateWindow fonksiyonundan çıkılmamıştır). lParam parametresinde CREATESTRUCT isimli bir yapının adresi bulunur. Bu yapının içi CreateWindow tarafından doldurulmuştur ve faydalı bilgiler içermektedir. Bu yapı içerisindeki bilgilere şu biçimde erişilebilir:

case WM_CREATE:
    {
        CREATESTRUCT *pStruct;
        pStruct = (LPCREATESTRUCT ) lParam;
        .............
        .............
        .............
    }
    break;

SendMessage ve PostMessage Fonksiyonları

            Mesaj kuyruğuna mesajlar PostMessage fonksiyonuyla programcı tarafından bilinçli olarak da bırakılabilirler. Tabii bu mesaj normal olarak kuyruğun sonuna bırakılırlar. Mesajın kuyruğa bırakılmasıyla işlenmesi arasında belli bir zaman kaybı söz konusu olabilir. Yani PostMessage fonksiyonu pencere fonksiyonu içerisinde kullanıldığında programın akışı PostMessage fonksiyonundan çıkar, mesaj kuyruğuna girilerek sıradaki mesajlar işlenir. En sonunda kuyruğa PostMessage ile programcı tarafından bırakılan mesaj alınarak işlenir. Oysa SendMessage fonksiyonu mesajı kuyruğa bırakmaz, doğrudan pencere fonksiyonunu çağırarak hemen işler. Yani programın akışı SendMessage'den çıktığında mesaj işlenmiş olur. Her iki fonksiyonun da parametrik yapısı aynıdır.




LRESULT SendMessage(
                HWND hWnd,
                UINT Msg,
                WPARAM wParam,
                LPARAM lParam
);

BOOL PostMessage(
                HWND hWnd,
                UINT Msg,
                WPARAM wParam,
                LPARAM lParam
);

Fonksiyonların birinci parametresi mesajın gönderileceği pencerenin handle değeridir. Yani bu fonksiyonlar bu handle'a ilişkin pencerenin yaratılması sırasında belirtilen pencere fonksiyonunu çağırırlar. Fonksiyonların ikinci parametresi gönderilecek mesajın numarasıdır. Üçüncü ve dördüncü parametreler mesajın wParam ve lParam parametreleridir. PostMessage fonksiyonunun geri dönüş değeri BOOL türündendir, işlemin başarısını bildirir. Oysa SendMessage fonksiyonunun geri dönüş değeri çağırılan pencere fonksiyonunun geri dönüş değeridir.

Kaynakların Program İçerisinden Kullanılması

            Normal olarak kaynaklar rc uzantılı bir text dosyası içerisine kaynak dili kullanılarak yazılırlar. Kaynak derleyicisi tarafından derlenip res uzantılı yapılırlar ve linker tarafından PE formatındaki exe dosyanın içindeki kaynak bölümüne yerleştirilirler. Visual C++ geliştirme sisteminde rc dosyası proje dosyasına eklenirse bu işlemler otomatik olarak yapılır.
            Her kaynağın kaynak dilinde nasıl yazılacağı önceden belirlenmiştir ve belli bir syntax kuralı vardır. Ancak kaynakların programcı tarafından bu biçimde yazılması, yani kaynak dilinin öğrenilmesi çok zahmetlidir. Bunun için tüm geliştirme sistemlerinde kaynaklar ismine kaynak editörü(resource editor) denilen bir ortamda görsel olarak hazırlanırlar. Kaynaklar görsel olarak belirlendikten sonra geliştirme sistemi bunun kaynak dilindeki karşılığını rc dosyası biçiminde oluşturur. Her kaynağın bir ismi vardır. Bu isim alfabetik ya da sayısal biçimde verilebilir. Eğer kaynak isminin ilk harfi alfabetik bir karakterle başlıyorsa kaynak alfabetik olarak isimlendirilmiştir, sayısal bir karakterle başlıyorsa kaynak sayısal olarak isimlendirilmiştir(Eğer bir sayı alfabetik bir isim olarak kullanılacaksa çift tırnak içine alınmalıdır). Genel olarak sayısal biçimde isimlendirilmiş kaynaklar ile daha hızlı işlem yapılır. Bir kaynağı bir programın içinde kullanmak için kaynağı hazır hale getirmek gerekir. Bu işlem sırasında kaynak exe dosyanın kaynak bölümünden alınır, bellekte dinamik olarak yaratılan bir veri yapısının içerisine çekilir. kaynağı hazır hale getiren fonksiyonların isimleri Loadxxxx biçimindedir. Kaynağı hazır hale getiren Loadxxxx fonksiyonlarının iki parametresi vardır. Birincisi exe dosyanın bellekteki yükleme adresi olan hInstance adresidir, ikincisi ise kaynağın ismidir(Bu fonksiyonların exe dosyasının kaynak bölümüne erişebilmesi için exe dosyasının bellekteki yükleme adresini bilmeleri gereklidir). Loadxxxx fonksiyonlarının geri dönüş değerleri kaynağa ilişkin handle değerleridir. Örneğin HCURSOR, HICON, HMENU biçiminde olabilir(hepsi aslında void *).


Menü Kaynağının Kaynak Dilinde Oluşturulması

            Kaynak dilinde her kaynak önce kaynak ismiyle başlar, sonra onu kaynağın türünü belirten bir anahtar sözcük izler, sonra kaynaklara göre değişebilen parametrik bilgiler yazılır. Bir menü menü çubuğu ve popup menülerden oluşur. Popup menünün içerisinde başka bir popup menü bulunabilir. Bir menü popup menülerden, popup menüler de menü elemanlarından oluşur. Kaynak derleyicileri C'nin ön işlemci komutlarını aynı biçimde kullanabilir. Popup menülerin bir numarası yoktur ama her menü elemanının bir numarası olmak zorundadır. Menü elemanlarının numaraları istenildiği gibi seçilebilir(Ancak 100'den büyük olması tavsiye edilir). Ancak her menü elemanının numarası diğerinden farklı olmalıdır.
            Kaynak dilinde yazılmış kaynaklar çeşitli sayılar kullanabilirler. Bu sayıların ayrı bir başlık dosyasında sembolik sabit olarak tanımlanmaları önerilmektedir. Bu durumda kaynak kullanımı için bir rc dosyası, bir de h dosyası oluşturulur. Bu rc dosyası içerisinden h dosyası include edilir. Örneğin Visual C++ geliştirme sisteminde bir kaynak dosyası yaratıldığında otomatik olarak resource.h dosyası da yaratılır.

Menü Kaynağının Program İçerisinden Kullanılması

            Bir menü kaynağını programa dahil edebilmek için üç yöntem vardır:

1. WNDCLASS yapısının lpszMenuName elemanına menü kaynak ismi girilirse menü otomatik olarak görüntülenir.
2. WNDCLASS yapısının lpszMenuName elemanı NULL olarak girilirse menü yine de CreateWindow fonksiyonunda yaratılabilir. Bunun için önce LoadMenu fonksiyonuyla menü kaynağı hazırlanır, sonra buradan alınan handle değeri CreateWindow fonksiyonunun hMenu parametresi olarak verilir.

HMENU hMenu;
hMenu = LoadMenu(hInstance, "SAMPLE_MENU");
CreateWindow(.........................., hMenu, ......);

3. Menü CreateWindow fonksiyonundan sonra programın herhangi bir yerinde SetMenu API fonsiyonuyla da yaratılabilir.

Alt Pencerelerle İşlemler

            Alt pencereler CreateWindow fonksiyonuyla yaratılırlar. Verilen koordinatlar üst pencerenin çalışma alanı(client area) referans alınarak oluşturulurlar(Üst pencerelerin referans noktası masaüstü penceresinin sol üst köşesidir). Alt pencere yaratılırken üst pencerenin handle değerine gereksinim duyulur. Alt pencerelerin handle değerlerinin yanısıra bir de id değerleri vardır. Alt pencere id değerleri işaretsiz tam sayı biçimindedir ve normal olarak WORD sınırları içerisindedir. CreateWindow fonksiyonunun dokuzuncu parametresi HMENU türündendir. HMENU parametresi üst pencerelerde menü işlemleri için kullanılırken, alt pencerelerde pencere id değerinin belirlenmesi amacıyla kullanılır. Tabii bu parametrenin alt pencere id'si olarak girilmesi durumunda tür dönüştürmesi yapılması gerekir. Örneğin (HMENU) 100, ya da sembolik olarak (HMENU) CHILD_ID. Pencere  id değeri WORD sınırlarında sıfırdan farklı herhangi bir değer olabilir. Alt pencerelerin id değerleri aslında tamamen programlamayı kolaylaştırmak amacıyla düşünülmüştür. Hem handle değeri hem de id değeri her ikisi de bir pencereyi teşhis etmek amacıyla kullanılabilir. Ancak id değerinin tam sayı türünden olması programlamada çeşitli biçimlerde kolaylık sağlamaktadır. Zaten alt pencerenin handle değeriyle id değerinin bir tanesinin bilinmesi durumunda diğerinin elde edilmesini sağlayan API fonksiyonları vardır. Alt pencerelerin ve üst pencerelerin farklı pencere fonksiyonları olabilir. Alt pencereyle üst pencerenin pencere fonksiyonlarının farklı olabilmesi için bu iki pencerenin farklı WNDCLASS yapılarıyla yaratılması gerekir. Çünkü pencere fonksiyonunun belirlenmesi WNDCLASS ile yapılmaktadır. Bir program içerisinde ne kadar çok alt pencere ve üst pencere yaratılmış olursa olsun bu pencerelere ilişkin mesajlar programın(aslında alt işlemin(thread)) mesaj kuyruğuna yerleştirilirler. Yani her programın(aslında alt işlemin) yalnızca bir tane mesaj kuyruğu vardır, o programın yarattığı bütün pencerelere ilişkin mesajlar aynı kuyruğa yerleştirilir. Programın tek bir mesaj döngüsü vardır. GetMessage fonksiyonu tüm pencereler için gönderilmiş olan mesajları alabilmektedir. Mesaj karşılığında hangi pencere fonksiyonunun çağırılacağı kararı DispatchMessage fonksiyonu tarafından verilir. DispatchMessage fonksiyonu mesajın hWnd parametresine bakarak pencerenin hangi WNDCLASS yapısıyla yaratılmış olduğunu tespit eder ve buradan ilgili pencere fonksiyonunu bularak çağırır. DestroyWindow fonksiyonu ile üst pencere yok edilince DestroyWindow fonksiyonu önce alt pencereleri yok eder, daha sonra ilgili pencereyi yok eder.

Uyarı: DefWindowProc fonksiyonu WM_CLOSE mesajı işlenmemişse default olarak DestroyWindow fonksiyonunu çağırır. Ancak WM_DESTROY için PostQuitMessage'i çağırmaz. Eğer WM_DESTROY mesajı ile PostQuitMessage çağırılmamışsa pencere silinir ama program sonlanmaz.

Üst ve Alt Pencereler Arası Mesaj Alış-Verişi


            SendMessage ve PostMessage fonksiyonlarıyla üst pencere alt pencereye, alt pencere de üst pencereye mesaj gönderebilir. Aslında bu fonksiyonlarla handle değeri bilindikten sonra her türlü pencereye mesaj gönderilebilmektedir.

Alt Pencere Nerede Yaratılmalı?


            Alt pencere üst pencere yaratıldıktan sonra herhangi bir yerde yaratılabilir. Ancak uygulamalarda bu işlem genellikle iki biçimde yapılır:
1. Önce CreateWindow ile üst pencere yaratılır. Bu kodun aşağısında yine CreateWindow ile alt pencere yaratılır.

2. Alt pencere üst pencerenin pencere fonksiyonu içerisinde WM_CREATE mesajında yaratılır. Tabii burada hInstance değerinin WinMain fonksiyonundan bir biçimde elde edilmesi gerekir. hInstance değerinin herhangi bir yerden elde edilmesi için birkaç yöntem vardır. En fazla kullanılan yöntem bu değerin WinMain içerisinde global bir değişkene taşınmasıdır. 

0 yorum: