Herşeyden önce bu isteğimizi gerçekleştirmek için isteğimizi uygulayacağımız
bir sınıfa sahip olmamız gerekir. Ne yazık ki standart ProgressBar sınıfı
“sealed” olduğu için ben sınıfımı Control sınıfından türettim:
public class XPProgressBar:Control
{
}
public class XPProgressBar:Control
{
}
Daha sonra yapmamız gereken standart ProgressBar özelliklerini (Maximum,
Minimum, Value, Step) özelliklerini sınıfımıza uygulamaktır. Bu özelliklerin
hepsi integer’dir. Kolay olduğu için bu kısmı geçiyorum. Dikkat edilmesi
gereken nokta Value özelliğine bir değer geçerken sınıf örneğimizin yeniden
boyanmasını sağlamaktır. Bunu da Refresh() fonksiyonu ile yapabiliriz.
Uygulamamızın amacı XP sitillerinin uygulanması olduğu için Style isminde bir
özellik tanıtırız. Bu özellik Normal ve System isimlerinde iki enum değeri
tutar. Eğer özelliğimizin değeri System ise XP sitili uygulanır.
public Styles Style
{
get {<return FStyle;}
set
{
FStyle=value;
Refresh();
}
}
public Styles Style
{
get {<return FStyle;}
set
{
FStyle=value;
Refresh();
}
}
Şimdi sınıfımızın boyanması için OnPaint metoduna geçebiliriz. İlkönce
Normal değerini görelim.
<SPANSTYLE16739"
?? New="FONT-SIZE:9PT;COLOR:BLUE;FONT-FAMILY:'COURIER
designtimesp="protected<SPANSTYLE16740"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" override void OnPaint(PaintEventArgs e)
{
{
<SPANSTYLE16749"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" Rectangle rect =
ClientRectangle;
<SPANSTYLE16753"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" rect.Width-=6;
<SPANSTYLE16757"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" rect.Height-=6;
<SPANSTYLE16761"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" if(Maximum!=Minimum)
{
rect.Width =(Value-Minimum)*100/(Maximum-Minimum)*rect.Width/100;
}
{
rect.Width =(Value-Minimum)*100/(Maximum-Minimum)*rect.Width/100;
}
<SPANSTYLE16778"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" if(Style==Styles.Normal)
{
ControlPaint.DrawBorder3D(e.Graphics,ClientRectangle,Border3DStyle.Sunken);
{
ControlPaint.DrawBorder3D(e.Graphics,ClientRectangle,Border3DStyle.Sunken);
<SPANSTYLE16794"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" rect=new Rectangle(new
Point(rect.X+3,rect.Y+3),rect.Size);
<SPANSTYLE16800"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp="
e.Graphics.FillRectangle(Brushes.Blue,rect);
}
else
{
//Burada Styles.System değerini uygulayacağız.
}
}
}
else
{
//Burada Styles.System değerini uygulayacağız.
}
}
Yukarıdaki kodda yapılan Maximum ve Minimum değerlerine göre boyanacak
alanın bulunup daha sonra boyanmasıdır. Dikkat edeceğiniz gibi segment şeklinde
değil de düz boya şeklinde boyanmıştır. Eğer isterseniz bu aşamada bileşenimizi
test edebilirsiniz.
Dikkat edeceğiniz gibi standart bir ProgressBar’ın yapacağı işlemleri
gerçekleştirdik. Şimdi asıl amacımız XP sitillerinin uygulanması olduğuna göre
bu aşamaya geçelim.
Öncelikle kullandığımız işletim sisteminin yapacağımız bu işlemi
desteklemesi için Windows XP olması lazım. Bunu nasıl anlayacağımızı görelim:
<SPANSTYLE16846"
?? New="FONT-SIZE:9PT;COLOR:BLUE;FONT-FAMILY:'COURIER
designtimesp="bool<SPANSTYLE16847"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" IsThemedos()
{
if(Environment.OSVersion.Platform != PlatformID.Win32NT
{
if(Environment.OSVersion.Platform != PlatformID.Win32NT
<SPANSTYLE16859"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" ||
Environment.OSVersion.Version.Major < 5
<SPANSTYLE16863"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" ||
Environment.OSVersion.Version.Minor < 1)
<SPANSTYLE16867"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" return
<SPANSTYLE='COLOR:BLUE'false;
<SPANSTYLE16873" ?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp="
<SPANSTYLE16876"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" return
<SPANSTYLE='COLOR:BLUE'true;
}
}
Yukarıdaki fonksiyonda yapılan kullanılan işletim sisteminin version
numaralarına bakarak Windows XP olup almadığını anlamaktır. Eğer değilse
program XP sitillerinin kullanımına izin vermeyecektir.
Şimdi burada bir ara verip XP sitillerinin kullanımına olanak veren
WinApi leri tanıtmak istiyorum. Öncelikle kullanacağımız dll “UxTheme.dll” dir.
Bizim bu programda kullanacağımız 4 tane WinApi fonksiyonu var. Şimdi bunları
tanıyalım:
HTHEME OpenThemeData( HWND hwnd,LPCWSTR
pszClassList);
Bu fonksiyon bir window için ilgili sınıfın datasını açar. Dönüş değeri
IntPtr dir. “pszClassList” parametresi ise kullanacağımız sınıfın string değeridir.
Bizim örneğimizde bu değer "PROGRESS" dir.
BOOL IsAppThemed(VOID);
Bu Api bir kontrol fonksiyonudur. uygulamamızın visual sitilleri uygulayıp
uygulamayacağını sorgular.
BOOL IsThemeActive(VOID);
Bu da başka bir kontrol fonksiyonudur. Visual sitillerin uygulamamız
için aktif olup olmadığını denetler.
HRESULT DrawThemeBackground(
HTHEME hTheme,
<SPANSTYLE='FONT-SIZE:12PT' HDC hdc,
<SPANSTYLE='FONT-SIZE:12PT' int iPartId,
<SPANSTYLE='FONT-SIZE:12PT' int iStateId,
<SPANSTYLE='FONT-SIZE:12PT' const RECT *pRect,
<SPANSTYLE='FONT-SIZE:12PT' const RECT *pClipRect
<SPANSTYLE='FONT-SIZE:12PT');
Uygulamamızın belki de en can alıcı Api si budur. Bu fonksiyonla visual
sitillerin çizim işlemini gerçekleştiriyoruz. Dönüş değeri integer dir.
Parametrelerine gelince:
hTheme: OpenThemeData fonksiyonu ile elde ettiğimiz IntPtr değerini kullanacağız.
hdc: Controlümüzün hdc değeri. <SPANSTYLE16960" ??
New="FONT-SIZE:10PT;FONT-FAMILY:'COURIER
designtimesp="CreateGraphics().GetHdc() ile elde edilir.
iPartId ve iStateId: Bu parametreler çizeceğimiz kontrolün bölümlerini
ifade eder. Visual Studio nun yardım indeksi bölümüne “Parts and States”
yazarsak konuyla ilgili dökümanı bulabiliriz. Bu durumda Controlümüzün arkaplanını
çizeceksek iPartId 1 değerini, eğer öndeki ilerleme bölümünü çizeceksek 3 değerini
almalıdır. StateId değeri ise ProgressBar için kullanılmaz. Eğer dökümanı iyice
incelersek yapacağımız diğer uygulamalarda XP sitillerini nasıl uygulayacağımız
kolaylıkla anlaşılır.
pRect ve pClipRect: <SPANSTYLE='MSO-SPACERUN:YES' Bu parametreler
<SPANSTYLE='MSO-SPACERUN:YES' çizeceğimiz dörtgen bölümü ifade eder.
ClipRect “null” değerini alabilir.
Şimdi programımıza geri dönüp anlattığımız Api lerin kullanımına
geçebiliriz. Öncelikle sınıfımızın yapıcısında <SPANSTYLE='MSO-SPACERUN:YES'
OpenThemeData apisini kullanarak XP sitilimizin değerini tutabilirz. Daha sonra
sınıfımızın OnPaint metodunda boş bıraktığımız “else” ifadesini dolduralım.
<SPANSTYLE16974"
?? New="FONT-SIZE:9PT;COLOR:BLUE;FONT-FAMILY:'COURIER
designtimesp="if<SPANSTYLE16975"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp="(IsThemedos() && IsAppThemed() &&
IsThemeActive())
{
DrawThemeBackground(e.Graphics,1,1,ClientRectangle);
DrawSystemSegments(e.Graphics,rect);
}
{
DrawThemeBackground(e.Graphics,1,1,ClientRectangle);
DrawSystemSegments(e.Graphics,rect);
}
<SPANSTYLE16994"
?? New="FONT-SIZE:9PT;COLOR:BLUE;FONT-FAMILY:'COURIER
designtimesp="private<SPANSTYLE16995"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" void DrawSystemSegments(Graphics g, Rectangle rc)
{
int segwidth = 8;
{
int segwidth = 8;
<SPANSTYLE17008" ?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp="
<SPANSTYLE17011"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" int Count =
((rc.Width)/(segwidth+2))+((rc.Width<=0)?0:1);
<SPANSTYLE17016" ?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp="
<SPANSTYLE17019"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" Rectangle rect = new
Rectangle(3,3,Count*(segwidth+2),rc.Height);
<SPANSTYLE17024"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" if
(rect.Width>(Width-2*3))
{
{
<SPANSTYLE17033"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" rect.Width = rc.Width;
<SPANSTYLE17038"
?? New="FONT-SIZE:9PT;FONT-FAMILY:'COURIER
designtimesp=" }
DrawThemeBackground(g,3,1,rect);
}
DrawThemeBackground(g,3,1,rect);
}
Öncelikle kontrolümüzün arka planını çizdik. Daha sonra
DrawSystemSegments fonksiyonu ile segmentleri hesaplayıp sonra da bunu
çizdirdik.
Hiç yorum yok:
Yorum Gönder