BilgiTeknoloji.net    
b i l g i   t e k n o l o j i   y a z ı l ı m

Ana Sayfa

Marjinal XML Access Pratik Uygulamalar Projeler Ekonometri Dilimiz Editörden Çetrefil İletişim
 

Saydam Pencereler


Saydam ve yarı saydam pencereler oluşturmak eski Windows'larda olmayan olan bir özellik. Windows 2000 ile birlikte yarı saydam pencerelerin oluşturulması, pencerelerin yavaşça görünür hale gelmesi gibi özellikler arayüzü hoş bir hale getiriyor.

Bu yazıda saydam pencerelerin nasıl oluşturulacağı ve Windows'taki bölge tanımlayıcılarının nasıl kullanıldığı hakkında bilgiler yer alıyor.


• Saydam Pencereler Oluşturmak
• Renk Saydamlığı
• Windows’ta Bölge Tanımları
• Bölgeleri Katıştırmak
• Ay Yıldız Pencere Oluşturmak
• Bölgelerin Tersini Almak


2000 sürümü sonrasında Windows'un arayüzü ile ilgili önemli değişiklikler yapılmıştır. Bunlardan biri bileşenlerin saydamlaştırılabilmesidir. Masaüstündeki simgeleri taşırken geçişli yarı saydamlık oluşturulması, komut listeleri açılırken pencerenin yavaşça görüntülenmesi bu değişikliklerin sonuçlarından yalnızca ikisidir.


SAYDAM PENCERELER OLUŞTURMAK

Pencerelerin saydamlığı temelde iki çeşittir. Bir renk belirtilerek bu renge sahip yerlerin görünmemesi ve aynı zamanda pencerenin görünen kısımlarının herhangi bir oranda saydamlaştırılması sağlanabilir.

Delphi6'da olmasına rağmen VB için ancak .NET sürümü ile gelen AlphaBlend özelliği saydam pencereler oluşturmayı kolaylaştırmıştır.

Doğrusu VB6'da bunu yapmak için yeni sürümü beklemeye gerek yoktu. Windows saydamlıkla ilgili çeşitli APİ işlevleri sunuyor.

Windows 2000 ile birlikte gelen SetLayeredWindowAttributes işlevi pencereleri saydamlaştırır. (Bu, eski Windows'larda aşağıdaki kodların ve ekteki örnek uygulamaların doğru çalışmayacağı anlamına geliyor.)


[VB6]

Const gorunurluk = 120 'En çok 255

Dim stil As Long
stil = GetWindowLong(HW, GWL_EXSTYLE)

If (stil And WS_EX_LAYERED) = 0 Then _
   SetWindowLong HW, GWL_EXSTYLE, stil Or WS_EX_LAYERED

SetLayeredWindowAttributes HWND, 0, gorunurluk, LWA_ALPHA


[Delphi6]

var
  stil: Integer;
  key: cardinal;

const
  gorunurluk = 120;

begin

  stil := GetWindowLong(Handle, GWL_EXSTYLE);

  key:=0;
  if chkAlpha.checked then key:= (key or LWA_ALPHA);

  if (stil and WS_EX_LAYERED) = 0 then
    SetWindowLong(Handle, GWL_EXSTYLE, stil or WS_EX_LAYERED);

  SetLayeredWindowAttributes(Handle, 0, gorunurluk, LWA_ALPHA);


Bu kod ile pencere görünürlük değeri oranında saydamlaşıyor.

Pencereler tam olarak görüntülendiklerinde görüntülenme değeri 255'tir. Bunu 0 yapmak pencereyi tamamen gizler.


RENK SAYDAMLIĞI

Pencerenin tamamını saydamlaştırmak yerine belirtilen bir renge ait bölgelerin tamamen gizlenmesi de sağlanabilir.

Yukarıdaki kodda SetLayeredWindowAttributes işlevinin bulunduğu satırları aşağıdaki gibi düzenlemek yeterlidir.

[VB]
SetLayeredWindowAttributes HWND, ColorDialog1.Color, 255, LWA_COLORKEY

[Delphi]
SetLayeredWindowAttributes(Handle, ColorDialog1.color, 255, LWA_COLORKEY);

Ekteki Saydam uygulamasının Hakkında kutusunda beyaz kısımları gizledik. Pencere üzerinde karmaşık resimler olduğunda bile renk doğru ve hızlı bir şekilde gizleniyor.

Kutuyu sağ tuşla tıkladığınızda pencere yavaşça kaybolacak. Tabii bu bir saat bileşeni içinde AlphaBlendValue özelliğini azaltmaktan başka bir şey değildi.


WİNDOWS'TA BÖLGE TANIMLARI

Windows pencerelerin ekranda kapladıkları bölgeyi HRGN (handle of region) türündeki genel bölge belirteci ile tanımlar. Bir bölge dörtgen, elips, oval, çokgen ve bunların herhangi şekildeki birleşimi olabilir.

Çözümü pek mümkün görünmeyen Logo Puzzle oyununda pencereyi bu yolla çerçevelendirmiştik.

Dörtgen oluşturmak için birkaç APİ işlevi mevcuttur. Basit bir dörtgen CreateRectRGN, eğik yuvarlak ya da bir çember oluşturmak da CreateEllipticRgn ile yapılabilir.

Bir bölgeyi oluşturmak pencereleri ya da diğer şeyleri şekillendirmek için yeterli değildir. Bunu pencereye uygulamak gerekir. HRGN’nin işaret ettiği adreste yalnızca bölgenin tam olarak nasıl tanımlandığını ifade eden bilgiler yer alır. Bir dörtgen ya da çokgen için kenarlara ait noktalar bu adreste saklanır.


[Delphi]

procedure TForm1.Button1Click(Sender: TObject);
var
  bolge: HRGN;
begin
  bolge:=CreateEllipticRgn(0,0,Width,Height);
  SetWindowRgn(handle,bolge,true);
end;


[VB]

Private Declare Function CreateEllipticRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long

Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long

Private Sub Command1_Click()
  ScaleMode = vbPixels
  Dim bolge As Long
  bolge = CreateEllipticRgn(0, 0, ScaleWidth, ScaleHeight)
  SetWindowRgn hWnd, bolge, True
End Sub



Dörtgen dışındaki bölgeler ise CreateRoundRectRgn, CreateEllipticRgn, CreatePolygonRgn, CreatePolyPolygonRgn gibi işlevlerle oluşturuluyor. Bunların herbiri oval, elips, çokgen türünde bölgeler üretiyor.

Tabii bir form penceresini bu işlevler kullanılarak çokgen, yıldız ya da karmaşık bir başka şekle sokulabilir.


BÖLGELERİ KATIŞTIRMAK

Bölgeler belli genel şekillerde olmayıp yukarıda belirtilenlerin birleşimi, kesişimi, farkları alınarak oluşturulabilirler. Bu işlem CombineRGN işlevi ile yapılır. CombineRGN sırayla sonuç bölgesini, birinci ve ikinci bölgeleri ve katıştırma tipini geçiş değişkeni olarak almaktadır.

Örneğin birinci ve ikinci bölgenin birleşiminin alınması için katıştırma değerini RGN_OR yapmak gerekir. Ayrıca CombineRGN’den önce sonuç bölgesi tanımının herhangi bir şekilde yapılmış olması gerektiğini bilmelisiniz. Aşağıdaki kodda sonuç bölgesi CreateRectRGN ile rasgele bir şekilde tanımlanıyor ve CombineRGN satırında birinci ve ikinci bölgeler RGN_OR ile birleştiriliyor.

bolge:=CreateRectRgn(0,0,0,0);
bolge1:=CreateEllipticRgn(0,0,clientWidth,clientHeight);
bolge2:=CreateRectRgn(30,30,ClientWidth-30,ClientHeight-30);
CombineRGN(bolge,bolge1,bolge2,RGN_OR);

CombineRGN katıştırma yöntemi olarak RGN_AND, RGN_COPY, RGN_DIFF, RGN_OR, RGN_XOR değerlerini alabiliyor.

Yukarıdaki kodda bir daire ve dörtgen birleştiriliyor. Aşağıdaki resimlerde bunu görebilirsiniz.


AY YILDIZ PENCERE

Bölgelerin farkını almak çok çeşitli geometrik şekiller üretmenizi sağlayabilir. Örneğin ay şekilde bir pencere oluşturmak için kısmen çakışan iki dairenin farkını almak yeterlidir. Ya da yıldız şeklinde bir bölgeyi, köşe noktalarını doğrudan belirterek oluşturmak mümkündür.

var
  ay, ayparca1, ayparca2: HRGN;
begin
  ay:= CreateEllipticRgn(0,0,0,0);
  ayparca1:= CreateEllipticRgn(0,0,554,554);
  ayparca2:= CreateEllipticRgn(140,0,682,554);
  CombineRgn(ay,ayparca1,ayparca2,RGN_DIFF);

Bir ay ve yıldız tanımlanıp bunları CombineRGN ile birleştirdiğinizde oluşacak görüntü tabii ki bu ikisinin birleşimi şeklindedir.

var
  ayyildiz, yildiz: HRGN;
  yildiz_noktalar: array of TPoint;

begin
  ...
  SetLength(yildiz_noktalar,10);
  yildiz_noktalar[0]:= Point(415,126);
  yildiz_noktalar[1]:= Point(445,215);
  yildiz_noktalar[2]:= Point(541,215);
  yildiz_noktalar[3]:= Point(463,272);
  yildiz_noktalar[4]:= Point(492,360);
  yildiz_noktalar[5]:= Point(415,306);
  yildiz_noktalar[6]:= Point(338,360);
  yildiz_noktalar[7]:= Point(367,272);
  yildiz_noktalar[8]:= Point(289,216);
  yildiz_noktalar[9]:= Point(386,216);
  yildiz:= CreatePolygonRgn(yildiz_noktalar[0],10,ALTERNATE);

  ayyildiz:= CreateRectRgn(0,0,0,0);
  CombineRgn(ayyildiz,ay,yildiz,RGN_OR);


Bölge tanımlandığında bunu pencereye uygulamayı unutmayın.

SetWindowRgn(handle,ayyildiz,true);


Bölge tanımlarının tersini almak da yukarıdakilerden farklı değildir. Bölgenin içinde bulunduğu dış pencere, bu bölge için evrensel küme olarak kabul edilebilir. Dış pencere bölgesi ile bu bölgenin farkı, bölgenin tümleyenini yani tersini verir.


var
  cerceve, bolge: HRGN;
begin
  ..
  cerceve:=CreateRectRgn(0,0,width,height);
  CombineRGN(bolge,cerceve,bolge,RGN_DIFF);

  SetWindowRgn(handle, bolge, true);


Ekteki Bölge uygulamasında çerçeve şekli görüntülenip Ters Çevir komutu ile çerçevenin tersi görüntülendi. (Aşağıdaki resim, üstte ortadakinin tersi.)

DOSYALAR:
bolge.exe
(zip, 201 kb.)
saydam_delphi.exe
(zip, 261 kb.)
saydam_vb.exe
(zip, 13 kb.)
bolge_kod.zip
saydam_delphi_kod.zip
saydam_vb_kod.zip


Serkan ŞAHİNOĞLU
(
Chip Dergisi, Mart 2003)


http://BilgiTeknoloji.net