wm user mesajları

WM_USER Mesajları


işletim
            Windows'un önceden belirlenmiş olan WM_ mesajları 0 ile 0x0400 arasında bulunmaktadır. Ancak programcı isterse kendi mesaj numaralarıyla da işlem yapabilir. Bunun için windows.h içerisinde tanımlanmış olan WM_USER değerinden 0x7FFF'e kadar olan mesajlar kullanılmalıdır. WM_USER sistem tarafından işlenen bir mesaj değildir. Yalnızca programcının kullanabileceği mesaj numarasının nereden başlayacağını anlatan bir sembolik sabittir.

Alt Pencere Biçimleri

            CreateWindow fonksiyonunun ikinci parametresi olan pencere biçimi eğer alt pencere söz konusuysa en azından WS_CHILD içermelidir. Ancak WS_BORDER eklenmezse pencerenin sınır çizgisi görünmez. Genellikle alt pencereler için başlık kullanılmaz. Ancak WS_CAPTION pencere biçimi eklenirse pencere başlık kısmına sahip olabilir.

WS_VISIBLE Pencere Biçimi


            İster üst pencere ister alt pencere söz konusu olsun eğer pencere biçimi olarak WS_VISIBLE seçilirse pencere yaratılır yaratılmaz pencere görüntülenir. Eğer WS_VISIBLE kullanılmazsa görüntüleme işlemi için ShowWindow fonksiyonunun çağırılması gerekir.
GetClientRect API Fonksiyonu

            Bir pencereyle ilgili işlem yapılırken örneğin alt pencere koordinatlarının belirlenmesi ya da çizimler söz konusu olduğunda orijin noktası çalışma alanının(client area) sol üst köşesidir. Pencere boyutunun değiştirilmesi durumunda çalışma alanının sağ alt köşegeninin koordinatları da değişir. GetClientRect fonksiyonu çalışma alanının sağ alt köşegeninin koordinatlarını elde etmekte kullanılır. Bu koordinatın elde edilmesiyle pencerenin genişlik ve yükseklik bilgisi elde edilmiş olur. Prototipi:

BOOL GetClientRect(
                HWND hWnd,
                LPRECT lpRect
);

Kullanımı:
LPRECT rect;
GetClientRect(hWnd, &rect);

Fonksiyonun ikinci parametresi RECT türünden bir yapı değişkeninin adresini alır. RECT yapısı windows.h içerisinde şöyle bildirilmiştir:

typedef struct tagRECT{
                long left, top, right, bottom;
} RECT *LPRECT;

GetClientRect fonksiyonu ile elde edilen dikdörtgensel koordinatın sol üst köşegeni her zaman 0, 0 olur. Zaten bu fonksiyon sağ alt köşegenin elde edilmesi için kullanılır.

WM_SIZE Mesajı


            Windows bir pencerenin boyutunun değiştirildiği bir durumda mesaj kuyruğuna bu mesajı bırakır. Pencerenin boyutu köşe noktalarından mouse ile çekildiğinde ya da maximize, minimize, restore tuşlarına basıldığında değişmektedir. Mesajın wParam ve lParam parametreleri şöyle yerleştirilir:
Width = LOWORD(lParam);            /*rect.right*/
Hight = HIWORD(lparam);              /*rect.bottom*/

wParam parametresi şu değerleri alabilir:
SIZE_MINIMIZED
SIZE_MAXIMIZED
SIZE_RESTORED

MoveWindow API Fonksiyonu


            CreateWindow fonksiyonu ile belirlenen koordinat pencerenin ilk açılma görüntüsüne ilişkindir. Bunun dışında pencerenin boyutu çeşitli biçimlerde değiştirilebilir. MoveWindow fonksiyonu hem pencerenin boyutunu değiştirmekte hem de onu ötelemekte kullanılabilir. Prototipi:

BOOL MoveWindow(
                HWND hWnd,
                int x,
                int y,
                int nWidth,
                int nHeight,
                BOOL bRepaint
);

Fonksiyonun birinci parametresi ilgili pencerenin handle değeri, x, y, nWidth ve nHeight parametreleri pencerenin yeni konumunun bilgileridir. Fonksiyonun son parametresi taşınan pencerenin görüntüsünün güncellenmesiyle ilgilidir. Bu parametre genellikle TRUE olarak verilir. Bu durumda güncelleme işlemi hemen yapılır.

Kontroller


            Windows sistemi tarafından tanımlanmış olan bir grup alt pencere sistemine kontrol denir. Kontroller; temel kontroller ve gelişmiş kontroller biçiminde ikiye ayrılır. Temel kontroller şunlardır:

Static kontrolü
Push button kontrolü
Edit box kontrolü
List box kontrolü
Check box kontrolü
Radio button kontrolü
Combo box kontrolü
Scroll bar kontrolü

Gelişmiş kontroller şunlardır:

Toolbar kontrolü
Tree kontrolü
Status bar kontolrü
Proggress bar kontrolü
Column kontrolü
Property sheet kontrolü
Tab kontrolü
...

Windows sistemi yüklenirken bir grup WNDCLASS yapısını çeşitli isimlerle sisteme register eder. Bu sınıf isimleri alt pencere yaratmakta kullanılırsa pencere fonksiyonu sınıf ile belirtilen fonksiyonlar olur. Bu sınıfların pencere fonksiyonları user32.dll içerisindedir ve programcıdan gizlenmiştir. Bu sınıflar kullanılarak alt pencere yaratıldığında bu pencere için gönderilen mesajlar programcının değil bu sınıfların pencere fonksiyonu tarafından işlenir. Örneğin kontrol sınıflarına ilişkin bir pencere yaratılıp mouse ile üzerine click yapılsa mouse mesajı programın mesaj kuyruğuna bırakılacak ancak DispatchMessage kotrolün pencere fonksiyonunu çağıracaktır.

Static Kontrolü


            Bu kontrol yalnızca bir alt pencerenin üzerine yazı görüntülemek için kullanılır. Static kontrol penceresinin zemin ve yazı renkleri ileride ele alınacaktır. Static kontrol penceresinin zemin rengiyle üst pencerenin zemin rengi aynı alınırsa bu kontrol bir pencereye yazı yazmak amacıyla kullanılır. Bu kontrolü yaratmak için CreateWindow fonksiyonunda sınıf ismi yerine "static" girilir. Pencere kordinatları yazının yazılacağı pencerenin koordinatlarıdır. Pencerenin içerisine yazılacak yazı CreateWindow fonksiyonunun pencere başlığı yazısıdır.
(WM_SIZE mesajı bir pencere ilk kez görüntülendiği zaman da gönderilmektedir.)

Static Kontrolünün Özel Pencere Biçimleri


            Her pencere için ortak olan pencere biçimlerinin yanı sıra her kontrolün ayrı yalnızca o kontrol için anlamlı olan özel pencere biçimleri de vardır. Static kontrolü için en önemlileri şunlardır:

SS_LEFT

SS_RIGHT

SS_CENTER
/*Bunlar yazının hizalanmasına ilişkindir.*/
SS_WHITERECT

SS_BLACKRECT

SS_GRAYRECT
/*Bunlar static kontrolünün zemin rengine ilişkindir.*/
Ancak bu renkler mutlak değil göreli renklerdir. Denetim masasındaki renklendirmeye bağlı olarak değişirler.
SS_WHITEFRAME

SS_BLACKFRAME

SS_GRAYFRAME
/*Kontrolün sınır çizgilerinin rengine ilişkindir.*/


Not: Bir pencerenin double-click mesajlarını kabul edebilmesi için sınıfın yaratıldığı WNDCLASS yapısının UINT Style elemanını CS_DBLCLKS olarak belirtmek gerekir.


Devamı... 2 Temmuz 2013 Salı Unknown 0 yorum

destroy window fonksiyonu


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. 

Devamı... Unknown 0 yorum

pencere fonksiyonunun geri dönüş değeri

Pencere Fonksiyonunun Geri Dönüş Değeri

işletim
            Pencere fonksiyonunun geri dönüş değeri DispatchMessage fonksiyonu tarafından yorumlanır. Fonksiyonun geri dönüş değeri mesajdan mesaja değişir. Yani hangi mesaj geldiğinde neyle geri dönüleceği önceden bilinmek zorundadır. Ancak aksi söylenmediği sürece pencere fonksiyonu eğer mesajı işlemişse 0 ile geri dönmelidir. İşlememişse DefWindowProc fonksiyonunun geri dönüş değeriyle geri dönmelidir.

LRESULT CALLBACK WindowProc(HWND hWnd, UINT, message, WPARAM wParam, LPARAM lParam);
{
                switch(message) {
                               case .......... :
                                               ........
                                               ........
                                               break;
                               case .......... :
                                               ........
                                               ........
                                               break;
                               default:
                                               return DefWindowProc(hWnd, message, wParam, lParam);
                }
                return 0;
}

Pencerenin Kapatılması Sırasında Gerçekleşen İşlemler

            Bir pencereye kapatmak için klik yapıldığında ya da klavye ile Alt+F4 tuşlarına basıldığında Windows yalnızca mesaj kuyruğuna WM_CLOSE mesajını bırakır. Bu mesaja karşılık DefWindowProc DestroyWindow API fonksiyonunu çağırmaktadır. Bu API fonksiyonu pencereyi kapar ve mesaj kuyruğuna WM_DESTROY mesajını koyar. WM_DESTROY mesajı genellikle programcı tarafından işlenir. Programcı bu mesaj karşılığında PostQuitMessage API fonksiyonunu çağırmalıdır(zaten DefWindowProc fonksiyonu da default olarak PostQuitMessage fonksiyonunu çağırır), bu fonksiyon yalnızca kuyruğa WM_QUIT mesajını yerleştirir. GetMessage fonksiyonu da bu mesajı alarak 0 ile geri döner ve WinMain sonlanır.


Visual C++ Geliştirme Sisteminin Kullanılması

            Windows altında geliştirme ortamlarında programlama sistemi karmaşık olduğu için mutlaka proje dosyası oluşturularak çalışılır. Uygun bir proje dosyası oluşturabilmek için File => New seçilir. Eğer Win32 Console Application seçilirse konsol programı yazılabilir. Bir konsol programı tamamen DOS'teki bilgilerle yazılabilir. Ancak Windows'un grafik özellikleri kullanılamaz. Eğer Win32 Application seçilirse API düzeyinde programlama yapılabilir. 6.0 sürümünde iskelet programı oluşturan bir wizard da yerleştirilmiştir. Tüm projeler için ayrı bir dizin açılır ve proje dosyaları o dizin içerisine yerleştirilir. Dizin proje ismiyle aynı isimde olur. Açılan dizin içerisine projedeki bütün kaynak dosyalar yerleştirilir. Proje dizininin altında res ve debug/release isimli iki dizin oluşturulur(bu genellikle debug olur, program kaynak kullanmamışsa res dizini açılmaz). Res dizini içerisinde kaynak kullanımına ilişkin dosyalar bulunur. Debug/release'in içerisinde bütün obj modüller, exe dosyaları ve precompiled header dosyası bulunur. Precompiled header dosyası başlık dosyalarını çabuk analiz etmek için gerekir, çok büyük bir dosyadır. Bir projeyi diskete almak için önce debug/release dizini silinmeli ve proje tüm alt dizinleriyle beraber alınmalıdır. Bir proje yaratıldığında bütün proje işlemleri ismine proje çalışma alanı(project workspace) denilen bir pencere yardımıyla yürütülür. Proje çalışma alanı penceresi kapatılabilir(projenin kapandığı anlamına gelmez), daha sonra Alt+0 tuşları ile açılabilir. Bir projenin tamamen kapatılması için File=>Close Workspace seçilmelidir. Proje çalışma alanı penceresinin 4 alt penceresi vardır.

Class View:
Burada bütün C++'taki sınıflar C'deki fonksiyonlar listelenir. Buradaki bir elemanın üzerine double click yapılırsa o fonksiyonun tanımlamasının bulunduğu yere gidilebilir.
File View:
Burada projenin içindeki dosyaların listesi bulunur. Bu pencere aynı zamanda projeye dosya eklemek ve projeden dosya çıkarmak için de kullanılır. Eklemek için projenin üzerinde sağ fare tuşuna basılıp Add Files To Project seçilerek yapılır.
Resource View:
Bu pencere program kaynak kullanıyorsa yaratılır. Kaynak işlemleri bu pencereden izlenebilir.
Info View:
Yardım almakta kullanılır.


Programın Derlenmesi ve Çalıştırılması

            Editördeki program Build=>Compile menüsüyle derlenir(Ctrl+F7). Proje içerisindeki bütün dosyaları ve kaynak dosyasını derleyip hep beraber link ederek exe yapmak için Build=>Build seçilir(F7). Bu seçenek yalnızca değişmiş olan dosyaları yeniden derler. Koşulsuz bütün dosyaları derleyip exe yapmak için Build=>Rebuild seçilir. Bir programı çalıştırmak için Build=>execute seçilir(Ctrl+F5). Tabii değişen dosyalar bu arada tekrar derlenir. Bir projeyi açmak için File=>Open Workspace.
            Bir fonksiyonun pencere fonksiyonu olduğunu belirtmek için o fonksiyon isminin WndClass yapısının lpfnWndProc elemanına yazılması gerekir.




Windows Programlamada Yardım İşlemleri

            Windows altında programlama için iyi bir yardım desteğinin olması gerekir. Visual C++ geliştirme ortamının Online Book diye isimlendirilen bir yardım desteği vardır. Visual C++ 6.0 sürümünde yardım desteği MSDN programının ayrıca install edilmesiyle sağlanır. Online Book içerisinde sistemin orijinal kitapları bulundurulmaktadır.

Mouse Mesajları

            Bir pencerenin başlık kısmı çıkartılmış bölgesine çalışma alanı(client area) denir. Çalışma alanının sol üst köşegeni pek çok işlem için orijin noktası belirtir. Mouse  pencerenin çalışma alanı içerisinde bir yerde tıklandığında ve çekildiğinde Windows mesaj kuyuruğuna WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONUP mesajlarını ekler. Bu mesajların lParam ve lParam parametreleri şu bilgileri içerir:
wParam: Click yapıldığında aynı zamanda bir tuşa basılıp basılmadığını belirtir. Şunlardan oluşur:

MK_CONTROL
MK_LBUTTON
MK_RBUTTON
MK_MBUTTON
MK_SHIFT

lParam: Mouse'un click yapıldığı pixel pozisyonudur.
xPos = LOWRD(lParam);
yPos = HIWORD(lParam);

LOWORD ve HIWORD makroları 32 bit bir bilginin yüksek anlamlı ve düşük anlamlı 2 byte'ını elde etmek için kullanılır.
#define HIWORD(x)           ((WORD) (x) >> 16)
#define LOWORD(x)          ((WORD) (x))
Bu makrolar windows.h içerisinde tanımlanmıştır.

MessageBox Fonksiyonu

            Windows'ta acil bir mesaj basmak için MessageBox API fonksiyonu kullanılır. Bu fonksiyon ile pencere başlığı, pencerenin içerisindeki mesaj, istenen tuş takımı ve görüntülenecek ikon belirlenebilir.

int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption
UINT uType
);

Fonksiyonun birinci parametresi messagebox penceresinin çıkartılacağı üst pencerenin handle değeridir. Bu parametre NULL olarak girilebilir(messagebox yaratmak için bir pencere yaratmak gerekli değildir). Yani programın hiçbir pencereyi olmasa bile messagebox çıkartılabilir. İkinci parametresi pencerenin içine yazılacak yazının başlangıç adresini alır. Üçüncü parametresi pencerenin başlık yazısını belirtir. Dördüncü parametresi tuş takımı ve ikon görüntüsünü belirler. Tuş takımları şunlar olabilir:

MB_ABORTRETRYIGNORE
MB_OK
MB_OKCANCEL
MB_YESNO
MB_YESNOCANCEL

İkon görüntüsü şunlar olabilir:

MB_ICONEXCLAMATION
MB_ICONWARNING
MB_ICONINFORMATION
MB_ICONASTERIKS
MB_ICONQUESTION
MB_ICONSTOP

            Tuş takımıyla ikon görüntüsü bit OR işlemine sokularak birleştirilebilir. Örneğin: MB_OK | MB_ICONEXCLAMATION
            Tuş takımlarından bir tanesi default olarak seçilebilir. Default tuş enter tuşuna basıldığında seçilmiş kabul edilen tuştur. Default tuşu belirlemek için 3 tane sembolik sabit vardır:

MB_DEFBUTTON1
MB_DEFBUTTON2
MB_DEFBUTTON3

Bu sembolik sabitler de diğerleriyle birleştirilerek kullanılırlar. Örneğin:
MB_YESNOCANCEL | MB_ICON_EXCLAMATION | MB_DEFBUTTON3

Fonksiyonun geri dönüş değeri hangi tuşa basılarak pencerenin kapatıldığı bilgisini verir. Şunlardan bir tanesi olabilir:

ID_ABORT
ID_CANCEL
ID_IGNORE
ID_NO
ID_OK
ID_RETRY
ID_YES

Mouse'un sol tuşuna basıldığında messagebox çıkartan uygulama:






LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
                switch (message) {
                               case WM_DESTROY:
                                               PostQuitMessage(0);
                                               break;
                               case WM_LBUTTONDOWN:
MessageBox(hwnd, "Deneme", "Deneme", MB_YESNOCANCEL |   MB_ICONSTOP  |  MB_DEFBUTTON2);
                                               break;
                               default:
                                               return DefWindowProc(hwnd, message, wParam, lParam);
                }
                return 0;
}

