msg yapısının elemanları

2 Temmuz 2013 Salı Unknown 0 yorum
MSG Yapısının Elamanları

işletim
- HWND hWnd
                Her pencerenin bir mesaj kuyruğu yoktur. Her programın bir mesaj kuyruğu vardır. Yani bir program 10 tane pencere yaratmış olsa bile bu pencerelerin herhangi birisinde oluşan girdi işlemi aynı kuyruğa yazılacaktır. Yapının bu elemanı programın hangi penceresine ilişkin bir mesaj oluştuğunu belirtir.

- UINT message
                Bu eleman mesajın hangi sebepten kuyruğa yazıldığını anlatan bir sayı içerir. Bir mesaj yüzlerce sebepten dolayı kuyruğa yazılabilir. Ancak mesajın nedenleri sayısal düzeyde konuşulmaz. Windows.h içerisinde tüm bu sayılar WM_ ile başlayan sembolik sabitlerle tanımlanmıştır. Yani örneğin 108 numaralı mesaj yerine WM_XXXXX mesajı biçiminde durum ifade edilir.

- WPARAM wParam
   LPARAM lParam
                WPARAM aslında unsigned int türüdür. Unsigned int türü 16 bit Windows sistemlerinde 2 byte uzunluğundaydı. Ancak 32 bit Windows sistemlerinde 4 byte'lık bir bilgidir. Burada W ön eki 16 bit Windows sistemleri kullanılırken isimlendirilmiştir. 32 bit sistemlere geçildiğinde bu isimlendirmenin kullanılmasına devam edilmiştir. LPARAM unsigned long türüdür ve her iki sistemde de 4 byte uzunluğundadır. Bu elemanlara mesaja bağlı olan ek bilgiler yerleştirilir. Örneğin WM_CHAR mesajında wParam basılan tuşun ASCII sıra numarasını içerirken WM_LBUTTONDOWN mesajında basılan noktanın koordinat bilgisini içermektedir. Her mesaj için bu elemanlara hangi bilgilerin yerleştirildiği ayrıca öğrenilmelidir.

- DWORD time
                Mesajın gönderildiği zaman bilgisidir.

- POINT pt
                Bu eleman bazı mesajlarda ekrana ilişkin koordinat bilgisini tutmak amacıyla kullanılır.

Mesaj Döngüsü

                Mesajlar sistem tarafından kuyruğa yazılır, ancak bu mesajların alınarak işlenmesi programcı tarafından yapılır. Programcı mesajları alarak önce bu mesajları anlamlandırır, daha sonra uygun işlemleri yapacak kodları çalıştırır. Programa ilişkin pencere kapatılıp program sonlandırılacağı zaman bu işlem de Windows tarafından WM_QUIT mesajı olarak kuyruğa yazılır. Yani bir döngü içerisinde mesajların sürekli alınarak işlenmesi WM_QUIT mesajı görüldüğünde de döngü sonlandırılarak programın bitirilmesi gerekir.

GetMessage Fonksiyonu

                GetMessage kuyrukta bulunan ilk mesajı alır ve bu mesajı kuyruktan siler. Fonksiyonun prototipi:


BOOL GetMessage(
                     LPMSG lpMsg,
                     HWND hWnd,
                     UINT wMsgFilterMin,
                     UINT wMsgFilterMax
);

                Fonksiyonun birinci paranmertesi MSG türünden bir göstericidir. Bu parametreye MSG türünden bir yapının adresi geçirilmelidir. GetMessage kuyrukta sırada bulunan mesajı alarak bu yapının içerisine yerleştirir. İkinci parametre programa ilişkin hangi pencerenin mesajlarının alınacağını belirtir. Yani GetMessage ile özellikle bir pencereye ilişkin mesajlar alınabilir. Bu parametre NULL girilirse bütün pencerelere ilişkin mesajlar alınır. Fonksiyonun üçüncü ve dördüncü parametreleri hangi aralıktaki mesajların kuyruktan alınacağını belirtir. Örneğin bu parametrelere 100 ve 120 girilirse yalnızca bu aralıkta numaralara sahip olan mesajlar alınır. Eğer bu iki parametreye 0 girilirse tüm mesajların alınacağı anlamına gelir. İskelet programda tüm mesajlar alınmaktadır. Fonksiyon eğer WM_QUIT mesajını aldıysa 0 değerine, WM_QUIT dışındaki bir mesajı aldıysa 0 dışı herhangi bir değere geri döner. GetMessage eğer kuyrukta mesaj yoksa programın çizelgeleme dışı bırakılıp bloke edilmesine yol açar. Yani programcı bakış açısıyla programın akışı GetMessage içerisinde beklemektedir. Kuyruktan sürekli olarak mesajı alan WM_QUIT görünce işlemi sonlandıran bir döngü şöyle kurulabilir:

while (GetMessage(&msg, NULL, 0, 0)) {
...........
..........
.........
}

                Mesaj döngüsünden çıkıldığında WinMain fonksiyonu da biter, bu fonkiyon bitince de program biter. GetMessage fonksiyonu ile mesaj alındıktan sonra anlamlandırılıp işlenmelidir, ancak prensip olarak mesajın mümkün olduğu kadar çabuk bir biçimde işlenmesi istenir. Eğer mesajın işlenmesi uzun sürerse GetMessage bir sonraki mesajı kuyruktan alamaz. Böylece programda herhangi bir ilerleme söz konusu olamaz. Ancak yine de mesajın işlenmesini geciktirecek ciddi sebepler olabilir. O zaman programın akışının devam etmesi nasıl sağlanacaktır? İşte alt işlemli programlama sistemi(multi-threading) bu tür problemlere çözüm bulmaktadır.

Mesajların İşlenmesi ve Pencere Fonksiyonu

                Mesajların işlenmesi ismine pencere fonksiyonu denilen bir fonksiyon tarafından yapılır. Kuyruktan mesaj alındığında DispatchMessage API fonksiyonu çağırılır. DispatchMessage fonksiyonuna parametre olarak kuyruktan alınan mesajın bulunduğu değişkenin adresi geçirilmektedir. DispatchMessage mesajın hWnd elamanına bakarak mesajın hangi pencereye ilişkin olduğunu anlar. O pencere ilişkin pencere fonksiyonunu çağırır. Bir pencere yapısının parametrik yapısı şöyle olmak zorundadır:





LRESULT CALLBACK WndProc(
                     HWND hWnd,
                     UINT message
                     WPARAM wParam
                     LPARAM lParam
);

                Fonksiyonun geri dönüş değeri LRESULT yani long olmak zorundadır. Çağırma biçimi __stdcall olmak zorundadır. Zaten CALLBACK sembolik sabiti __stdcall anlamına gelmektedir. DispatchMessage fonksiyonu mesajı alıp mesaj içerisindeki hWnd, message, wParam, lParam elemanlarını ayrıştırarak bu elemanları pencere fonksiyonunun parametresi yapmak suretiyle pencere fonksiyonunu çağırır. Yani programın akışı pencere fonksiyonumuzdan çıktığında akış DispatchMessage içerisinden devam eder.
                Mesaj döngüsünün içerisinde TranslateMessage API fonksiyonu da çağırılmaktadır. Bu fonksiyonun mesaj işlenme mekanizmasıyla ciddi bir bağlantısı yoktur. ASCII tuşlarına basıldığında WM_CHAR mesajının oluşumunu sağlar.

Pencere Fonksiyonunun Tasarımı

            Bunun için önce mesajın ne mesajı olduğunun tespit edilmesi gerekir. Bu işlem bir switch deyimiyle yapılabilir. Daha sonra mesaj parametreleri yorumlanarak case ifadeleri işlenir.

Windows Programının Sonlandırılması

            Bir Windows programı programın akışı mesaj döngüsünden çıkıp WinMain fonksiyonunun bitmesiyle sonlanır. Program akışının mesaj döngüsünden çıkması GetMessage fonksiyonunun 0 ile geri dönmesiyle sağlanır. GetMessage fonksiyonu WM_QUIT mesajını gördüğünde 0'a geri döner.

DefWindowProc API Fonksiyonu

            Bir programın en basit işlemleri yapacak biçimde sağlıklı çalışabilmesi için bir takım kritik mesajların işlenmesi gerekir. Oysa bunların işlenmesi ve bu mesajlara karşılık default bazı işlemleri yapılması uzun bir işlem yükü gerektirir. İşte DefWindowProc fonksiyonu bir mesaj için default kritik işlemleri yapabilen bir fonksiyondur. Yani pencere fonksiyonu içerisinde mesajlar işlenir, işlenmeyen mesajlar bu API fonksiyon çağırılarak işletilir. O halde en basit bir pencere fonksiyonu şöyle tasarlanabilir:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT, message, WPARAM wParam, LPARAM lParam)
{
                return DefWindowProc(hWnd, message, wParam, lParam);
}              /*Tüm mesajlar default olarak işlenecektir*/

            DefWindowProc fonksiyonunun gelen mesajlara karşı hangi kritik işlemleri yaptığı bazı tür işlemlerde programcı tarafından bilinmek zorundadır.
            İşlenen mesajlar için DefWindowProc fonksiyonu çağırılmamalıdır. O halde bu fonksiyon tipik olarak switch'in default kısmına yerleştirilmelidir.


0 yorum: