Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Zeki Yuğnak
Zeki Yuğnak
http://www.csharpnedir.com/
İletişme geçmek için tıklayın.
4 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler:  C++ / C++.NET Zeki Yuğnak
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Orta
Kategori : C++ / C++.NET
Yayınlanma Tarihi : 19.8.2003
Okunma Sayısı : 23106
Yorum Sayısı : 0     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 10.8.2022
Turhal Temizer
Mac OS/X Removing CUDA 10.8.2022
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
Double-Buffering Yöntemi ile Titremeyi(Flicker) Önlemek (C++.NET)
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Bu yazımda sizlere Double Buffering yöntemini kullanarak titreme sorunundan nasıl kurtulabileceğinizden bahsedeceğim.İlk olarak titreme sorununun oluşmasının sebeblerinden bahsedelim isterseniz.MFC veya WinApi ile çizim işlemleri yapmış arkadaşlarında bildiği gibi,çizimlerimizi herzaman WM_PAINT mesajı içerisinde çizeriz.Bu işlemi gerçekleştirmemizin sebebi ise şudur.Bir pencere içerisinde yapılan işlemlerin hiç biri windows tarafından saklanmaz.Yani pencereyi yerleğiştirdiğimizde veya yenilediğimizde şekillerimizin silindiğini görürüz.Şekillerin silinmemesinden programcı kendisi sorumludur.Pencere her yenilendiğinde paint mesajı işlenir ve bu mesaj içerisinde yapılmış işlemler ekrana yansıtılır ve diğer farklı dc nesneleri ile yaptığımız çizimlerin hepsi silinir.

Görünüme her yeni eklediğimiz çizim işleminden sonra çizimlerin aktif olabilmesi için yine bizim paint mesajını çağırmamız gerekir.Aksi takdirde yaptığımız değişikliklerin hiç biri görünümde işlenmez. Eğer bir şekli hareket ettiriyorsak veya görünümde bulunan çizimleri silmek istiyorsak bunun için görünüm bölümünü boş küme haline getirip daha sonra paint mesajını çağırmamız gerekir.Görünümü boş küme haline getirmemizin sebebi ise, paint mesajı buna bakarak görünümü silip silmeyeceğine karar verir. Bu sayede görünümü istediğimiz şekilde silebiliriz. Fakat bu nokta da bir sorun çıkmaktadır. Bu işlemi üst üste tekrladığımızda, her defasında görünüm silindiği için titreme meydana gelmektedir.Görünüme fazla çizim yaptığımızda ise bu sorun çizim işlemlerini zorlaştırmakla birlikte, iyi bir görünüşte sunmamaktadır.

Paint mesajını iki şekilde çağırabiliriz.UpdateWindow() ve InvalidateRect() fonksiyonları ile.UpdateWindow fonksiyonu çağırdığımızda direk olarak paint mesajını işler ve görünümün tamamını yeniler.Fakat InvalidateRect fonksiyonunun kullanım şekli biraz daha farklıdır.Bu fonksiyonla görünümü istediğimiz boyutlarda bir dikdörtgensel alan haline getirebiliriz.Fonksiyonun ilk parametresi güncelleme alanı olarak belirlenecek bu dikdörtgensel bölgeyi belirtir.Bu parametreye NULL değerini veririsek tüm görünüm bölümünü belirtmiş oluruz.İkinci paremetresi ise paint mesajının zemini silip silmeyeceğine karar verir.False değerini verirsek görünüme yapılan çizimleri eklenir fakat zemini silmez.Biz bu yöntemde false değerini kullanacağız fakat zemin silinmediği için bir kaç şey eklememiz gerekecek birazdan bundan bahsedeceğim.Aşağıda bu fonksiyonun prototipini görebilirsiniz.

BOOL InvalidateRect(const RECT *lpRect, BOOL bErase);
Eski çizimlerin silinebilmesi için bir buffer kullanacağız.Her yeni çizimden sonra buffer i istediğimiz boyutta oluştutup,yeni çizimlerimizi bu buffer da saklayacağız ve görünüme bunu yapıştıracağız.Zemini silmediğimiz için hiç bir titreme olmayacak , eski çizimler ekranda duracak fakat bizim için bu sorun olmayacak çünkü , biz her yeni çizimde buffer i yeniden oluşturduğumuz için ve eski görünümün üzerine yapıştırdığımız için sadece yeni çizdiğimiz şekiller görünümde çizilecek.Bu işlem windows tarafından çok hızlı yapıldığı için bu esnada hiç bir titreme meydana gelmez.Bu yönteme Double Buffering yöntemi adı verilir. Eğer tek bir buffer değilde bunun yerine iki buffer kullanırsak bu yönteme de Triple Buffering adı verilir. Şimdi bunu biraz kodla anlatmaya çalışalım.

CDC dc //Ana dc değeri CBitmap buffer; //buffer CDC bufferdc; //Buffer dc nesnesi
Görünüme çizim yapabilmemiz için bir dc nesnesine ihtiyaç duyarız. Bu nesneyi CDC sınıfnı kullanarak oluştururuz. Bu sınıf içerisinde çizim fonksiyonları ve daha bir çok faydalı fonksiyonlar bulunmaktadır.İlk olarak çizim yapmak için bir dc nesnesi oluşturduk.Bir alt satırda çizimleri saklayacağımız, yukardada bahsettiğmiz bufferımızı oluşturduk (buffer).Buffer için burda bir bitmap kullandık.Çizimlerimizi bu bitmap üzerinde saklayabiliriz.Yine buffer üzerinde çizimleri yapabilmemiz içinde bir dc nesnesine ihtiyacımız var ve nesnemizi burda oluşturduk (bufferdc).