Sınıf çalışması: Farenin sol tuşuna basıldığında yesnocancel messagebox'ı gözükecek, bunlardan bir tanesi seçildiğinde başka bi messagebox ile hangi tuş'a basıldığı yazdırılacak.

LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
                switch (message) {
                               case WM_DESTROY:
                                               PostQuitMessage(0);
                                               break;
                               case WM_LBUTTONDOWN:
iMsgBoxReturnValue = MessageBox(hwnd, "Deneme yapıyom ben", "Deneme dedik aşşaada", MB_YESNOCANCEL | MB_ICONSTOP | MB_DEFBUTTON2);
                                               switch (iMsgBoxReturnValue) {
                                               case IDYES:
MessageBox(hwnd, "Yes'e bastın kardeş", "Deneme", MB_OK | MB_ICONSTOP);
                                                               break;
                                               case IDNO:
MessageBox(hwnd, "No'ya bastın kardeş", "Deneme", MB_OK | MB_ICONSTOP);
                                                               break;
                                               case IDCANCEL:
MessageBox(hwnd, "Cancel'a bastın kardeş", "Deneme", MB_OK | MB_ICONSTOP);
                                                               break;
                                               }
                                               break;
                               default:
                                               return DefWindowProc(hwnd, message, wParam, lParam);
                }
                return 0;

}
Devamı... Unknown 0 yorum

msg yapısının elemanları

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.


Devamı... Unknown 0 yorum

açılmış pencerenin görüntülenmesi

Yaratılmış Pencerenin Görüntülenmesi

işletim
            Bir pencere WS_VISIBLE pencere biçimiyle yaratılmışsa yaratılır yaratılmaz zaten görüntülenir. Ancak değilse ShowWindow API fonksiyonu ile görüntülenir.

BOOL ShowWindow(HWND hWnd, int nExitCode);

            Fonksiyonun birinci parametresi görüntülenecek pencerenin handle değeri, ikinci parametresi ise görüntülenme biçimidir. Görüntülenme biçimi SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE olabilir.
(Bir fonksiyonun geri dönüş değeri BOOL ise başarı bilgisinin verildiği anlaşılır. BOOL değer mantıksal olarak 0 ya da 0 dışı bir değer olarak değerlendirilir. Örneğin ShowWindow başarılı ise 1'e değil 0 dışı herhangi bir değere geri dönmektedir.)
            Ana pencere yaratıldıktan sonra içsel görüntünün güncelleştirilmesi için WM_PAINT mesajı gerekebilir. Bunu sağlamak için UpdateWindow API fonksiyonu çağırılır.

İskelet Programın Aşamaları

            Pencereli bir Windows programı tipik olarak 3 aşamadan geçilerek oluşturulur.

1. WNDCLASS yapısının içi doldurularak sisteme tanıtılması aşaması,
2. Pencerenin yaratılarak görüntülenmesi aşaması,
3. Mesaj dögüsünün oluşturulması ve pencere fonksiyonunun tasarımı.

Mesaj Kavramı

            DOS işletim sisteminde klavye ve mouse bilgileri programcının koda yerleştirdiği fonksiyonlar yardımıyla elde edilir. Örneğin getchar() fonksiyonu klavyeden bir tuşa basılana kadar bekler, basılan tuşun bilgisini alarak işlemini sonlandırır. Oysa Windows sistemlerinde klavye ve mouse gibi giriş bilgileri programcının çağırdığı bir fonksiyonla değil, Windows sistemlerinin kendisi tarafından ilk elden alınır. Windows sistemlerinde sistem tarafından tespit edilen girdi bilgilerine mesaj denir. Her girdi bilgisinin yani mesajın hangi nedenden dolayı oluştuğunu açıklayan bir türü vardır. Örneğin mesaj klavyede bir tuşa basılmasından dolayı oluşmuş olabilir ya da mouse ile tek tıklama ya da çift tıklama sonucunda oluşmuş olabilir. Windows oluşan bu mesajı MSG yapısı biçiminde ifade ederek programın mesaj kuyruğuna yerleştirir. Her programın(32 bit Windows sistemlerinde aslında her alt işlemin) bir mesaj kuruğu vardır. Mesaj kuyruğu aslında MSG türünden bir yapı dizisi biçimindedir. MSG yapısı şöyledir:

typedef struct tagMSG {     // msg 
    HWND   hwnd;      
    UINT   message;
    WPARAM wParam;
    LPARAM lParam;
    DWORD  time;
    POINT  pt;
} MSG;


Devamı... Unknown 0 yorum