CRect rc; GetClientRect(&rc); //görünümün boyutlarını alıyoruz. //buffer’ı yaratıyoruz. bufferdc.CreateCompatibleDC(dc); //görünümün boyutları ile aynı olacak bir bitmap olusturduk buffer.CreateCompatibleBitmap(&bufferdc,rc.Width(),rc.Height());
//buffer arabiriminde bu bitmap i seçtik bufferdc.SelectObject(&buffer);
Yukarda da bahsettiğim gibi eski şekillerin görünümden silinebilmesi için her yenilemede buffer’ı görünüme yapıştırmamız gerekir.Bu sebebten dolayı buffer ın boyutları görünümün boyutları ile aynı olmak zorundadır.Görünümün boyutlarını almak için CRect sınıfından bir nesne türettik (rc).Sonrada GetClientRect fonksiyonu ile görünümün boyularını bu türettiğimiz nesneye aldık.Buffer için oluşturduğumuz nesneyi kullanabilmek için yukarda türettiğimiz ana dc ye bağlı olarak yarattık.Alt satırda ise görünümün boyut değerleriyle eşit ve bufferdc ye bağlı olacak şekilde bitmap’ ımızı yarattık.Sonrada bunu kullanabilmek ve üzerinde işlem yapabilmek için bufferdc ye seçtik.

CBitmap image; //resmi okuyacağımız bitmap BITMAP bitmap; //resmin özelliklerini tutan yapı //dosyadan resmi okuyoruz. image.m_hObject=(HBITMAP)LoadImage(theApp.m_hInstance,m_file,IMAGE_BITMAP,0,0, LR_LOADFROMFILE|LR_DEFAULTSIZE); image.GetObject(sizeof(bitmap),&bitmap); //resmin özelliklerini alıyoruz
Burada görünüme çizceğimiz resim için bir bitmap nesnesi türetiyoruz ve sonrada resmimizi bu bitmap üzerine okuyoruz.Yalnız burda bir değişken daha kullandık (bitmap).Bu değişkeni BITMAP yapısından türettik.Bu değişkeni, dosyadan okuduğumuz resimin özelliklerini (boyutlarını,tipini vb..) öğrenmek için kullanacağız.

Resmin özelliklerini elde etmek için CBitmap sınıfında bulunan GetObject fonksiyonunu kullandık.Bu fonksiyona parametre olarak türettimiz BITMAP yapısından türettiğimiz değişkenimizin adresini verdik.Fonksiyon içerisinde adresini aldığı yapıya gerekli özellikleri yerleştirecektir.

CDC usedc; //çizim yapacağımız dc usedc.CreateCompatibleDC(&bufferdc);//çizim yapacağımız dc yi yarattık usedc.SelectObject(&image);//dosyadan okuduğumuz resmi seçtik
Yukarıdaki kodta ise dosyadan okuduğuz resmin üzerirnde işlem yapmak için bir dc değerine ihtiyacamız olacağından yine CDC sınıfından bir nesne türettik.Bu nesneyi yaratırken,resmi buffer üzerine çizeceğimiz için bufferdc ye bağlı olacak şekilde yarattık.Son satırdada dosyadan okuduğumuz resmi yarattığımız dc nesnesine seçtik.

//dosyadan okuduğumuz resmi buffer a yapıştırdık memdc.BitBlt(m_pt.x,m_pt.y,bitmap.bmWidth,bitmap.bmHeight,&usedc,0,0,SRCCOPY); //bufferı da ekrana yapıştırdık dc->BitBlt(0,0,rc.Width(),rc.Height(),&memdc,0,0,SRCCOPY);
Yaptığımız bütün bu işlemlerden sonra sıra bunları görünüme çizmeye geldi.Yukarıdaki kodda ilk olarak resmimizi seçtiğimiz dc nesnesini buffer’a yapıştırıyoruz. Resmin boyutlarını önceden BITMAP türünden olan değişkenimize atmıştık ve burda bu değişkenimizden yararlanarak,resmin boyutlarına bağlı kalarak resmimizi yapıştırdık.Son olarakta buffer’ı, görünüme çizim yapmak için en üstte tanımladığımız dc nesnemize çizdik. Çizimlerimizin görülebilmesi için bu işlemlerin her yenilemede yapılması gerekmektedir.

Siteden indirebileceğiniz,örnekte bu işlemin uygulanmış şeklini görebilirsiniz. Programda buffer’ı açmak için menüden buffer seçeneğini seçiniz.Bundan sonra titremenin yok olduğunu görebilirsiniz.İYİ ÇALIŞMALAR.....

Örnek kaynak uygulamayı indirmek için tıklayın.

Zeki Yuğnak
Erciyes Üniversitesi
Elektronik Mühendisliği

 

Makale:
Double-Buffering Yöntemi ile Titremeyi(Flicker) Önlemek (C++.NET) C++ ve C++.NET dili Zeki Yuğnak
  • Yazılan Yorumlar
  • Yorum Yaz
Bu konu hakkında yayınlanan yorum bulunmamaktadır.
"Yorum Yaz" tabını kullanarak sizde yorumlarınızı yazabilirsiniz.
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor