You are on page 1of 347

BU DKMAN KAAN ASLAN TARAFINDAN C VE SSTEM PROGRAMCILARI DERNENDE VERLEN C# LE .

NET ORTAMINDA UYGULAMA GELTRME KURSUNDAK DERS ERS NDE TUTULAN NOTLARDAN OLUMAKTADIR. NOTLAR ZERNDE HBR DZELTME YAPILMAMITIR

C# UYGULAMALARI TEMEL
Dispose Kalb ve IDisposable Arayz: C# da biti fonksiyonu p toplayc tarafndan nesne bellekten silinmeden hemen nce arlr. Biti fonksiyonlarnn isimleri ~<snf ismi> biimdedir. Snfn tek bir biti fonksiyonu bulunabilir. Sfr parametresi olmak zorundadr. Biti fonksiyonu kavram ileyi ve isim olarak C++ dan aktarlmt r. Fakat C++ da biti fonksiyonlar deterministiktir. Yani biti fonksiyonlarnn hangi noktada arlaca kesinlikle bilinmektedir. Fakat C# daki biti fonksiyonlar deterministik deildir. Yani nesne seilebilir duruma geldikten sonra tam olarak nesnenin ne zaman silinecei dolaysyla biti fonksiyonunun arlaca nceden belli deildir. Bu nedenle C# da biti fonksiyonlar C++ daki kadar yo un kullanlmamaktadr. Bazen snfn balang fonksiyonu iinde kritik baz kaynaklar tahsis edilmi olabilir. Referansn kullanm bittikten sonra ya da belirli bir noktada bu kaynaklarn boaltlmas gerekebilir. Bu tr boaltmlarn biti fonksiyonu iinde yaplmas ve biti fonksiyonuna braklmas iyi bir teknik deildir. te bu yzden IDisposable arayz dnlm tr. IDisposable arayz tek bir fonksiyona sahiptir. interface IDisposable { void Dispose(); } Eer bir snf ya da yap IDisposable arayzn destekliyorsa o snf ya da yapnn bir Dispose fonksiyonu vard r ve bu fonksiyon gerekli olan boaltm ilemlerini yapmaktadr. O halde biz byle bir snf ya da yap y kullanyorsak iimiz bitince Dispose fonksiyonunu armalyz. Genellikle IDisposable arayzn destekleyen snflarda ve yaplarda tasarmc bir biti fonksiyonu da yazm tr ve biti fonksiyonunda da bo altm yapmtr. Bu nedenle programc Dispose ilemini bilinli olarak yapabilir. Kaynaklar biti fonksiyonu sayesinde ve p toplayc sayesinde iade edilecektir. Fakat kaynak boaltmnn baz nemli ayrntlar vardr. Kaynaklar managed, unmanaged olmak zere iki ksma ayrlmaktad r. Unmanaged kaynaklar iletim sistemi dzeyinde CLR nin kontrol dnda tahsis edilmi kaynaklard r. Bu tr kaynaklar sistem fonksiyonlar ya da API fonksiyonlar arlarak tahsis edilmektedir. Managed kaynaklar CLR nin kontrol altndaki kaynaklardr. Bir snfn bakabir snf kullanmas durumunda kullanlan kaynaklar managed kaynaklardr. rnein bir B snf bir A snf trnden bir nesneyi yaratarak kullanyor olsun birde do rudan API fonksiyonlar ararak tahsis ettii unmanaged kaynaklar kullanyor olsun. imdi biz B snf trnden nesnenin boaltlmas ileminde iki eyden sorumluyuz. Birincisi unmanaged kaynaklarn boaltlmas ikincisi A snfna ilikin tahsis edilmi nesnenin yani managed kaynaklarn boaltlmasdr. .net ordamnda bir snn baka bir snf iermesi durumunda ieren snf nesnesi seilebilir duruma geldiinde ou kez ierilen nesne de secilebilir duruma gelmektedir. class A { //... } class B { private A m_a; 1

//... public B() { m_a = new A(); //... } //... } B b = new B(); b B nesnesi a ... A nesnesi ...

Burada B nesnesi seilebilir duruma geldiinde A nesnesi de seilebilir duruma gelmektedir. te p toplaycnn nce A nesnesinimi yoksa B nesnesinimi boaltaca bir kurala balanmam tr. rnein nce A nesnesi sonra B nesnesi heap ten silinebilir. Bu durumda nce A nesnesi iin sonra B nesnesi iin biti fonksiyonlar arlacaktr. Bu nedenle elemana sahip snfn biti fonksiyonunda elemana ilikin referansn kullanlmas sorunlara yol aabilmektedir. phesiz snfn deer trlerine ilikin veri elemanlarnn biti fonksiyonunda kullanlmasnda bir saknca yoktur. Bir snfn hem managed(yani baka snf trnden bir veri elemannn olmas durumu) ve unmaneged kaynaklara sahip olmas durumunda onlar nasl dzenli boaltlabilir. te bu kalba Disposa kalb (Dispose Pattern) denilmektedir. Snf unmanaged kaynak kulland na gre IDisposable arayzn desteklemesi iyi olur. Boaltma ilemi hem Dispose fonksiyonunda hem biti fonksiyonunda yap lmaldr. Bu durumda biz Dispose fonksiyonunda hem managed hem unmaneged kaynaklar ve biti fonksiyonunda ise unmanaged kaynaklar boaltmamz gerekir. Grld gibi burada her iki yerden de unmanaged kaynaklar boaltlmaktad r. Ortak ilemlerin bir fonksiyona yaptrlmas uygundur. class A { //... } class B { private A m_a; //... public B() { m_a = new A(); //... } //... } public void Dispose(bool disposing) 2

{ if(disposing) { //managed kaynaklar bo alt } // unmanaged kaynaklar bo alt } public void Dispose() { Dispose(true); } ~B() { Dispose(false); } //... } Buradaki bir problem kaynaklarn Dispose fonksiyonuyla boaltlmasyla ortaya kmaktadr. B b = new B(); //... b.Dispose(); b nesnesi iin Dispose edildii halde yine biti fonksiyonu arlacaktr. Biti fonksiyonu ikinci kez unmanaged kaynaklarn bo altlmasna yol aacaktr. Bo altlm kaynaklarn yeniden boaltlmaya almas soruna yol aar. Bunu zmenin bir yolu bir snf iinde bir bayrak(flag) tutarak bunu engellenmesidir. Fakat daha iyi bir yntem biti fonksiyonunun arlmasn engellemektir. Bu ilem GC snfnn SuppressFinalize fonksiyonuyla yap lr. public static void SuppressFinalize(object obj) O halde yukardaki kodun u ekilde dzeltilmesi gerekir. class A { //... } class B { private A m_a; //... public B() { m_a = new A(); //... } //... } public void Dispose(bool disposng) { if(disposing) { //managed kaynaklar bo alt 3

GC.SuppressFinalize(this); } // unmanaged kaynaklar bo alt } public void Dispose() { Dispose(true); } ~B() { Dispose(false); } //... } Artk Dispose fonksiyonu arldnda bouna biti fonksiyonu arlmayacaktr. Collection Snflar: Birden fazla nesneyi belli bir veri yapsn kullanarak tutan zel snflara collection snflar denilmektedir. Collection snflar liste tarz ve szlk tarz olmak zere ikiye ayrlmaktadr. .netteki tm collection snflar baz arayzleri desteklemektedir. Collection Snflar

IEnumerable

ICollection

IList

IDictionary

Collection snflarn destekledii en temel arayz IEnumarable arayzdr. Bu arayzden ICollection arayz tretilmitir. ICollection arayzndende IList ve IDictionary arayzleri tretilmitir. Liste tarz snflar IList arayzn szlk tarz snflar IDictionary arayzn desteklemektedir. rnein ArrayList snf IList arayzn desteklemektedir. Yani liste tarz bir collection snftr. IEnumerable Arayz: Bu arayz ok biimli olarak dolalabilirlii temsil etmektedir. Bu arayzn tek bir eleman vard r. interface IEnumarable { IEnumarator GetEnumerator(); } Grld gibi bu arayzn enumarator veren bir fonksiyonu vardr. IEnumarator arayznn elemanlar unlardr. Arayzn MoveNext isimli fonksiyonu sonraki elemana gei salar. bool MoveNext() 4

Fonksiyon son eleman girilmise false deerine girilmemise true deerine geri dner. Enumaratr ilk alndnda ilk elemann bir gerisinde olduu varsaylmaktadr. Dolaysyla yrme ii yle yaplabilir. while(r.MoveNext()) { //... } Arayzn bir elemanda Current isimli property dir. Object Current { get; } Bu property konumlanlm olan pozisyondaki nesne ile geri dnmektedir ya da nesneyi geri vermektedir. Reset fonksiyonu Enumaratr ilk konumuna getirir. void Reset() Eer bir snf ya da yap IEnumarable arayzn destekliyorsa biz o snf ya da yapnn tuttuu elemanlar tek tek ele geirebiliriz. O halde Enumerator yoluyla dolam yle yap labilir. int val; ien = c.GetEnumerator(); while (ien.MoveNext()) { val = (T)ien.Current; }

using System; using System.Collections; namespace CSD { class App { public static void Main() { ArrayList al = new ArrayList(); for (int i = 0; i<10; ++i) al.Add(i); IEnumerable ie = al; IEnumerator ien; int val; ien = ie.GetEnumerator(); while (ien.MoveNext()) { val = (int)ien.Current; 5

Console.WriteLine(val); } } } } Anmsanaca gibi tm diziler System.Array snfndan tretilmitir. System.Array snf da IEnumerable arayzn desteklemektedir. O halde tm dizilerde Enumerator yoluyla dolalabilir. using System; using System.Collections; namespace CSD { class App { public static void Main() { int [ ] a = {1, 2, 3, 4, 5, 6, 7, 8, 9}; IEnumerator ie = a.GetEnumerator(); while (ie.MoveNext()) { int val = (int)ie.Current; Console.WriteLine(val); } } } } foreach deyimi Ienumerable arayzn destekleyen her trl snf ya da yapyla kullanlabilir. Foreach dngsn gren derleyici aslnda ilgili dizilime GetEnumerator fonksiyonunu uygulayarak yukardaki gibi bir dng yoluyla elemanlara ular. Anahtar Notlar: Bir .exe ya da .dll ister .net sistemine ister doal alma sistemine ilikin olsun PE(Portable Exacutable) dosya formatna sahiptir. Do al exe ve dll lerde CLR header ksm yoktur. .net exe ve dll lerde bu balk ksm vard r. Dolaysyla bir exe ya da dll in .net e ilikin olup olmad hemen bu blmn varl sorgulanarak belirlenebilir. Pratik olarak ilgili exe ya da dll in ILASM program ile yklenebilirliine de baklabilir(komut satrnda debug iinde ki programlar ildasm x.exe gibi). C# standartlarna gre foreach deyiminin karl yledir. foreach (V v in x) embedded statement alm { E e = ((C) (x)).GetEnummerator(); try { V v; while (e.MoveNext()) { v = (V)(T)e.Current; embedded-statement } } 6

finally { //Dispose e } } IEnumareble arayzn destekleyen bir snf yazarsak onu bizde foreach deyimiyle birlikte kullanabiliriz. Ienumareble arayzn destekleyen bir snf yle yazlabilir. 1. Bir tane IEnumerator arayzn destekleyen bir snf olu turulur. Bu snfn collection snfn iinde private olarak bildirilmesi iyi olur. 2. Ana collection snf iin GetEnumerator fonksiyonu yazlr. Bu fonksiyon iinde Ienumerator arayzn destekleyen snf trnden nesne yaratlr ve o nesne ile geri dnlr. Nesne yaratlrken collection snfn kendi referansnn snfa geirilmesi gerekir. using System; using System.Collections; namespace CSD { class App { public static void Main() { MyCollection mc = new MyCollection(); foreach (int x in mc) Console.WriteLine(x); } class MyCollection : IEnumerable { private int[] m_array; public MyCollection () { m_array = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; } public IEnumerator GetEnumerator() { return new MyCollectionEnumerator(this); } //... private class MyCollectionEnumerator : IEnumerator { private MyCollection m_mc; private int m_index; public MyCollectionEnumerator(MyCollection mc) { m_mc = mc; m_index = -1; } public bool MoveNext() { 7

++m_index; return m_index < m_mc.m_array.Length; } public object Current { get { return m_mc.m_array[m_index]; } } public void Reset() { m_index = -1; } //... } } } } Anahtar Notlar: C# standartlarna gre bir collection snfn foreach deyimiyle kullanlabilmesi iin IEnumerable arayzn desteklemek yerine dorudan IEnumerator arayznn fonksiyonlarna sahip olmas da yeterlidir. ICollection Arayz: Bu arayz ister liste ister szlk tarz olsun her trl collection snflarn ortak elemanlarn tanmlamaktad r. Bu arayzn elemanlar unlardr. int Count { get; } Bu property eleman collection da tutulan eleman saysn elde etmekte kullanlr. void CopyTo(Array array, int index) Grld gibi her collection snfnn kendi tuttuu elemanlar ayn trden bir diziye kopyalayan bir CopyTo fonksiyonu olmak zorundadr. CopyTo fonksiyonunun 2.parametresi hedef dizideki kopyalamann balatlaca index numarasn verir. ICollection arayznn dier elemanlar MSDN dkmanlarnda izlenebilir. IList Arayz ve Liste Tarz Collection Snflar: Liste tarz snflar elemanlarn belli bir sraya gre yerletirildii ve herhangi bir index teki elemann elde edilebildii Collection snflar belirtir. ArrayList buna tipik bir rnektir. ArrayList snfnn pek ok fonksiyonu IList arayznden gelen fonksiyonlard r. IList arayznn nemli elemanlar unlard r: int Add(Object value) Add fonksiyonu collection n sonuna eleman eklemek iin kullanlr. Geri dn deeri eklenen elemann index numarasd r. void Clear() Bu fonksiyon Collection iindeki tm elemanlar silmek iin kullanlmaktad r.

void insert(int index, Object value) Fonksiyonunu 1. parametresi insert pozisyonunu ikinci parametresi insert edilecek eleman belirtmektedir. void RemoveAt(int index) Belirli indexteki eleman silmek iin kullanlr. Ilist arayznn int parametreli indeksleyicisi belirli bir elemana erimekte kullanlr. Ilist arayznn dier elemanlar MSDN dkmanlar ndan takipedilebilir. ArrayList Snfnn Baz Ayrntlar: ArrayList snfnda kapasite bytlmesi her zaman 2 kat yap lmaktad r. Balang kapasitesi int parametreli balang fonksiyonuyla belirlenebilir. ICollection parametreli balang fonksiyonu ilgili dizilimi dolaarak onun elemanlarndan ArrayList yapar. ArrayList snfndave pek ok liste tarz Collection snfnda AddRange gibi bir fonksiyon vardr. Bu fonksiyonlar birden fazla eleman eklemek iin kullanlmaktadr.Benzer biimde InsertRange gibi fonksiyonlarlada karlalmaktad r. Ilist arayznden gelen Remove fonksiyonu ArrayList iindeki belirli bir eleman arayp bulduktan sonra silmektedir. Arayp bulma ilemi ok biimli olarak Object snfnn Equals sanal fonksiyonuyla yaplmaktadr. Object snfn Equals isimli sanal fonksiyonu yledir. public virtual bool Equals( object obj) int, long gibi temel yaplar iin string snf iin zaten Equals fonksiyonlar override edilmitir. Eer biz kendi snfm z ya da yap mz iin Equals fonksiyonunu override etmezsek bu durumda object snfnn ki arlr. Object snfnn Equals fonksiyonu ise referans eitliine bakmaktadr. using System; using System.Collections; namespace CSD { class App { public static void Main() { ArrayList al = new ArrayList(); al.AddRange(new Sample[] { new Sample(1), new Sample(2), new Sample(3), new Sample(4), new Sample(5) }); al.Remove(new Sample(3)); foreach (Sample s in al) Console.WriteLine(s.A); } } class Sample { private int m_a; 9

public Sample(int a) { m_a = a; } public int A { get { return m_a; } } public override bool Equals(object obj) { Sample s = (Sample)obj; return m_a == s.m_a; } } } ValueType snfnn Equals fonksiyonu reflection ilemi uygulayarak ilgili trn byte uzunluunu elde eder ve byte byte karlatrma yapar. Windows Message System i: Windows sistemleri mesaj tabanl sistemlerdir. Anahtar Notlar: Mesaj szc daha ok aa seviyeli programlamada kullanlmaktadr. Mesaj yerine Event terimi de edeer biimde kullanlmaktad r. Mesaj tabanl sistemlerde klavye fare gibi girdi olaylar daha ilk elden iletim sistemi tarafndan ele alnr ve programcya verilir. Halbuki klasik Console tabanl almada girdi olaylar programc tarafndan elde edilmektedir. Mesaj tabanl alma modeli grafik arayze sahip iletim sistemlerinde zorunlu olarak uygulanmaktadr. Bugn Mac OS sistemleri Unix/Linux ortamlarndaki xwindow sistemleri mesaj tabanl girdi modeli kullanmaktadr. Windows iletim sistemi pencere yaratan her bir thread iin bir mesaj kuyruu olu turmaktadr. Windows klavye, fare gibi kaynaklarda olu an olaylar izleyerek bu olaylar bir mesaj biiminde ilgili thread in mesaj kuyruuna eklemektedir. rnein bir pencere zerinde farenin sol tuuna tklam olalm windows hangi pencereye tklandn tespit edecek bu pencerenin hangi programn threadi tarafndan yaratldn bulacaktr. Bu tklama olayn bir mesaj formuna dn trecek ve mesaj kuyru una ekleyecektir. Windows kuyrua yerletirdii mesajlar iin mesajn ne nedenle b rakldn anlatan bir mesaj numaras ve o olaya ilikin dier parametrik bilgileri de mesaja ekler. Windows mesaj kuyru a b rakarak mesaj konusundaki sorumluluu programcya devreder. Yani window kuyru a mesaj brakmakta ve artk baka bir eyle ilgilenmemektedir. Bir windows programnn bir dng iinde kuyruktaki mesajlar alp ilemesi gerekir. Buna programn ya da ilgili thread in mesaj dngs denilmektedir. Yani bir windows program yaamn mesaj dngsnde geirmektedir. Eer thread in mesaj kuyruunda mesaj yoksa thread bloke edilerek etkin bir biimde bekletilmektedir. Yani bir programn (thread in) o anda mesaj kuyruunda mesaj yoksa o program CPU zaman harcamamaktad r. Birwindows programnn etkin sonlanmas u biimdedir: Kullanc X ikonuna tklar. Windows mesaj kuyru unna WM_CLOSE isimli mesaj b rakr. Bu mesaj alan program mesaj dngsnden kar ve program bylece sonlanr. Mesaj tabanl sistemler de programlar tipik olarak bir mesaj dngs yoluyla kuyruktan mesajn 10

alnp ilenmesi biiminde oluturulurlar. Programc kuyrukta srada bulunan mesaj alr ve hangi olay karsnda ne yapacan belirler. Programlar ne oldu ve ben ne yapmalym biiminde yazlmaktad r. Pencere Kavram ve Pencere Terminolojisi: letim sistemi tarafndan bamsz olarak kontrol edilebilen dikdrtgensel blgelere pencere denir. letim sistemi yaratlan tm pencereleri bir biimde bir liste iinde tutmaktadr. Masa stne alan pencerelere ana pencereler(top level windows) denilmektedir. Bir pencerenin iinde grntlenen ve o pencerenin snrlar d na kamayan pencerelere alt pencereler(chil windows) denilmektedir. Alt pencerelerin alt pencereleri olabilir. Birr alt pencerenin iinde bulunduu pencereye o alt pencerenin st penceresi (parent windows) denilmektedir. st pencereleri ayn olan pencere karde pencereler( sibliny windows) denilmektedir. Aslnda en dtaki masast de bir penceredir. Bu durumda tm anapencereler karde pencerelerdir. Ve masast penceresinin alt pencereleri durumundadr. Hem alt pencere hem de ana pencere grnmnde olan zel bir pencere durumuna sahiplenilmi pencerler (owned windows) denilmektedir. Sahiplenilmi pencereler st pencerelerin dna kabilir ve ana pencere durumundadr. Bunlar hibir zaman st pencerelerin altnda grntlenmezler Sahiplenilmi pencereler ve st pencerleri minimize edildiinde onlarda minimize edilirler. Tipik olark dialog pencerleri byledir. Tipik olarak bir anapencerede bir pencere bal ve snr izgileri bulunmaktadr. Fakat bir pencere klasik olarak grdmz ana pencerelerin tm bileenlerine sahip olmak zorunda deildir. Genellikle alt pencereler balk ksmna sahip olmazlar fakat bu bir zorunluluk cdeildir. Aslnda bir pencere snr izgilerine de sahip olmak zorunda deildir. Pencere balnn altndaki izim taplabilen blgeye alma alan (client area) denilir. alma alannn sol st kesi izim alan iin orjin belirtmektedir. Bir pencere btnsel olarak grnr ya da grnmez yap labilir. Bir pencere klavye ve fare mesajlarna kapatlabilir.Bu duruma pencerenin pasif hale getirilmesi (disable) denilmektedir. Bu hale gelmi bir pencere grnr bir durumdadr. Fakat windows klavye ve fare olaylar iin kuyru a mesaj brakmaz. Alt pencereler ile ana pencerler arasnda ciddi bir ilecsel fazlalk ya da azlk yoktur. Bir thread in yaratt tm pencereleristerpencere olsun ister alt pencere oldun ayn mesaj kuyruuna ilikindir. Yani tm bu pencerler iin oluan mesajlar ayn kuyru a b raklr. Mesaj kuyruu mesaj bana bir tane deil thrread bana bir tanedir. Dolaysyla bir mesaj dngs o threadin yratt tm pencerelerin mesajlarn alp ilemektedir. Windows da mesaj kavram byk lde pencere kavramyla ilikilendirilmitir. Yani biz bir pencere yaratmadktan sonra bir mesaj kuyru u ya da bir mesaj dngs sz konusu olmamaktadr. Console ve GUI Uygulamalar: Windows uygulamalar kabaca Console ve GUI uygulamalar olmak zere ikiye ayrlmaktadr. Console uygulamalarnda program altrld nda siyah Console penceresi iletim sistemi tarafndan otomatik yaratlmaktadr. Zaten bir exe dosyann Console uygulamas olup olmad PE balk blmnde yazmaktad r. phesiz birConsole uygulamas baka bir Console uygulamas tarafndan altrldnda yeniden bir Console penceresi almayabilir. Fakat bir Console uygulamas isterse normal GUI pencereleri yaratp normal mesaj dngsne girebilir. GUI uygulamas tipik olarak pencereli programlar anlatmaktadr. Fakat teknik anlamda bir GUI programnn pencereye sahip olmas da zorunlu deildir. Yani GUI uygulamalar teknik olarak Console uygulamas olmayan uygulamalard r. Yani bir GUI uygulamas hibir pencere yaratmazsa grsel bir uygulama sergilemez. Ayrca bir GUI uygulamas ek bir Console penceresi de yaratabilir. Console uygulamas iin csc derleyicisi /target:exe GUI uygulamas iin /target:winexe dir. /target belirlemesi yap lmaz ise exe uygulamas yap ld kabul edilir. skelet GUI Program: GUI uygulamalar iin kullanlan trlerin byk ounlu u Windows.Forms.dll iinde bulunmaktadr. Bu trlerin byk ounluu yine System. Windows.Forms dolaysyla bu dll e referans edip bu isim alann using direktifi ile kullanmak 11

gerekir. Fakat microsoft izim ile ilgili system.drawing dll iine yerletirmitir. Bu isim alan da System.Drawing dir. D meler, edit alanlar, listeleme kutular gibi grsel elerde hep birer penceredir ve tm pencerelerin baz ortak eleri vard r. Pencerelerin ortak elerinin hepsi kontrol snfnda toplanmtr. Programlama penceresi kontrol snfndan dolayl olarak tretilmi form snfyla temsil edilmektedir. Control

Form

skelet GUI program yledir. u dll lere referans yap lacaktr. System.dll, System.Windows.dll, System.Drawing.dll Application snfnn static Run fonksiyonlar mesaj dngsn olu turmaktadr. Yani bu fonksiyon dngsnde mesaj kuyruundan mesaj alnarak sradaki mesaj ilenir. Windows programnn sonlanmas iin bu fonksiyonun geri dnmesi ve Main fonksiyonunun bitmesi gerekir. Anapnecerenin yaratlmas Form snfndan bir nesne yaratmakla otomatik yap lmaktadr. Fakat bir takm eklemeler yapabilmek iin form snfn dorudan deilde treterek kullanmak daha dorudur. using System; using System.Windows.Forms; using System.Drawing;

namespace CSD { class App { public static void Main() { MyForm mf = new MyForm(); Application.Run(mf); } class MyForm : Form { public MyForm() { //... } //... } } } 12

Application snfnn parametresiz ve form trnden parametre alan Run fonksiyonlar vard r. skelet programda biz form parametreli Run fonksiyonunu kullandk. Bu fonksiyon ayn zamanda pencereyi visible (grnr) duruma da getirmektedir. Prametresiz Run fonksiyonu kullanldnda Form nesnesi yaratldnda pencere yaratld nda ama grnr deildir. Anapencereyi grnr hale getirmek iin Control snfndan gelen Show fonksiyonu arlabilir ya da Control snfndan gelen bool trden Visible propertisi true yaplabilir. using System; using System.Windows.Forms; using System.Drawing;

namespace CSD { class App { public static void Main() { MyForm mf = new MyForm(); mf.Visible = true; Application.Run(); } class MyForm : Form { public MyForm() { //... } //... } } } Bir programda birden fazla anapencere olabilir. Windows un grev ubuu alan programlar deil anapencereleri gstermektedir. Parametresiz Application.Run() fonksiyonundan anapencereleri kapatmakla kamayz. Fakat parametreli Run fonksiyonundan parametre olarak verdiimiz anapencereyi kapatarak kabiliriz. Form nesnesinin yaratlmas tek hamledede yaplabilir. Bu durumda Msin fonksiyonu tek bir satrdan oluur. using System; using System.Windows.Forms; using System.Drawing;

namespace CSD { class App { 13

public static void Main() { MyForm mf1 = new MyForm(); mf1.Visible = true; MyForm mf2 = new MyForm(); mf2.Visible = true; Application.Run(mf2); } class MyForm : Form { public MyForm() { //... } //... } } } Bundan sonraki iskelet program kopyalanacak using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { //... } //... } } }

14

Control Snfnn nemli Property Elemanlar: Control snf tm pencere snflarnn ortak taban snf oldu una gre buradaki elemanlar yalnzca anapencereler iin deil her trl pencereler iin anlamld r. Control snfnn eitli property elemanlar set edildiinde pencere zerinde eitli grsel deiiklikler oluturulabilmektedir. Aslnda biz bir property e deer at yor olsakta arka planda property nin set blm alt rlp karmak API fonksiyonlar yla ilemler yrtlmektedir. Yani ilemler bir property e deer atamak biiminde basitletirilmitir. Visible Property si: Bu property bool trden read/write property dir. Bu property ye true atarsak pencere grnr hale gelir false atarsak grnmez hale gelir. Anapencerenin propertylerini set etme ilemi Main iinde yaplabilecei gibi pencere snfnn balang fonksiyonunda da yap labilir. Balang fonksiyonunda set ilemi iyi bir tekniktir. Text Property si : Bu property string trnden read/write property dir. Bu property pencere yazsn oluturur. Pencere yazs anapencere iin pencere balndaki yazd r. D meler iin d me zerindeki yaz, edit alanlar iin adit alan zerindeki yazy alt rr. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; } //... } } } Color Yaps ve BackColor Property Yap s: BackColor property si Color yaps trndendir. Bu property ye atama yap ldnda pencerenin zemin rengi deiir. Color yap s renk tutmak iin kullanlmaktadr. Rengin 0-255 aras red, green, blue tonel deerleri vard r. 4. bileenine alfa faktr denilmektedir. Alfa faktr transparanlk belirtir. Color yap snn read only RGB ve A propertyleri byte trndendir. A propertyleri rengin ilgili Tonel bileenlerini elde etmek iin kullanlr. Color yapsnn eitli statik propertyleri eitli renkleri Color yaps olarak vermektedir. Byle 100 n zerinde renk vard r. rnein Color.Redkrmz rengi veren Color.Blue mavi rengi veren propertylerdir. Eer programc istedii tonel bileimlerden bir renk elde etmek istiyorsa Color yap snn FromArgb statik fonksiyonlarn kullanmald r. 3 parametreli FromArgb fonksiyonu srasyla Red, Green, Blue deerlerini alr. Fonksiyonun geri dn deeri ilgili tonel deerlere 15

ilikin renktir. Bu fonksiyon Alfa bileenini 255 de tutar. Yani saydamsz bir renk elde edilir. rnein: using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = Color.Aqua; } //... } } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = Color.FromArgb(128, 128, 128);

} //... 16

} } } 4 parametreli FromArgb fonksiyonu Alfa faktrn de almaktadr. this.Text = "rnek Pencere"; this.BackColor = Color.FromArgb(128, 255, 0, 0); Color yapsnn yalnzca default balang fonksiyonu vardr. Pencerenin Konumlandrlmasna ilikin Yaplar ve Property ler: Konumlandrma da anapencereler iin orjin masastnn solt st k esi alt pencerelerde ise st pencerenin alma alannn sol st kesidir. Point yaps System.Drawing isim alan iindedir. Point yapsnn amac bir x ,y noktasn tutmaktadr. Point yap snn 2 parametreli balang fonksiyonu x ve y deerlerini set ederek nesneyi olu turur. Point pt = new Point(100, 200); Point yapsnn X ve Y isimli int trden read/write property elemanlar noktann bileenlerini get ve set etmek iin kullanlmaktadr. rnein:
Point pt; pt.X = 100; pt.Y = 200;

Point yapsnn Point parametreli ve int parametreli offset fonksiyonlar noktay X Y deeri kadar teler. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; Color c = Color.Yellow; Point pt = new Point(100, 200); pt.Offset(1, 1); } //... } } 17

} Point yapsnn dier elemanlar MSDN ktphanesinden izlenmelidir. Control snfnn Point trnden read/write location isimli property eleman pnecereyi konumland rmak iin kullanlmaktad r. rnein: using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.Location = new Point(300, 100); } //... } } } Anapencerelerin konumlandrmada ve boyutland rmada istisnai bir durumu vardr. Form snfnn (Control snfnn deil) StarPosition isimli property eleman Form.StartPosition isimli bir enum trndendir. letim sistemi anapencerenin ilk konumlandrmasn bu property e gre yapmaktad r. Bu enum trnn elemanlar ve anlamlar yledir. CenterSecreen: Bu durumda anapencere programcnn belirttii boyutta ekrann ortasnda konumland rlr. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } 18

class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.Location = new Point(300, 100); this.StartPosition = FormStartPosition.CenterScreen; } //... } } } WindowsDefaultLocation: Burada konumlandrma iletim sisteminin isteine braklr fakat boyutlandrma yap labilir. Bu default durumdur. Manual: Bu durumda konumlandrma ve boyutland rma tamamen programcya braklr. Yani pencereyi location property sine deer atayarak istediimiz yerde grntlemek iin startposition manuele ekilmelidir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.Location = new Point(300, 100); this.StartPosition = FormStartPosition.Manual; } //... } } }

19

Control snfnn Top, Left read/write Right, Bottom read only int trden property elemanlar Yukar, sol, sa ve aa koordinatlara ilikindir. Yani Location propertysini set etmek yerine Left ve Top propertlerini set etmek ayn etkiyi yaratr. public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.Location = new Point(300, 300); this.Left = 0; this.StartPosition = FormStartPosition.Manual; } Control snfnn int trden width ve Height trden property elemanlar genilik ve ykseklik ayarlarn ayarlamaktadr. this.Width = 100; this.Height = 200; Size isimli yap tamemen point yaps gibi iki deer tutmaktadr. Size yapsnn kullanm Point yap snn kullanmna banzemektedir. Bu yap genilik ve ykseklik deerlerini tutmaktadr. Yap nn Width ve Heigth propertlyleri read/Write propertylerdir ve genilik ykseklik deerlerinin set etmekte kullanlr.Set ilemi yapnn balang fonksiyonundan da yaplabilir. rnein: Size s = new Size(100, 200); s.Width = 50; s.Height = 75; Controle snfnn Size isimili property eleman size trndendir buna atanan deer pencereyi boyutlandrr. this.Size= new Size(100, 200) Yani Size property sine deer atamakla width ve Heigth propertylerine deer atamak ayn eydir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.Location = new Point(300, 300); this.Size = new Size(100, 200); 20

this.StartPosition = FormStartPosition.Manual; } //... } } } Baund Rectangle Yaps ve Baund Property Eleman: Rectangel yap s dikdrtgensel bir blgeyi tutmak iin kullanlr. Rectangle yap snn 4 parametreli balang fonksiyonu sol st k e ve genilik, ykseklik biiminde alnan dikdrtgensel blgeyi tutar. public Rectangle(int x , int y, int width, int height) Point ve Size parametreli balang fonksiyonu sol st ke ve genilik ykseklik deerlerinin point ve size yaps biiminde alr. public Rectangle(Point location, Size size) Rectangle rect = new Rectangle(new Point(100, 200), new Size(10, 20)); Rectangle yapsnn Read/Write Location property si sol st k eyi Read/Write Size property si genilik, ykseklik bilgisinin alp set etmekte kullanlr. Rectangle yap snn Read Only Top, Bottom, Left ve Write Property elemanlar dikdrtgenin sol st ve sa alt kegenlerine ilikin koordinatlar verir. X ve Y Property elemanlar yine solt st keye ilikin koordinatlar belirtir. Left ve Top dan farkl olarak bunlar Read/Write property lerdir. Yine Yapnn Width ve Heigth propertyleri vardr. Rectangle yapsnn Contains fonksiyonlar bir noktann ya da Rectangle yapsnn dierinin iinde olup olmad n belirlemektedir. Rectangle yapsnn Offset isimli fonksiyonlar dikdrtgeni delta X, delta Y miktar kadar kayd rr. Yap nn inflate fonksiyonlar dikdrtgensel blgeyi iki taraftan ap bzmek iin kullanlabilir. Rectangle yapsnn Intersect fonksiyonlar iki dikdrtgenin kesiimine ilikin, dikdrtgenin Union fonksiyonun birleimine ilikin fonksiyonudur. Control snfnn Read/Write Bounds isimli property eleman Rectangle yap s trndendir. Bu propertye deer atad mzda pencerenin konumu bu Rectangle da belirtilen deerlere gelir. rnein: using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() 21

{ Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.Bounds = new Rectangle(100, 100, 200, 200); } //... } } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.StartPosition = FormStartPosition.Manual; this.Bounds = new Rectangle(100, 100, 200, 200); } //... } } } ClientRectangle ve ClientSize Property Elemanlar: Control snfnn ClientRectangle Read Only property eleman alma alannn koordinatlarn Rectangle olarak verir. Fakat bu property nin verdii Rectangle yine alma alan orjinlidir. Yani verilen dikdtgenin sol st kesi 0, 0 durumundadr. ClientSize property si Read/Write bir property dir ve Size trndendir. Biz bu property e atama yaparsak pencere bulunduu konumda alma alannn genilii ve ykseklii 22

belirlenen deer dolacak biimde geniletilir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.StartPosition = FormStartPosition.Manual; this.Bounds = new Rectangle(100, 100, 0, 0); this.ClientSize = new Size(100, 100); MessageBox.Show(this.ClientRectangle.ToString()); } //... } } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; 23

this.StartPosition = FormStartPosition.Manual; this.Bounds = new Rectangle(100, 100, 0, 0); this.ClientSize = new Size(100, 100); MessageBox.Show(this.Bounds.ToString()); } //... } } } Name Property si: Control snfnn Name property si string trndendir ve read/write property dir. Name property si alma srasnda ktphane tarafndan kullanlmamaktad r. Programc buraya bir deer atayp sonra onu alabilir. Visual Studio IDE si forma yerletirdii her kontrole bir isim verir ve bu ismi Name property sine atar. this.Name = "Test"; Mesaj Diyalog Penceresinin kartlmas ve MessageBox Snf: Mesaj diyalog penceresi kartmak iin MessageBox snfnn statik Show fonksiyonlar kullanlr. En genel bir Show fonksiyonu aadaki 4 parametreli fonksiyondur. Aslnda bir parametreli, 2 parametreli ve 3 parametreli show fonksiyonlar bu 4 parameteli fonksiyonu default deerlerle armaktad r. rnein programc pratiklik iin 1 parametreli Show fonksiyonunu kullanabilir. Bu durumda 4 parametreli fonksiyonun dier parametreleri belirlenmemi gibi etki sz konusudur. 4 parametreli show fonksiyonu yledir. public static DialogResult Show( string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon ) Fonkjsiyonun 1. parametresi message penceresi iinde grntlenecek yazyu belirtir. 2. Parametre pencere balk yazsnda grntlenecek yazy belirtir. 3. parametre MessageBoxButton isminde bir enum trndendir. Mesaj penceresi ile yalnzca baz tu takmlar grntlenebilir. Tu takmlar unlardr. Ok, OkCancel, AbortRetryIgnore, YesNoCancel, YesNo, RetryCancel... Fonkjsiyonun son parametresi MessageBoxIcon isimli bir enum trndendir. Bu parametre diyalog penceresinden icon resmini belirtmektedir. Fonksiyonun geri dn deeri diyalog result trndendir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() 24

{ Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.StartPosition = FormStartPosition.Manual; this.Bounds = new Rectangle(100, 100, 0, 0); this.ClientSize = new Size(100, 100); MessageBox.Show("this is a test", "Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); } //... } } } Geri dn deeri hangi tula ktmz belirtir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "rnek Pencere"; this.BackColor = System.Drawing.Color.Red; this.StartPosition = FormStartPosition.Manual; this.Bounds = new Rectangle(100, 100, 0, 0); this.ClientSize = new Size(100, 100); DialogResult result = MessageBox.Show("this is a test", "Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if (result == DialogResult.OK) MessageBox.Show("Ok"); 25

else if (result == DialogResult.Cancel) MessageBox.Show("Cancel"); } //... } } } Alt Pencerelerin Yaratlmas: Anmsanaca gibi child windows st pencerenin alma alan d na kamayan pencerelerdir.Alt pencereler iin orjin noktas onun st penceresinin alma alannn sol st kesidir. Windows da d me gibi edit alanlar gibi, listeleme kutular gibi pek ok alt pencere zaten oluturulmu biimdedir. Programc bu hazr alt pencereleri programnda kullanabilir. Fakat programc do rudan kontrol snfn kullanarak ya da geniletilebilir olmas iin kontrol snfndan snf treterek kendi alt pencerelerini oluturabilir. Alt pencere yaratmak iin kontrol snf trnden ya da kontrol snfndan tretilmi bir snf trnden bir nesne new operatryle olu turmak yeterlidir. Her pencerenin bir alt pencere listesi vardr. Bu alt pencere listesi kontrol snfnn Controls isimli property elemanyla temsil edilmektedir. Controls property eleman Ilist arayayzn destekleyen bir snf trndendir. public Control.ControlCollection Controls{get;} Grld gibi ControlCollection snf Control snfnn iinde bildirilmi bir snftr. Fakat bizim iin nemli olan Controls property sinin Liste tarz bir Collection snf trnden olduudur. Alt pencerelere temsil edilen referanslarn st pencereyi temsil edne snfn veri eleman olarak bulundurulmas nesne ynelimli programlama teknii bakm ndan anlamld r. O halde rnein bir anapencereye u admlardan geilerek bir alt pencere yerletirilebilir. 1. Altpencere snf trnden (yani kontrol ya da kontrolden tretilmi bir snf trnden) bir snf referans st pencereyi temsil eden pencere snfnn private veri eleman olarak bildirilir. 2. Alt pencere nesnesi st pencereyi temsil eden snfn balang fonksiyonunda yaratlr. 3. Altpencere referans st pencerenin control isimli collection elemanna eklenir. En basit bir alt pencere kontrol snf kullanlarak yaratlabilir. Bir alt pencere yaratld nda zemin rengi st pencerenin zemin rengi ile ayn olur. Eer biz pencerenin snr izgilerini izmezsek yaratlm alt pencereyi fark edemeyiz. Ayrca alt pencereleri visible duruma getirmeye gerek yoktur. Alt pencereler otomatik olarak zaten visible durumdadr. Bu durumda rnein kontrol snf kullanlarak bir alt pencere yle oluturulabilir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); 26

} class MyForm : Form { private Control m_child; public MyForm() { this.Text = "Test Child"; m_child = new Control(); m_child.BackColor = Color.Red; m_child.Bounds = new Rectangle(100, 100, 100, 100); this.Controls.Add(m_child); //... } //... } } } Control snfn dorudan kullanmak yerine control snfndan bir snf treterek kullanmak daha iyi bir tekniktir. Anahtar Notlar: Alt pencereler iletim sistemi dzeyinde aslnda alt pnecere nesnesi new ile yaratlrken deil st pencerenin alt pencere listesine eklewnirken yaratlmaktadr. Alt pencereyi st pencerenin pencere listesine eklemenin dier bir yolu control snfnn parents property sini kullanmaktr. Bu property aadaki gibi bildirilmitir. public Control Parent{get; set;} Yanialt pencereyi st pencerenin pencere listesine eklemek yerine alt pencerenin parents propertysinne st pencereyi atamak ayn anlamdadr. m_child = new MyControl(); ile m_child.Parent = this; ayn anlamdadr. Muhtemelen Parent propertysinin set blm yle yazlmt r. public Control Parent { set { value.Controls.Add(this); } } Controls Collection elemannn ilikin olduu Collection snfnn AddRange isimli bir fonksiyonu da vardr. AddRange fonksiyonu oparametre olarak Controls snf trnden bir dizi alr ve dizinin tm elemanlarn pencerenin altpencere listesine ekler. Bu durumda tek hamlede biz birden fazla alt pencereyi st pencereye ekleyebiliriz. rnein:

27

m_c1 = new MyControl(); m_c2 = new MyControl(); m_c3 = new MyControl(); this.Controls.AddRange(new Control [ ] {m_c1, m_c2, m_c3}); Bir alt pencere nesnesi yaratldnda pencerenin Location ve Size property leri 0 durumundadr. phesiz byle bir pencere ekranda grlemez. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { private MyControl m_c1, m_c2, m_c3; public MyForm() { this.Text = "Test Child";

m_c1 = new MyControl(); m_c1.Bounds = new Rectangle(0, 0, 100, 100); m_c2 = new MyControl(); m_c2.Bounds = new Rectangle(150, 0, 100, 100); m_c3 = new MyControl(); m_c3.Bounds = new Rectangle(300, 0, 100, 100); this.Controls.AddRange(new Control [] {m_c1, m_c2, m_c3}); //... } //... } class MyControl : Control {

public MyControl() { this.BackColor = Color.Red; } 28

} } } Pencere Mesajlarnn lenmesi: Anmsanaca gibi iletim sistemi st ya da alt pencere zerinde bir ilem gerekletiinde gerekleen ileme ilikin bir mesaj pencerenin yaratld thread in mesaj kuyru una eklemektedir. Mesaj kuyruundan mesaj alp ileyen fonksiyon Application.Run fonksiyonlard r. Bir mesaj karsnda programcnn belirledii bir kod u alt rmas gerekir. Bu ilem biraz karmak bir srele gereklemektedir. .net ortam yaratlan her pencerenin pencere ister alt ister ana pencere olsun control referansn kendi iinde bir collection da saklar. rnein bir anapencere te alt pencere sz konusu olsun. Bu pencerelerinin hepsi dolayl olarak control snfndan tretilmitir. w1 w2 w3 w4

Burada .net ortam bu drt pencerenin control referansnda collection iinde tutuyor durumdadr. Windows un kuyrua brakt her mesajn en azndan ortak baz bileenleri vardr. rnein windows her mesaj iin o mesaj hangi pencereye ilikin olduunu belirten bir handle deeri ierir. Ayn zamanda her mesajn bir numaras vard r. Mesajn numaras mesajn hangi olaydan dolay kuyrua brakldn belirtmektedir. Ayrca her mesaj ilave baz parametrik bilgilere sahiptir. Application.Run fonksiyonlar kuyruktan mesaj alr. Mesajn handle deerinden haraketle Collection iinde arama yaparak mesajn ilikin olduu pencerenin control referansn elde eder. Application.Run fonksiyonlar mesajn ilikin olduu control referansn bulduktan sonra mesaj numarasn inceler. Her mesaj iin control snfnn bir tane OnXXX isimli protected bir sanal fonksiyonu vard r. te Run fonksiyonlar mesajn numarasna bakarak ilgili control referansn kullanp sanal OnXXX fonksiyonlarn armaktadr. Yukardaki aklamalara gre programc bir olay gerekletiinde kendi kodunun almasn yle salayabilir. 1. Programcnn ilgili mesaj olay iin arlacak OnXXX fonksiyonunu bilmesi gerekir. 2. Programc belirledii OnXXX fonksiyonunu kendi snfnda Override eder. Bylece Application.Run fonksiyonlar bu sanal OnXXX fonksiyonunu ard nda programcnn fonksiyonu arlm olur. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } 29

class MyForm : Form { private MyControl m_c1, m_c2, m_c3; public MyForm() { this.Text = "Test Child";

m_c1 = new MyControl(); m_c1.Bounds = new Rectangle(0, 0, 100, 100); m_c2 = new MyControl(); m_c2.Bounds = new Rectangle(150, 0, 100, 100); m_c3 = new MyControl(); m_c3.Bounds = new Rectangle(300, 0, 100, 100); this.Controls.AddRange(new Control [] {m_c1, m_c2, m_c3}); //... } //... protected override void OnClick(EventArgs e) { MessageBox.Show("test"); } } class MyControl : Control {

public MyControl() { this.BackColor = Color.Red; } } } } Mesaj Parametre Snflar: Anmsanaca gibi windows her mesaj iin Handle deeri ve mesaj numarasnn yansra o mesaja zg ek birtakm bilgiler de yerletirebiliyordu. te Application.Run fonksiyonlar kuyruktan mesaj aldnda mesajn parametrik bilgilerini elde edip bu parametrik bilgileri YYYEventArgs isimli bir snf nesnesi biimine dntrp OnXXX fonksiyonuna parametre olarak geirmektedir. Yani programc hangi mesaj iliyorsa o mesajn parametrik bilgilerini OnXXX fonksiyonunun parametresinden elde edebilir. Tm YYYEventArgs isimli snflar EventArgs isimli bir taban snftan tretilmitir. EventArgs isimli snf parametresiz snf bir snf temsil etmektedir. Yani EventArgs parametre snf bir mesaj parametresine sahip olmayan bir snftr. Event Yoluyla Mesaj lenmesi: Mesaj ilemenin dier bir yolu control snfnn Event elemanlarn kullanmaktr. Mesajlarn bu biimde ilenmesi daha pratik olduu iin tercih 30

edilmektedir. Kontrol snfnn her mesaj iin bir OnXXX sanal fonksiyonunun yansra buna kar gelen bir XXX Event eleman vardr. rnein OnClick fonksiyonuna karlk gelene Event elemannn ismi Click OnKeyDown fonksiyonuna karlk gelen Event elemannn ismi KeyDown dur. te control snfnn OnXXX fonksiyonlar XXX isimli event elemannn fonksiyonlarn armaktad r. Bylece programc bir mesaj iin OnXXX isimili sanal fonksiyonunu Override etmek yerine XXX elemanna fonksiyonda girebilir. Sk yap lan bir hata bir mesajn her iki yntemle birden ilenmesi srasnda olumaktadr. Programcnn hem OnXXX isimli sanal fonksiyonunu Override ettiini hemde XXX Event elemanna += operatr ile fonksiyon girdiini dnelim. Bu durumda ilgili mesaj olu tuunda OnXXX fonksiyonu arlacak fakat XXX Event fonksiyonu arlmayacaktr. nk XXX Event fonksiyonlarn aran Control snfnn OnXXX fonksiyonudur. Halbuki artk Override edilmi fonksiyon arlmaktadr. Eer programc Control snfnn OnXXX nin fonksiyonunu da armak istiyorsa bunu aadaki gibi base.OnXXX yaparak salamaldr. Kontrol snfnn OnXXX sanal fonksiyonuna karlk bir XXX event elaman vard r. Bu Event eleleman YYY isimli bir delege trndendir. Programcnn bu event elemana fonksiyon ekleyebilmesi iin ilgili delege trnden nesne yaratmas gerekir. Ve arlacak event fonksiyonu o delegenin parametrik yapsna uygun olmak zorundad r. rnein MouseDown isimli Event elemannn ilikin olduu delege snf MouseEvent Handler isimli snftr. Bu delege snf geri dn deeri void olan 1. parametresi object 2. parametresi MouseEventArgs trnden olan fonksiyonlar tutabilir. Dolays yla programcnn bu Event elemana fonksiyon girerken MouseEventHandler trnden bir nesne yaratmas ve girecei fonksiyonu burada belirtmesi gerekir. rnein: (krmz blm) using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.MouseDown += new MouseEventHandler(MouseDownHandler); } public void MouseDownHandler(object sender, MouseEventArgs mea) { MessageBox.Show("Test"); } //... } } } 31

arlacak fonksiyon sar ile iaretlenmitir. YYYEventHandler isimli delegenin ikinci parametresi oluan mesaja ilikin mesaj parametre snf trndendir. Bu tr OnXXX sanal fonksiyonuna geirilen parametre snf tryle aynd r. Mesaj ileme konusunun anahtar noktalar yledir. Mesajlar her zaman Control snfnn OnXXX sanal fonksiyonunun Override edilmesiyle ilenebilir. OnXXX sanal fonksiyonu Override etmek yerine Control snfnn XXX isimli YYYEventHandler isimli delege trnden Event elemanna bir delege nesnesi eklenebilir. XXX Event elemannn ilikin olduu YYYEventHandler isimli delege snfnn geri dn deeri void, 1. parametresi object ve 2. parametresi mesaj parametre snf trndendir. Bu ikinci parametrenin tr OnXXX fonksiyonunun tryle aynd r. Mesaj olutu unda arlacak mesaj fonksiyonunun birinci object parametresi ne anlama gelmektedir? Bu parametre mesaj hangi nesne zerinde olumusa o nesnenin referansn belirtmektedir. rnein Forum a ilikin bir mesaj olu mu sa object parametresi yaratlm form snfnn referansn bir d me iinde olay gereklemise object parametresi bu dme nesnesinin referansn belirtmektedir. Olaylar daha iyi anlamak iin kontrol snfnn OnMouseDown sanal fonksiyonunun nasl yazld n gsterelim: class Control { //... public event MouseEventHandler MouseDown; protected virtual void OnMouseDown(MouseEventArgs e); { //... MouseDown(this, e); //... } Bir mesajn ilenmesi iin nelerin bilinmesi gerekir? 1. Programcnn hangi olay gerekletiinde ilgili mesajn kuyrua b rakldn bilmesi gerekir. 2. Programc mesaj parametre snfn incelemeli bylece ilgili mesaj olutu unda hangi ek bilgilerinde verildiini belirleyebilmelidir. 3. Programc bu mesaj karsnda arlacak kontrol snfnn OnXXX fonksiyonunun hangisi olduunu bilmelidir. 4. Programcnn ilgili mesaja ilikin event elemannn ne olduunu ve bunun hangi delege snfndan olduunu bilmesi gerekir. Temel Pencere Mesajlar Click Mesaj: Click mesaj fareyle pencerenin alma alan zerine tklanp el ekildiinde gnderilir. Bu mesaj karsnda Control snfnn arlan sanal fonksiyonu OnClick isimli fonksiyondur. Mesajn mesaj parametres snf EventArgs snfd r. Yanibu mesaj bize ekstra bir bilgi vermektedir. Tetiklenen Event eleman Click ismindedir. Bu event eleman EventHandler isimli delege trndendir. EventHandler delegesinin geri dn deeri void, 1. parametresi object, 2. parametresi EventArgs trndendir. using System; using System.Windows.Forms; using System.Drawing;

32

namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "Sample Event"; this.Click += new EventHandler(clickEventHandler); } private void clickEventHandler(object sender, EventArgs e) { MessageBox.Show("Click"); } } } } MouseDown ve MouseUp Mesajlar: Fareyle tua basld nda MouseDown mesaj el tutan ekildiinde MouseUp mesaj olu ur. arlan sanal fonksiyonlar Control snfnn OnMouseDown ve OnMouseUp fonksiyonlardr. lgili Event eleman MouseDown ve MouseUp isimli elemanlardr. Bu mesajlar da alma alan mesajlard r. Nu mesajlar olutu unda hangi tua baslm ya da ekilmi olduu ve hangi koordinatta bu iin gerekletii bilgileri de verilmektedir. Bu mesajlarn mesaj parametre snf MouseEventArgs isimli snftr. Bu snfn X ve Y isimli int trden Read Only property elemanlar basm ve ekim koordinatlarn vermektedir. Snfn Location isimli property eleman ise ayn koordinat point olarak verir. Hangi tua basld Button property(public MouseButtons Button { get; }) si ile elde edilebilir. Bu property MouseButtom isimli bir enum trndendir. Snfn dier elemanlar MSDN dkumanlar ndan izlenmelidir. MouseDown ve MouseUp event elemanlar MouseDownHandler delege trndendir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } 33

class MyForm : Form { public MyForm() { this.Text = "Sample Event"; this.MouseDown += new MouseEventHandler(mouseDownHandler); } private void mouseDownHandler(object sender, MouseEventArgs mea) { MessageBox.Show(mea.Location.ToString()); } } } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "Sample Event"; this.MouseDown += new MouseEventHandler(mouseDownHandler); } private void mouseDownHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { MessageBox.Show(mea.Location.ToString()); } } } } } Resize Mesaj: Bir ana pencerenin boyutlarnn deitirilebilmesi iin Form snfnn 34

FormBorderStyle elemann Sizable olmas gereekir. Zaten Form snf iin bu property default olarak bu deerdedir. Eer programc anapencerenin boyutlandrlabilir olmasn istemiyorsa FormBorderStyle property sine Sizable yerine Fixed ieren baka bir deer atamaldr. rnein: using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "Sample Event"; this.FormBorderStyle = FormBorderStyle.Fixed3D;//boyutlandrlamaz. this.MouseDown += new MouseEventHandler(mouseDownHandler); } private void mouseDownHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { MessageBox.Show(mea.Location.ToString()); } } } } } Grld gibi FormBorderStyle propertysi hem anapencerenin kenar izgilerini belirlemekte hem de anapencerenin boyutlandrlabilir olup olmad n belirlemektedir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); 35

} class MyForm : Form { public MyForm() { this.Text = "Sample Event"; this.FormBorderStyle = FormBorderStyle.Sizable;//kenardan ekerek boyutlandrlabilir form this.MouseDown += new MouseEventHandler(mouseDownHandler); } private void mouseDownHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { MessageBox.Show(mea.Location.ToString()); } } } } } Pencerenin boyutu fareyle ya da programlama yoluyla deitirildiinde windows Resize mesajn kuyrua brakmaktadr. Bu mesaj olu tuunda arlan sanal fonksiyon OnRize isimli fonksiyondur. Mesajn parametre snf EventArgs snfdr. Yani bu mesaj bize ek bir bilgi vermemektedir. Mesajn ilikin olduu Event eleman Resize isimli elemandr. Resize event eleman EventHandler isimli delege trndendir. Anahtar Notlar: Windows 95, 98 ME sistemlerinde pencereyi geniletirken ya da srklerken default olarak pencere ierii tazelenmemektedir. Halbuki Windows XP ve Vista da default durum pencere ieriinin de tazelenmesidir. te Windows XP ve Vista daki bu default surumda Resize mesaj geniletme ya da daraltma srasnda srekli gnderilmektedir. Halbuki dier modda geniletme ya da daraltma ileminden sonra elimizi fareden ektiimizde bu mesaj bir kez gnderilir. Programc Risize mesaj olutu unda artk Control snfnn Size, Width, Heigth gibi propery elemanlarna bakarak boyutland rma sonucundaki yeni pencere genilik ve yksekliini elde edebilir. Programc ClientSize ve ClientRectangle propertyleri ile alma alannn yeni boyutlarn elde edebilir. Baz uygulamalarda programc pencerenin belirli bir boyuttan daha fazla kltlmesini ya da bytlmesini istemeyebilir. Bunu salamak iin Form snfnn Size trnden MaximumSize ve MinumumSize propertylerini kullanmaktadr. rne in: this.MinimumSize = new Size(200, 200); using System; using System.Windows.Forms; using System.Drawing; 36

namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "Sample Event"; this.FormBorderStyle = FormBorderStyle.Sizable; this.MouseDown += new MouseEventHandler(mouseDownHandler); this.Resize += new EventHandler(resizeEventHandler); this.MinimumSize = new Size(200, 200); } private void resizeEventHandler(object sender, EventArgs mea) { MessageBox.Show(this.Size.ToString()); } private void mouseDownHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { MessageBox.Show(mea.Location.ToString()); } } } } } Resize mesaj maximize ve minimize ilemleri srasnda da olu turulur. Fakat .net te (API de byle deil) pencere ilk kez ald nda Resize mesaj oluturulmamaktadr. Programc bazen pencerenin maximize ve minimize gibi zel durumlarda olup olmadn anlamak isteyebilir. Ya da pencereyi programlama yoluyla maximize ve minimize yapmak isteyebilir. Di er Fare Mesajlar: Fare mesajlarnn hepsinin mesaj parametre snf MouseEventArgs snfd r. Bu snf MouseDown mesajnda ele alnm tr. Yine mesaj olutu unda tetiklenecek event elemanlar MouseEventHandler delege trndendir. MouseUp mesaj el fareden ekildiinde oluur. MouseUp mesaj iin arlacak sanal fonksiyon OnMouseUp fonksiyonudur. Bu fonksiyonda MouseUp event elemannn fonksiyonlarn arr. 37

Farenin tuuna basl olsun ya da olmasn fare alma alan zerinde hareket ettrildiinde windows kuyrua MouseMove mesajlar b rakr. Bu mesajlar fare hareket ettririlirken her pixel iin oluturulmak zorunda deildir. Hangi yo unlukta oluturulaca sistemin iinde bulunduu duruma bald r. Bu mesaj iin arlacak sanal fonksiyon OnMouseMove fonksiyonudur. Bu fonksiyonda MouseMove event elemann tetikler. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { private Point m_prevPoint; private Pen m_redPen;

public MyForm() { this.Text = "ScratchPad Appilication"; this.BackColor = Color.White; this.Size = new Size(800, 400); this.MouseDown += new MouseEventHandler(mouseDownHandler); this.MouseMove += new MouseEventHandler(mouseMoveHandler); } //... private void mouseDownHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) m_prevPoint = mea.Location; } private void mouseMoveHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { Graphics g = this.CreateGraphics(); g.DrawLine(Pens.Red, m_prevPoint, mea.Location); m_prevPoint = mea.Location; } } 38

} } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { private Point m_prevPoint; private Pen m_redPen;

public MyForm() { this.Text = "ScratchPad Appilication"; this.BackColor = Color.White; this.Size = new Size(800, 400); m_redPen = new Pen(Brushes.Red, 5); this.MouseDown += new MouseEventHandler(mouseDownHandler); this.MouseMove += new MouseEventHandler(mouseMoveHandler); } //... private void mouseDownHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) m_prevPoint = mea.Location; } private void mouseMoveHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { Graphics g = this.CreateGraphics(); g.DrawLine(m_redPen, m_prevPoint, mea.Location); m_prevPoint = mea.Location; 39

} } } } } System Renkleri: Anmsanaca gibi denetim masasnda eitli pencere desenleri global dzeyde ayarlanabilmektedir. rnein biz denetim masasnda pencere zemin rengini deitirirsek pek ok programn pencerelerinin zemin rengi deiecektir. Denetim masasndan eitli gelerin renkleri deitirildiinde windows arka planda tm pencerelere rengin deitiini belirten mesajlar gndermektedir. Fakat .net te programn denetim masasndaki deiikliklere duyarl hale getirilmesi olduka kolaylatrlmt r. SystemColors isimli snfn Color trnden pek ok static property si vardr. Bu snfn denetim masasndaki eitli geleri temsil eden elemanlar vardr. rnein SystemColor.Window denetim masasndaki pencere zemin rengini temsil eder. Yani biz bizden bir renk istendii zaman o rengi SystemColors.Window biiminde verirsek denetim masasnda pencerenin zemin rengi deitirildiinde bu renk artk deimi rengi temsil eder. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { private Point m_prevPoint; private Pen m_redPen;

public MyForm() { this.Text = "ScratchPad Appilication"; this.BackColor = SystemColors.Window; this.Size = new Size(800, 400); m_redPen = new Pen(Brushes.Red, 5); this.MouseDown += new MouseEventHandler(mouseDownHandler); this.MouseMove += new MouseEventHandler(mouseMoveHandler); } //... private void mouseDownHandler(object sender, MouseEventArgs mea) 40

{ if (mea.Button == MouseButtons.Left) m_prevPoint = mea.Location; } private void mouseMoveHandler(object sender, MouseEventArgs mea) { if (mea.Button == MouseButtons.Left) { Graphics g = this.CreateGraphics(); g.DrawLine(m_redPen, m_prevPoint, mea.Location); m_prevPoint = mea.Location; } } } } } Pencerelerin Yok Edilmesi: Bir pencerenin nesne olarak yaratlmasyla iletim sistemi genelinde yaratlmas farkl zamanlarda gerekletirilmektedir. Control snf ya da o snftan tretilmi bir snf trnden nesneyi new operatr ile yarattmzda henz windows dzeyinde alt pencere yaratlmam durumdad r. Alt pencerenin windows dzeyinde yaratlmas st pencerenin pencere listesine eklenmesi srasnda yaplmaktad r. Fakat ana pencereler iin durum byle deildir. Ana pencereler gerekten de nesne new operatryle yaratld nda yarat lmaktadr. Peki bir pencere nasl yok edilir. Alt pencerelerin fiziksel olarak yok edilmesi tamamen ters bir ilem olarak alt pencerenin st pencerenin pencere listesinden silinmesiyle gerekletirilebilir. Fakat ana pencerenin yok edilmesi form snfnn Close fonksiyonuyla yaplmaktad r. phesiz st pencere yok edildiinde onun tm alt pencereleri de yok edilmektedir. Grld gibi programlama yoluyla ana pencereyi kapatp mesaj dngsnden kmak istiyorsak tek yap lacak ey Form snfnn Close fonksiyonun armaktr. Ana pencereyi kapatmann bir yolu da pencerenin sa st k esindeki X simgesine tklamaktr. phesiz kullanc X simgesine tklad nda bu ilemin iptal edilebilmesine olanak verilmelidir. te . net te X tuuna tkland nda Form snfnn baz event elemanlar tetiklenmektedir. Form snfnn FormClosing isimli event eleman FormClosingEventHandler isimli delege trndendir. Windows tarafndan oluturulan bu mesajn mesaj parametre snf FormClosingEventArgs isimli snftr. FormClosingEventArgs snfnn bool trden Cancel isimli property elemanna event fonksiyonu arldktan sonra .net tarafndan baklmaktadr. Eer bu elemanda true varsa pencerenin kapatlmas iptal edilir. Bu event arldnda bu eleman iinde default olarak false vardr. Form snfnn Close fonksiyonu yine FormClosing mesajn oluturmaktadr. O halde k kontrol (rnein save edilmesine ynelik) FormClosing mesanda gerekletirilebilir. FormClosing event eleman anapencere henz yok edilmeden nce tetiklenmektedir. Fakat bazen ana pnecere yok edildikten sonra da bir takm ilemlerin yap lmas gerekebilir. Bunun iin FormClosed event eleman kullanlr. phesiz artk bu event olutu unda pencerenin kapatlmasnn iptal edilmesi sz konusu deildir. O halde FormClosing mesaj ilemin iptal 41

edilmesi iin FormClosed mesaj kaynaklarn boaltlmas iin kullanlmald r. Bir uygulamay sonland rmann dier bir yolu da Appilicationsnfnn exit static fonksiyonunun arlmasdr. Bu fonksiyon dorudan mesaj dngsnden kmaya yarar. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { public MyForm() { this.Text = "Form Closing Example"; this.MouseDown +=new MouseEventHandler(MyForm_MouseDown); this.FormClosing += new FormClosingEventHandler(closingEventHandler); } //... void MyForm_MouseDown(object sender, MouseEventArgs e) { this.Close(); } private void closingEventHandler(object sender, FormClosingEventArgs fcea) { DialogResult dr; dr = MessageBox.Show("Save Changes?", "Message", MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) fcea.Cancel = true; } } } } Dme Kontrol: Dme kontolleri genellikle bir olay balatmak iin kullanlr. Dmeler(push buttons) seenek kutular(check boxes) ve radyo dmeleri(radio buttons) ile benzerlikler gstermektedir. Bu nedenle bu snfn ortak elemanlar buttonbase isimli bir taban snfta toplanmtr ve bu kontrol temsil eden snflar ButtonBase isimli snftan tretilmilerdir.

42

Control

ButtonBase

Button

CheckBox

RadioButton

Grld gibi dmeler Button snfndan elde edilmektedir. Bir d me yle kullanlr. 1. Button snf trnden bir nesne yaratlr. Nesne st pencerenin pencere listesine eklenir. 2. Nesnenin Text property si d menin zerinde kacak yazy belirtir. Programc isterse dier property lerle grnty ayarlayabilir. 3. Button snfnn Control snfndan gelen Click Event eleman dmeye tklandnda ilemin balatlmas iin kullanlabilir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } class MyForm : Form { private Button m_buttonOk; private Button m_buttonCancel; public MyForm() { m_buttonOk = new Button(); m_buttonOk.Text = "Ok"; m_buttonOk.Location = new Point(30, 100); m_buttonOk.Click += new EventHandler(ClickOkEventHandler); m_buttonOk.ForeColor = Color.Red; m_buttonCancel = new Button(); m_buttonCancel.Text = "Cancel"; m_buttonCancel.Location = new Point(120, 100); 43

m_buttonCancel.Click += new EventHandler(ClickCancelEventHandler); m_buttonCancel.ForeColor = Color.Red; this.Controls.AddRange(new Control[] { m_buttonOk, m_buttonCancel }); } private void ClickOkEventHandler(object sender, EventArgs ea) { MessageBox.Show("Ok"); } private void ClickCancelEventHandler(object sender, EventArgs ea) { MessageBox.Show("Cancel"); } //... } } } Control snfnn bool trden read/write Enabled isimli property eleman pencereyi kontrol klavye ve fare mesajlarna kapatmaktadr. phesiz kontrol nesnesi yaratld nda bu property default true durumdadr. Pasif duruma getirilen pek ok standart kontrol solgun renkle gsterilmektedir. Aslnda bu solgun grntleme ilemi windows tarafndan otomatik yaplmamaktad r. Windows pencere pasif duruma geerken kontrole EnabledChanged mesaj gnderir. Kontrol yazan kii de bu mesaj ileyerek solgun renkli izimi yapmaktadr. Kontrollerin Fareyle Srklenmesi: ekil srkleme ve kontrol srkleme gibi ilemlerin mant aynd r. ki mouseMove mesaj arasnda farenin nceki ve sonraki konumlar dikkate alnarak x ve y yer deitirmeleri hesaplanr. phesiz programc ilgili kontroln MouseDown ve MouseMove mesajlarn ilemelidir. Programc konrol Location property sini kullanarak x - y miktar kadar telemelidir. Bu telemeyi yaptktan sonra farenin hareket ettirildii nokta ilk nokta haline gelir. Yani farenin ilk tkland nokta konrol telendiinde yine ayn nokta olarak kalmaktadr. Baka bir deyile tklanan nokta kontroln sol st kesi orjinli noktas elde edilir. Anahtar Notlar: Bir propert eleman tamamen bir fonksiyon gibi davranmaktadr. rnein: m_buttonOk.Location ileminde Location property sinin get blm altrlacaktr. Bu propert muhtemelen aadaki gibi yazlmtr. class Control { private Point m_Location; //... public Point Location { get { return m_Location; } set { 44

m_Location = value; //... } } //... } Property bize bir yap veriyorsa biz o yap nn bir elemanna eritiimizde snf ierisindeki yapnn elemanna erimi olmayz. Property nin verdii return ifadesiyle yaratlan geici yap deikeninin elemanna erimi oluruz. Yani valx ve valy deerlerini biz rnein dmenin location property isinin x ve y ksmlarna ylr yerletiremeyiz. m_buttonOK.Location x = valx; m_buttonOK.Location y = valy; bu ilemi aadaki gibi yapmalyz. m_button.Location = new Point(valx, valy); Kontrol n srklenmesi iin kontrol n (rneimizde biz dme diyoruz)mouseDown, mouseUp ve mouseMove event fonksiyonlar yle yazlabilir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private Button m_buttonOK; private Point m_clickPoint; private bool m_flag; public MyForm() { this.Text = "Dragging Example"; m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.MouseDown += new MouseEventHandler(m_buttonOK_MouseDown); m_buttonOK.MouseUp += new MouseEventHandler(m_buttonOK_MouseUp); m_buttonOK.MouseMove += new MouseEventHandler(m_buttonOK_MouseMove); m_buttonOK.Parent = this; } void m_buttonOK_MouseDown(object sender, MouseEventArgs e) 45

{ if (e.Button == MouseButtons.Left) { m_clickPoint = e.Location; m_flag = true; } } void m_buttonOK_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) m_flag = false; } void m_buttonOK_MouseMove(object sender, MouseEventArgs e) { if (m_flag) { int deltaX = e.X - m_clickPoint.X; int deltaY = e.Y - m_clickPoint.Y; m_buttonOK.Left += deltaX; m_buttonOK.Top += deltaY; } } } } Mevcut Bir Control n Treterek Geniletilmesi: Elimizde bakalar tarafndan yazlm olan bir kontrol snf bulunuyor olsun. (rnein button snf bakalar tarafnda yazlm bir control snfd r) Biz bu mevcut kontrol geniletmek istersek bu control snfndan tretme yapabiliriz. Ve artk pencereri bu tretilmi snf kullanarak oluturabiliriz. rnein button snfn geniletmek istersek Button snfndan MyButton isimli bir snf tretebiliriz. Ve button nesneleri yerine MyButton nesneleri yaratabiliriz. rnein biz fareyle srklenebilen bir Button snf yazabiliriz. Bunun iin Button snfndan DargButton gibi bir snf tretiriz. Button snfnn MouseDown, MouseUp, MouseMove event elemanlarn bu DragButton snfnda ileyebiliriz. Bylece Button yerine DragButton snfn kullanarak srklenebilen dmeler oluturabiliriz. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } } 46

class MyForm : Form { private DragButton m_buttonOK; private DragButton m_buttonCancel; public MyForm() { this.Text = "Dragging Example"; m_buttonOK = new DragButton(); m_buttonOK.Text = "&Ok"; m_buttonCancel = new DragButton(); m_buttonCancel.Text = "&Cancel"; m_buttonCancel.Location = new Point(100, 100); this.Controls.Add(m_buttonOK); this.Controls.Add(m_buttonCancel); } }

class DragButton : Button { private Point m_clickPoint; private bool m_flag; public DragButton() : base() { this.MouseDown += new MouseEventHandler(mouseDownHandler); this.MouseUp += new MouseEventHandler(mouseUpHandler); this.MouseMove += new MouseEventHandler(mouseMoveHandler); } void mouseDownHandler(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { m_clickPoint = e.Location; m_flag = true; } } void mouseUpHandler(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) m_flag = false; }

47

void mouseMoveHandler(object sender, MouseEventArgs e) { if (m_flag) { int deltaX = e.X - m_clickPoint.X; int deltaY = e.Y - m_clickPoint.Y; this.Left += deltaX; this.Top += deltaY; } } } } TextBox Control : Bu control (API programlama da EditBox olarak bilinir) kullancdan bir edit alan iinden bilgi almak iin kullanlr. Bu control kendi iinde undo gibi karmak mekanizmalar iermektedir. Adeta bir editrn zelliklerine sahiptir. Control n en yaln kullanm kullancn girdii yaznn alnmazas biimidir. Programc control textbox n default balang fonksiyonu ile yaratr textbox kontrol kontrol snfndan gelen text property si iindeki yazy temsil eder. Yani biz bu property ye yaz girersek yaz textbox iinde grntlenir. Bu property den yaz alrsak control n iine girmi yazy alm oluruz.Tpk Button snfnda oldu u gibi TextBox snf yla benzerlik gsteren RichTextBox ve MaskedTextBox gibi snflar da vardr. Bu snflarn ortak zellikleri TextBoxBase iinde toplanmtr. TextBox snfda TextBoxBase snfndan tretilmitir. Control

TextBoxBase

TextBox using System; using System.Windows.Forms; using System.Drawing;

RichTextBox

MaskedTextBox

namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

48

class MyForm : Form { private TextBox m_textBoxName; private Button m_buttonOK; public MyForm() { m_textBoxName = new TextBox(); m_textBoxName.Location = new Point(100, 100); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 140); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); this.Controls.AddRange(new Control[] { m_buttonOK, m_textBoxName });

} private void buttonOKClickHandler(object sender, EventArgs ea) { MessageBox.Show(m_textBoxName.Text); } } } TextBox Control nn bool trden multiLine property eleman control ok satrl mod a geirmek iin kullanlabilir. Bu property nin default durumu false dur. Yani control tek satrldr. Control n int trden maxLength property si TextBoxBase snfndan gelmektedir. Control e girecek karakter saysn snrlamakta kullanlr. Control n bool trden readOnly property si program Read Only mod a geirmekte kullanlr. Bu property nin default deeri false biimdedir. Yani property read only deildir. ReadOnly Text Box a klavye ile yaz girilemez fakat text property si yoluyla yaz girilebilir. Control n ScrollBars isimli property eleman ok satrl durumda etkili olur. Bu property ScrollBars isimli enum trndendir. Default durumu scrollBars.none biimindedir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); 49

} }

class MyForm : Form { private TextBox m_textBoxName; private Button m_buttonOK; public MyForm() { m_textBoxName = new TextBox(); m_textBoxName.Bounds = new Rectangle(0, 0, 100, 100); m_textBoxName.BackColor = Color.White; m_textBoxName.Multiline = true; m_textBoxName.ReadOnly = true; m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 140); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); this.Controls.AddRange(new Control[] { m_buttonOK, m_textBoxName }); } private void buttonOKClickHandler(object sender, EventArgs ea) { m_textBoxName.Text = "Sleyman"; } } } Control n bool trden WordWrap property si sarma yaplp yaplmayacan belirtir. Default durum true yani sarma yap lmasdr. Sarma kaldrlrsa enter a baslmadktan sonra aa satra geilmez. phesiz yatay kayd rma ubu u ancak sarma yoksa sz konusu olabilir. Control n Lines isimli Read/Write property si zellikle ok satrl mod iin anlamld r. Bu propert string dizisi trndendir. Control deki yazy satr satr tek hamlede elde etmek iin kullanlr. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } } 50

class MyForm : Form { private TextBox m_textBoxName; private Button m_buttonOK; public MyForm() { m_textBoxName = new TextBox(); m_textBoxName.Bounds = new Rectangle(0, 0, 100, 100); m_textBoxName.BackColor = Color.White; m_textBoxName.Multiline = true; m_textBoxName.ScrollBars = ScrollBars.Both; m_textBoxName.WordWrap = false; m_textBoxName.Lines = new string[] { "Ankara", "zmir", "Adana" }; m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 140); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); this.Controls.AddRange(new Control[] { m_buttonOK, m_textBoxName }); } private void buttonOKClickHandler(object sender, EventArgs ea) { foreach (string line in m_textBoxName.Lines) MessageBox.Show(line); } } } Control n bool trden Modified property si Control ilk yaratld nda false durumdad r. Her hangi bir karakter girildiinde control tarafndan true yaplr. Tipik olarak editr programlarnda save ileminden sonra bu property programc tarafndan false yap lr kta da kontrol edilir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

51

class MyForm : Form { private TextBox m_textBoxName; private Button m_buttonOK; public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);

m_textBoxName = new TextBox(); m_textBoxName.Bounds = new Rectangle(0, 0, 300, 200); m_textBoxName.BackColor = Color.White; m_textBoxName.Multiline = true; m_textBoxName.ScrollBars = ScrollBars.Both; m_textBoxName.WordWrap = false;

m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 240); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); this.Controls.AddRange(new Control[] { m_buttonOK, m_textBoxName });

} void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxName.Modified) { DialogResult dr = MessageBox.Show("Save Changes? ", "Message", MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) { e.Cancel = true; return; } if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } 52

} private void buttonOKClickHandler(object sender, EventArgs ea) { foreach (string line in m_textBoxName.Lines) MessageBox.Show(line); } } } Control n int trden read only TextLength property si girilen yaznn uzunlu unu vermektedir. Bu tamamen Text property sinin Length ini elde etmekle Length deerini elde etmek ayn anlamdad r. Control n TextAlign isimli propert eleman HorizontalAligntment isimli enum trndendir. Yatay hizalama da kullanlr. Default durum Left biimindedir. Control n char trden PasswordChar property si set edildiinde control parola girme modu na geer. Property ye girilen karakter parola girme karakteri olur. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private TextBox m_textBoxName; private Button m_buttonOK; public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);

m_textBoxName = new TextBox(); m_textBoxName.Bounds = new Rectangle(0, 0, 300, 200); m_textBoxName.BackColor = Color.White; m_textBoxName.Multiline = true; m_textBoxName.ScrollBars = ScrollBars.Both; m_textBoxName.WordWrap = false; m_textBoxName.TextAlign = HorizontalAlignment.Center; m_textBoxName.PasswordChar = '*'; 53

m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 240); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); this.Controls.AddRange(new Control[] { m_buttonOK, m_textBoxName });

} void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxName.Modified) { DialogResult dr = MessageBox.Show("Save Changes? ", "Message", MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) { e.Cancel = true; return; } if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } } private void buttonOKClickHandler(object sender, EventArgs ea) { foreach (string line in m_textBoxName.Lines) MessageBox.Show(line); } } }

Control deki herhangi bir blgeyi programlama yoluyla semek iin int trden SelectionStart ve SelectionLength property leri kullanlmaktadr. Text Box iindeki her karakterin bir indeksi vardr. (Enter tuu iin iki karakter kontrole baslmaktadr) Bu propert seilmi olan blgeyi belirlemek iin de kullanlabilir. Seilmi alandaki yaz Control n SelectedText propert si ile elde edilebilir. Eer hibir alan seilmemise SelectedText property si bo bir string ierir. SelectedText Read/Write property dir. Eer bu property ye bir yaz atanrsa seilmi olan yaz silinir. Yerine sanki paste ilemi yaplyormu gibi atanan yaz yerletirilir. Eer hibir yaz seilmemise imlecin 54

bulunduu yere insert ilemi yaplr. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private TextBox m_textBoxName; private Button m_buttonOK; public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);

m_textBoxName = new TextBox(); m_textBoxName.Bounds = new Rectangle(0, 0, 300, 200); m_textBoxName.BackColor = Color.White; m_textBoxName.Multiline = true; m_textBoxName.ScrollBars = ScrollBars.Both; m_textBoxName.WordWrap = false;

m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 240); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); this.Controls.AddRange(new Control[] { m_buttonOK, m_textBoxName });

} void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxName.Modified) { DialogResult dr = MessageBox.Show("Save Changes? ", "Message", 55

MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) { e.Cancel = true; return; } if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } } private void buttonOKClickHandler(object sender, EventArgs ea) { m_textBoxName.SelectedText = "kaan"; } } } Tipik bir uygulama (zellikle chat programlarnda grlr. Text Box n sonuna programlama yoluyla yaz eklemektedir. Bu ilem ou kez yanl yap lmaktadr. Pek ok programc yanllkla yazy control n Text property sine eklemektedir. Byle yapldnda Text property sine yeni bir yaz girildii iin kayd rma ubuu bata grnr. Kayd rma ubu unun sonda kalmas iin Text property sine atama yerine insert uygulanmald r. Yani imle sona ekilip paste ilemi yaplmaldr. Paste ilemi daha nce akland gibi SelectedText property si ile yaplabilir. mlecin sona ekilmesi SelctionStart property sine uygun deerin atanmasyla salanabilir. SelectionStart property si ayn zamanda seme ileminin yansra imleci de tamaktadr. Yanl uygulama: using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { 56

private TextBox m_textBoxName; private Button m_buttonOK; private int m_count; public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);

m_textBoxName = new TextBox(); m_textBoxName.Bounds = new Rectangle(0, 0, 300, 200); m_textBoxName.BackColor = Color.White; m_textBoxName.Multiline = true; m_textBoxName.ScrollBars = ScrollBars.Both; m_textBoxName.WordWrap = false;

m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 240); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); this.Controls.AddRange(new Control[] { m_buttonOK, m_textBoxName });

} void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxName.Modified) { DialogResult dr = MessageBox.Show("Save Changes? ", "Message", MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) { e.Cancel = true; return; } if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } }

57

private void buttonOKClickHandler(object sender, EventArgs ea) { m_textBoxName.Text += m_count.ToString() + "\r\n"; ++m_count; } } } Doru Uygulama: using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private TextBox m_textBoxName; private Button m_buttonOK; private int m_count; public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);

m_textBoxName = new TextBox(); m_textBoxName.Bounds = new Rectangle(0, 0, 300, 200); m_textBoxName.BackColor = Color.White; m_textBoxName.Multiline = true; m_textBoxName.ScrollBars = ScrollBars.Both; m_textBoxName.WordWrap = false;

m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 240); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); this.Controls.AddRange(new Control[] { m_buttonOK, m_textBoxName });

58

} void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxName.Modified) { DialogResult dr = MessageBox.Show("Save Changes? ", "Message", MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) { e.Cancel = true; return; } if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } } private void buttonOKClickHandler(object sender, EventArgs ea) { m_textBoxName.SelectionStart = m_textBoxName.TextLength; m_textBoxName.SelectedText = "\r\n" + m_count.ToString() ; ++m_count; } } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form 59

{ private TextBox m_textBoxChat; private TextBox m_textBoxUser; private Button m_buttonOK;

public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing); this.FormBorderStyle = FormBorderStyle.Fixed3D; this.Size = new Size(600, 450); this.MaximizeBox = false; m_textBoxChat = new TextBox(); m_textBoxChat.Bounds = new Rectangle(10, 10, this.ClientSize.Width - 20, 300); m_textBoxChat.BackColor = Color.White; m_textBoxChat.Multiline = true; m_textBoxChat.ScrollBars = ScrollBars.Vertical; m_textBoxChat.WordWrap = false; m_textBoxChat.ReadOnly = true; m_textBoxChat.TabStop = false; m_textBoxUser = new TextBox(); m_textBoxUser.Bounds = new Rectangle(10, 330, this.ClientSize.Width - 20, 50); m_textBoxUser.BackColor = Color.White; m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(250, 380); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); m_textBoxUser.KeyDown += new KeyEventHandler(MyForm_KeyDown);

this.Controls.AddRange(new Control[] { m_textBoxUser, m_textBoxChat, m_buttonOK }); } void MyForm_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) buttonOKClickHandler(null, null); } void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxChat.Modified) { DialogResult dr = MessageBox.Show("Save Changes? ", "Message", MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) 60

{ e.Cancel = true; return; } if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } } private void buttonOKClickHandler(object sender, EventArgs ea) { m_textBoxChat.SelectionStart = m_textBoxChat.TextLength; m_textBoxChat.SelectedText = "<Kaan>: " + m_textBoxUser.Text + "\r\n"; m_textBoxUser.Text = string.Empty; m_textBoxUser.Focus(); } } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private TextBox m_textBoxChat; private TextBox m_textBoxUser; private Button m_buttonOK;

public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing); 61

this.FormBorderStyle = FormBorderStyle.Fixed3D; this.Size = new Size(600, 450); this.MaximizeBox = false; m_textBoxChat = new TextBox(); m_textBoxChat.Bounds = new Rectangle(10, 10, this.ClientSize.Width - 20, 300); m_textBoxChat.BackColor = Color.White; m_textBoxChat.Multiline = true; m_textBoxChat.ScrollBars = ScrollBars.Vertical; m_textBoxChat.WordWrap = false; m_textBoxChat.ReadOnly = true; m_textBoxChat.TabStop = false; m_textBoxUser = new TextBox(); m_textBoxUser.Bounds = new Rectangle(10, 330, this.ClientSize.Width - 20, 50); m_textBoxUser.BackColor = Color.White; m_textBoxUser.KeyDown += new KeyEventHandler(MyForm_KeyDown); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(250, 380); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); m_buttonOK.Enabled = false;

this.Controls.AddRange(new Control[] { m_textBoxUser, m_textBoxChat, m_buttonOK }); } void MyForm_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) buttonOKClickHandler(null, null); else m_buttonOK.Enabled = true; } void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxChat.Modified) { DialogResult dr = MessageBox.Show("Save Changes? ", "Message", MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) { e.Cancel = true; return; } 62

if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } } private void buttonOKClickHandler(object sender, EventArgs ea) { if (m_textBoxUser.Text == string.Empty) { return; } m_textBoxChat.SelectionStart = m_textBoxChat.TextLength; m_textBoxChat.SelectedText = "<Kaan>: " + m_textBoxUser.Text + "\r\n"; m_textBoxUser.Text = string.Empty; m_buttonOK.Enabled = false; m_textBoxUser.Focus(); } } } TextBox control nn tam olarak clipboard ve undo destei vard r. Control n TextBoxBase snfndan gelen Copy, Cut, Paste fonksiyonlar seili alan zerinde clipboard ilemi yapar. phesiz kullanc bu ileri klavyeyi kullanarak da yapabilir. Fakat bu fonksiyonlar bu ilerin programlama yoluyla yaplmasn salamaktad t. TextBox snfnn kendine zg(yani Control snfndan gelmeyen) event elemanlar da vard r. Bu event elemanlarnn bazlar TextBoxBase snfndan gelmitir. rnein snfn TextBoxBase snfndan gelen ModifiedChanged event eleman TextBox a ilkez karakter girildiinde tetiklenir. Yani Control n Modified property si false yapldktan sonra Control a karakter girildiinde modified property si deitii iin bu event tetiklenir. TextBox snfn dier event elemanlar dkmanlardan incelenmelidir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); 63

} }

class MyForm : Form { private TextBox m_textBoxChat; private TextBox m_textBoxUser; private Button m_buttonOK;

public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing); this.FormBorderStyle = FormBorderStyle.Fixed3D; this.Size = new Size(600, 450); this.MaximizeBox = false; m_textBoxChat = new TextBox(); m_textBoxChat.Bounds = new Rectangle(10, 10, this.ClientSize.Width - 20, 300); m_textBoxChat.BackColor = Color.White; m_textBoxChat.Multiline = true; m_textBoxChat.ScrollBars = ScrollBars.Vertical; m_textBoxChat.WordWrap = false; m_textBoxChat.ReadOnly = true; m_textBoxChat.TabStop = false; m_textBoxUser = new TextBox(); m_textBoxUser.Bounds = new Rectangle(10, 330, this.ClientSize.Width-20, 50); m_textBoxUser.BackColor = Color.White; m_textBoxUser.KeyDown += new KeyEventHandler(MyForm_KeyDown); m_textBoxUser.ModifiedChanged += new EventHandler(m_textBoxUser_ModifiedChanged); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(250, 380); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); m_buttonOK.Enabled = false; this.Controls.AddRange(new Control[] { m_textBoxUser, m_textBoxChat, m_buttonOK}); } void m_textBoxUser_ModifiedChanged(object sender, EventArgs e) { m_buttonOK.Enabled = true;

64

void MyForm_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { buttonOKClickHandler(null, null); } else m_buttonOK.Enabled = true; } void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxChat.Modified) { DialogResult dr = MessageBox.Show("Save Changes? ", "Message", MessageBoxButtons.YesNoCancel); if (dr == DialogResult.Cancel) { e.Cancel = true; return; } if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } } private void buttonOKClickHandler(object sender, EventArgs ea) { if (m_textBoxUser.Text == string.Empty) { return; } m_textBoxChat.SelectionStart = m_textBoxChat.TextLength; m_textBoxChat.SelectedText = "<Kaan>: " + m_textBoxUser.Text + "\r\n"; m_textBoxUser.Text = string.Empty; m_buttonOK.Enabled = false; m_textBoxUser.Focus(); } } }

65

Anahtar Notlar: Internetten "windows forms faq" listesi incelenmelidir. Bu dkumanlarla paralel olacak biimde Windows 2005 C# Recipes, C# Cookcook ve C# programmers Cookbook benzer temal kitaplardr. Ayrca Microsoft un .net le ilgili bazlar yo un bazlar az yo un olan haber guruplar vardr. Bu haber gruplar microsoft.public.dotnet n ekiyle balamaktad r ve Google tm USNET guruplarnda oldu u gibi bu guruplarda arama ve post ilemlerine izin vermektedir. rnein "microsoft.public.dotnet.languages.csharp" genel konular iin "microsoft.public.dotnet.faq" ok sorulan sorular iin, form programlama iin"microsoft.public.dotnet.framework.windowsforms" ve bunlarn altndaki guruplara baklabilir. Label Control: Amac sadece bir yazy gstermek olan basit alt pencerelere API dnyasnda "static" kontrol .net te ise "Label" denilmektedir. Label bir alt penceredir. Tek grevi yaz gstermektir. Pencere pasif durumdadr. Bu nedenle Fare mesajlar aaya iletilir. Ayn zamanda Control n zemin rengi transparan olduu iin kullanc bir pencere grntsyle karlamaz. Tabi phesiz dier kontrollerde olduu gibi kenar izgileri ve zemin rengi istenildii gibi ayarlanabilir. LabelControl Label snf yla temsil edilmitir. Label snf do rudan control snfndan tretilmitir. Programc label trnden nesneyi default balang fonksiyonu ile yaratr. Sonra Control n text property sine grntglenecek yazy girer. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private TextBox m_textBoxChat; private TextBox m_textBoxUser; private Button m_buttonOK; private Label m_label;

public MyForm() { this.Text = "TextBox Sample"; this.FormClosing += new FormClosingEventHandler(MyForm_FormClosing); this.FormBorderStyle = FormBorderStyle.Fixed3D; this.Size = new Size(600, 450); this.MaximizeBox = false; m_textBoxChat = new TextBox(); m_textBoxChat.Bounds = new Rectangle(10, 10, this.ClientSize.Width - 20, 300); 66

m_textBoxChat.BackColor = Color.White; m_textBoxChat.Multiline = true; m_textBoxChat.ScrollBars = ScrollBars.Vertical; m_textBoxChat.WordWrap = false; m_textBoxChat.ReadOnly = true; m_textBoxChat.TabStop = false; m_textBoxUser = new TextBox(); m_textBoxUser.Bounds = new Rectangle(10, 330, this.ClientSize.Width-20, 50); m_textBoxUser.BackColor = Color.White; m_textBoxUser.KeyDown += new KeyEventHandler(MyForm_KeyDown); m_textBoxUser.ModifiedChanged += new EventHandler(m_textBoxUser_ModifiedChanged); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(250, 380); m_buttonOK.Click += new EventHandler(buttonOKClickHandler); m_buttonOK.Enabled = false; m_label = new Label(); m_label.Text = "Enter Text: "; m_label.Location = new Point(10, 315); this.Controls.AddRange(new Control[] { m_textBoxUser, m_textBoxChat, m_buttonOK, m_label}); } void m_textBoxUser_ModifiedChanged(object sender, EventArgs e) { m_buttonOK.Enabled = true;

} void MyForm_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { buttonOKClickHandler(null, null); } else m_buttonOK.Enabled = true; } void MyForm_FormClosing(object sender, FormClosingEventArgs e) { if (m_textBoxChat.Modified) {
DialogResult dr = MessageBox.Show("Save Changes? ", "Message", MessageBoxButtons.YesNoCancel);

67

if (dr == DialogResult.Cancel) { e.Cancel = true; return; } if (dr == DialogResult.Yes) { MessageBox.Show("Saving"); } else { } } } private void buttonOKClickHandler(object sender, EventArgs ea) { if (m_textBoxUser.Text == string.Empty) { return; } m_textBoxChat.SelectionStart = m_textBoxChat.TextLength; m_textBoxChat.SelectedText = "<Kaan>: " + m_textBoxUser.Text + "\r\n"; m_textBoxUser.Text = string.Empty; m_buttonOK.Enabled = false;

m_textBoxUser.Focus(); } } } ListBox Control : Listeleme kutular bir gurup eleman listelemek bir ya da daha fazlasnn seilmesine olanak vermektedir. Listeleme kutular ile seimli listeleme kutular(combo boxes)bir birlerine benzeyen kontrollerdir. Bu nedenle bunlarn ortak elemanlar ListControl isimli bir snfta toplanmtr. Control

ListControl

ListBox

ComboBox

68

ListBox Control tipik olarak yle kullanlr: 1. Control ListBox snfnn default balang fonksiyonuyla yaratlr. (Text Property sinin bu control de bir nemi yoktur) 2. Snfn Items isimli property eleman ListBox.ObjectCollection isimli bir collection snf trndendir. Bu collection snf IList arayzn desteklemektedir. Bu snf adeta ArrayList gibi object tutan bir snftr. ListBox Control bu collection elemana eklenen her nesne iin sanal ToString fonksiyonunu arr ve oradan elde ettii yazy control e yerletirir. 3. ListBox snfnn eitli property ve event elemanlar aada ele alnacak olan faydal ilere yol amaktadr. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private ListBox m_listBox; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(500, 500); m_listBox = new ListBox(); m_listBox.Bounds = new Rectangle(100, 50, 200, 300); for (int i = 0; i < 100; ++i) m_listBox.Items.Add(new Sample(i)); this.Controls.AddRange(new Control[] { m_listBox }); } //... } class Sample { private int m_a; public Sample(int a) { m_a = a; 69

} public override string ToString() { return "Number: " + m_a.ToString(); } public int A { get { return m_a; } } } } Grld gibi ListBox control ayn zamandabir collection gibidir. Control n Bool trden Sorted isimli property eleman eklenen elemanlar sral bir biimde gstermekte kullanlr. Anahtar Notlar: C# da bir dizi refansnn baka bir dizi referansna atanabilmesi iin her iki dizi referansnnda referans trlerine ilikin olmas ve kaynak dizi trnn hedef dizi trnden tretilmi olmas gerekmektedir. Object [] o; string []s; int [] x; //... o=s; //geerli o= x; //geersiz; s=x;// geersiz. Int tr, Double trne dorudan atanabilir. Int dizi referans double dizi referansna dorudan atanabilemez. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private ListBox m_listBox; public MyForm() { 70

this.Text = "Sample ListBox"; this.Size = new Size(500, 500); m_listBox = new ListBox(); m_listBox.Bounds = new Rectangle(100, 50, 200, 300); m_listBox.Sorted = true; string[] cities = {"Ankara", "Eskiehir", "zmir", "Bursa", "Adana", "stanbul", "Mersin", "Bartn", "Yalova", "Sivas", "Bilecik"};

m_listBox.Items.AddRange(cities); this.Controls.AddRange(new Control[] { m_listBox }); } //... } class Sample { private int m_a; public Sample(int a) { m_a = a; } public override string ToString() { return "Number: " + m_a.ToString(); } public int A { get { return m_a; } } } } Bu property yalnzca Items.Add yap ld nda etkili olmaktadr. Insert yapldnda geerli olmaz. Yani insert ileminde bu property ye baklmamaktadr. Yalnzca Add' e baklmaktadr. ListBox snfnn Bool trden HorizontalScrollBar property si yatay kaydrma ubuunu grntlemkte kullanlr. Bu property nin default durumu false dur. (Dey Scroll Bar her zaman grntlenmektedir. Bir elemana ft tkland nda o elemana ilikin bir ilemin balatlmas istenebilir. Bunun iin ListBox snfnn control snfndan gelen DoubleClick eleman kullanlr. DoubleClick event eleman EventHandler isimli delege trndendir. Bu event olutuunda seilmi olan eleman verilmemektedir. Seilmi olan eleman herhangi bir zaman object trnden SelectedItem property si 71

ile elde edilebilir. Eer hibir eleman seili deilse SelectedItem eleman Null referans verir. ListBox Control tek seimli ya da ok seimli olabilir. Default durum tek seimli olmasd r. Snfn SelectionMode isimli property si SelectionMode isimli enum trndendir. Bu enum trnn elemanlar unlardr. None: Bu durumda her hangi bir eleman seilemez. One: Bu durumda bir tane eleman seilebilir. Default durumdur. MultiSimple: Birden fazla eleman seilebilir. MultiExtended: Hem ayrk hemde ardl seim yap labilir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private ListBox m_listBox; private Button m_buttonOK; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(500, 500); m_listBox = new ListBox(); m_listBox.Bounds = new Rectangle(100, 50, 200, 300); m_listBox.Sorted = true; m_listBox.DoubleClick += new EventHandler(m_listBox_DoubleClick); m_listBox.SelectionMode = SelectionMode.MultiSimple; string[] cities = {"Ankara", "Eskiehir", "zmir", "Bursa", "Adana", "stanbul", "Mersin", "Bartn", "Yalova", "Sivas", "Bilecik"};

m_listBox.Items.AddRange(cities); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(350, 200); m_buttonOK.Click += new EventHandler(m_buttonOK_Click);

72

this.Controls.AddRange(new Control[] { m_listBox, m_buttonOK }); } void m_buttonOK_Click(object sender, EventArgs e) { MessageBox.Show((string)m_listBox.SelectedItem); } void m_listBox_DoubleClick(object sender, EventArgs e) { MessageBox.Show((string)m_listBox.SelectedItem); }

//... }

} ListBox snfnn selectedIndices isimli property si ListBox.SelectedIndexCollection isimli collection snf trndendir. Eer oklu seime izin verilmise seilmi elemann indexleri SelctedIndices property si ile alnabilir. Eer tek eleman seilebiliyorsa seilmi elemann index i int trden selctedIndex property si ile alnabilir. Benzer biimde SlectedItems isimli property si de ListBox.SelectedObjectCollection isimli collection trndendir. Tm seilmi elemanlar verir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private ListBox m_listBox; private Button m_buttonOK; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(500, 500);

73

m_listBox = new ListBox(); m_listBox.Bounds = new Rectangle(100, 50, 200, 300); m_listBox.Sorted = true; m_listBox.DoubleClick += new EventHandler(m_listBox_DoubleClick); m_listBox.SelectionMode = SelectionMode.MultiExtended; string[] cities = {"Ankara", "Eskiehir", "zmir", "Bursa", "Adana", "stanbul", "Mersin", "Bartn", "Yalova", "Sivas", "Bilecik"};

m_listBox.Items.AddRange(cities); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(350, 200); m_buttonOK.Click += new EventHandler(m_buttonOK_Click);

this.Controls.AddRange(new Control[] { m_listBox, m_buttonOK }); } void m_buttonOK_Click(object sender, EventArgs e) { string text = null; foreach (string s in m_listBox.SelectedItems) text += s + " "; MessageBox.Show(text); } void m_listBox_DoubleClick(object sender, EventArgs e) { MessageBox.Show((string)m_listBox.SelectedItem); }

//... } } Grld gibi SelectedIndex ve SelectedIndices propertyleri ile SelectedItem property si Read/Write propertylerdir. Yani biz bu sayede programlama yoluyla istenilen bir eleman seili bir duruma getirebiliriz. ListBox snfnn Bool trden MultiColumn property si listeleme kutusunu ok stunlu yapmakta kullanlr. Default durum tek stnlu olmasdr. using System; using System.Windows.Forms; using System.Drawing; 74

namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private ListBox m_listBox; private Button m_buttonOK; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(500, 500); m_listBox = new ListBox(); m_listBox.Bounds = new Rectangle(100, 50, 200, 100); m_listBox.Sorted = true; m_listBox.DoubleClick += new EventHandler(m_listBox_DoubleClick); m_listBox.SelectionMode = SelectionMode.MultiExtended; string[] cities = {"Ankara", "Eskiehir", "zmir", "Bursa", "Adana", "stanbul", "Mersin", "Bartn", "Yalova", "Sivas", "Bilecik"};

m_listBox.Items.AddRange(cities); m_listBox.SelectedItem = "Eskiehir"; m_listBox.MultiColumn = true; m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(350, 200); m_buttonOK.Click += new EventHandler(m_buttonOK_Click);

this.Controls.AddRange(new Control[] { m_listBox, m_buttonOK }); } void m_buttonOK_Click(object sender, EventArgs e) { string text = null; foreach (string s in m_listBox.SelectedItems) text += s + " "; 75

MessageBox.Show(text); } void m_listBox_DoubleClick(object sender, EventArgs e) { MessageBox.Show((string)m_listBox.SelectedItem); }

//... }

} ListBox snfnn yukardan gelmeyen yani snfn kendisine zg olan SelectedIndexChanged isimli event eleman seili olan eleman deitiinde tetiklenir. Bu event eleman EventHandler isimli delege trndendir. using System; using System.Windows.Forms; using System.Drawing; using System.Collections; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private ListBox m_listBox; private ListBox m_listBoxOther; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(800, 500); m_listBox = new ListBox(); m_listBox.Bounds = new Rectangle(30, 50, 200, 300); m_listBox.Sorted = true; m_listBox.DoubleClick += new EventHandler(m_listBox_DoubleClick); m_listBox.SelectionMode = SelectionMode.MultiExtended; m_listBox.Items.Add(new City("stanbul", "Beikta", "ili", "skdar", "Kadiky", 76

"Kartal", "Pendik", "Tuzla", "Adalar")); m_listBox.Items.Add(new City("Adana", "Ceyhan", "Seyhan", "Kozan")); m_listBox.Items.Add(new City("Eskiehir", "Mihalk", "Seyitgazi", "Alpu")); m_listBox.Items.Add(new City("Antalya", "Finike", "Seril", "Serik", "Alanya", "Manavgat")); m_listBox.SelectedItem = "Eskiehir"; m_listBox.MultiColumn = true; m_listBox.SelectedIndexChanged += new EventHandler(m_listBox_SelectedIndexChanged);

m_listBoxOther = new ListBox(); m_listBoxOther.Bounds= new Rectangle(350, 50, 200, 300);

this.Controls.AddRange(new Control[] { m_listBox, m_listBoxOther}); } void m_listBox_SelectedIndexChanged(object sender, EventArgs e) { City city = (City)m_listBox.SelectedItem; m_listBoxOther.Items.Clear(); foreach (string s in city.Towns) m_listBoxOther.Items.Add(s); } void m_listBox_DoubleClick(object sender, EventArgs e) { MessageBox.Show((string)m_listBox.SelectedItem); }

//... }

class City { private string m_cityName; private ArrayList m_towns; public City(string cityName, params string[] tokens) { m_cityName = cityName; m_towns = new ArrayList(tokens); 77

} public string CityName { get { return m_cityName; } } public ArrayList Towns { get { return m_towns; } } public override string ToString() { return m_cityName; }

//... } } Seimli Listeleme Kutular: Seimli listeleme kutular aslnda listeleme kutusuna bir textBox ya da Label kontrolnn ilitirilmesi ile elde edilmitir. Seilen eleman listeleme kutusunun balk ksm nda grntlenir. phesiz bu kontrol de oklu seim zellii yoktur. Control kapalyken az yer kaplad iin ListBox kontrolne gre olduka sk tercih edilmektedir. ComboBox kullanm ListBox kullanmna ok benzer.Control ComboBox snfyla temsil edilmitir. Control ListControl snfndan tretilmitir. ComboBox kullanm byk lde ListBox kullanmna benzemektedir. Burada farkllklar zerinde durulacaktr. using System; using System.Windows.Forms; using System.Drawing; using System.Collections; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form 78

{ private ComboBox m_comboBox; private ListBox m_listBoxOther; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(800, 500); m_comboBox = new ComboBox(); m_comboBox.Bounds = new Rectangle(30, 50, 200, 300); m_comboBox.Sorted = true; m_comboBox.DoubleClick += new EventHandler(m_listBox_DoubleClick); m_comboBox.Items.Add(new City("stanbul", "Beikta", "ili", "skdar", "Kadiky", "Kartal", "Pendik", "Tuzla", "Adalar")); m_comboBox.Items.Add(new City("Adana", "Ceyhan", "Seyhan", "Kozan")); m_comboBox.Items.Add(new City("Eskiehir", "Mihalk", "Seyitgazi", "Alpu")); m_comboBox.Items.Add(new City("Antalya", "Finike", "Seril", "Serik", "Alanya", "Manavgat")); m_comboBox.SelectedItem = "Eskiehir"; m_comboBox.SelectedIndexChanged += new EventHandler(m_listBox_SelectedIndexChanged); m_listBoxOther = new ListBox(); m_listBoxOther.Bounds= new Rectangle(350, 50, 200, 300);

this.Controls.AddRange(new Control[] { m_comboBox, m_listBoxOther}); } void m_listBox_SelectedIndexChanged(object sender, EventArgs e) { City city = (City)m_comboBox.SelectedItem; m_listBoxOther.Items.Clear(); foreach (string s in city.Towns) m_listBoxOther.Items.Add(s); } void m_listBox_DoubleClick(object sender, EventArgs e) { MessageBox.Show((string)m_comboBox.SelectedItem); }

//... 79

class City { private string m_cityName; private ArrayList m_towns; public City(string cityName, params string[] tokens) { m_cityName = cityName; m_towns = new ArrayList(tokens); } public string CityName { get { return m_cityName; } } public ArrayList Towns { get { return m_towns; } } public override string ToString() { return m_cityName; }

//... } } ComboBox snfnn DropDownStyle isimli property eleman ComboBoxStyle isimli enum trndendir. Bu eneum trnn elemanlar ve anlamlar yledir. Simple: Bu modda combobox srekli aktr ve kapatlamaz. using System; using System.Windows.Forms; using System.Drawing; using System.Collections; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } 80

class MyForm : Form { private ComboBox m_comboBox; private ListBox m_listBoxOther; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(800, 500); m_comboBox = new ComboBox(); m_comboBox.Bounds = new Rectangle(30, 50, 200, 300); m_comboBox.Sorted = true; m_comboBox.DoubleClick += new EventHandler(m_listBox_DoubleClick); m_comboBox.Items.Add(new City("stanbul", "Beikta", "ili", "skdar", "Kadiky", "Kartal", "Pendik", "Tuzla", "Adalar")); m_comboBox.Items.Add(new City("Adana", "Ceyhan", "Seyhan", "Kozan")); m_comboBox.Items.Add(new City("Eskiehir", "Mihalk", "Seyitgazi", "Alpu")); m_comboBox.Items.Add(new City("Antalya", "Finike", "Seril", "Serik", "Alanya", "Manavgat")); m_comboBox.SelectedItem = "Eskiehir"; m_comboBox.SelectedIndexChanged += new EventHandler(m_listBox_SelectedIndexChanged); m_comboBox.DropDownStyle = ComboBoxStyle.Simple; m_listBoxOther = new ListBox(); m_listBoxOther.Bounds= new Rectangle(350, 50, 200, 300);

this.Controls.AddRange(new Control[] { m_comboBox, m_listBoxOther}); } void m_listBox_SelectedIndexChanged(object sender, EventArgs e) { City city = (City)m_comboBox.SelectedItem; m_listBoxOther.Items.Clear(); foreach (string s in city.Towns) m_listBoxOther.Items.Add(s); } void m_listBox_DoubleClick(object sender, EventArgs e) { MessageBox.Show((string)m_comboBox.SelectedItem); } 81

//... }

class City { private string m_cityName; private ArrayList m_towns; public City(string cityName, params string[] tokens) { m_cityName = cityName; m_towns = new ArrayList(tokens); } public string CityName { get { return m_cityName; } } public ArrayList Towns { get { return m_towns; } } public override string ToString() { return m_cityName; }

//... } } DropDown: Bu default durumdur. Programc edit alanna yaz girebilir. Yani girilecek yaz Combobox iindeki yazlardan bir olmak zorunda deildir. DropDownList: Bu modda ComboBox control nn edit alan read only dir. Dolaysyla kesinlikle listede olan elemanlardan biri seilir. using System; using System.Windows.Forms; using System.Drawing; using System.Collections; namespace CSD { 82

class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private ComboBox m_comboBox; private ListBox m_listBoxOther; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(800, 500); m_comboBox = new ComboBox(); m_comboBox.Bounds = new Rectangle(30, 50, 200, 300); m_comboBox.Sorted = true; m_comboBox.DoubleClick += new EventHandler(m_listBox_DoubleClick); m_comboBox.Items.Add(new City("stanbul", "Beikta", "ili", "skdar", "Kadiky", "Kartal", "Pendik", "Tuzla", "Adalar")); m_comboBox.Items.Add(new City("Adana", "Ceyhan", "Seyhan", "Kozan")); m_comboBox.Items.Add(new City("Eskiehir", "Mihalk", "Seyitgazi", "Alpu")); m_comboBox.Items.Add(new City("Antalya", "Finike", "Seril", "Serik", "Alanya", "Manavgat")); m_comboBox.SelectedItem = "Eskiehir"; m_comboBox.SelectedIndexChanged += new EventHandler(m_listBox_SelectedIndexChanged); m_comboBox.DropDownStyle = ComboBoxStyle.DropDownList;

m_listBoxOther = new ListBox(); m_listBoxOther.Bounds= new Rectangle(350, 50, 200, 300);

this.Controls.AddRange(new Control[] { m_comboBox, m_listBoxOther}); } void m_listBox_SelectedIndexChanged(object sender, EventArgs e) { City city = (City)m_comboBox.SelectedItem; m_listBoxOther.Items.Clear(); foreach (string s in city.Towns) 83

m_listBoxOther.Items.Add(s); } void m_listBox_DoubleClick(object sender, EventArgs e) { MessageBox.Show((string)m_comboBox.SelectedItem); }

//... }

class City { private string m_cityName; private ArrayList m_towns; public City(string cityName, params string[] tokens) { m_cityName = cityName; m_towns = new ArrayList(tokens); } public string CityName { get { return m_cityName; } } public ArrayList Towns { get { return m_towns; } } public override string ToString() { return m_cityName; }

//... } } DropDown modda edit alan iine girilen yaz seilmi olan anlamna gelmez. Yani edit alanndaki yaz seilmi elemann yazs olmak zorunda deildir. Bu nedenle programc bu modda seilmi eleman almak yerine kontrol n edit alanndaki yaznn alnmas daha anlaml olabilir. Control n edit alanndaki yaz ComboBox kontrolnn Text property si ile elde edilebilir. using System; using System.Windows.Forms; 84

using System.Drawing; using System.Collections; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private ComboBox m_comboBox; private ListBox m_listBoxOther; public MyForm() { this.Text = "Sample ListBox"; this.Size = new Size(800, 500); this.Click += new EventHandler(MyForm_Click); m_comboBox = new ComboBox(); m_comboBox.Bounds = new Rectangle(30, 50, 200, 300); m_comboBox.Sorted = true; m_comboBox.DoubleClick += new EventHandler(m_listBox_DoubleClick); m_comboBox.Items.Add(new City("stanbul", "Beikta", "ili", "skdar", "Kadiky", "Kartal", "Pendik", "Tuzla", "Adalar")); m_comboBox.Items.Add(new City("Adana", "Ceyhan", "Seyhan", "Kozan")); m_comboBox.Items.Add(new City("Eskiehir", "Mihalk", "Seyitgazi", "Alpu")); m_comboBox.Items.Add(new City("Antalya", "Finike", "Seril", "Serik", "Alanya", "Manavgat")); m_comboBox.SelectedItem = "Eskiehir"; m_comboBox.SelectedIndexChanged += new EventHandler(m_listBox_SelectedIndexChanged); m_comboBox.DropDownStyle = ComboBoxStyle.DropDown;

m_listBoxOther = new ListBox(); m_listBoxOther.Bounds= new Rectangle(350, 50, 200, 300);

this.Controls.AddRange(new Control[] { m_comboBox, m_listBoxOther}); }

85

void MyForm_Click(object sender, EventArgs e) { MessageBox.Show(m_comboBox.Text); } void m_listBox_SelectedIndexChanged(object sender, EventArgs e) { City city = (City)m_comboBox.SelectedItem; m_listBoxOther.Items.Clear(); foreach (string s in city.Towns) m_listBoxOther.Items.Add(s); } void m_listBox_DoubleClick(object sender, EventArgs e) { MessageBox.Show((string)m_comboBox.SelectedItem); }

//... }

class City { private string m_cityName; private ArrayList m_towns; public City(string cityName, params string[] tokens) { m_cityName = cityName; m_towns = new ArrayList(tokens); } public string CityName { get { return m_cityName; } } public ArrayList Towns { get { return m_towns; } } public override string ToString() { return m_cityName; }

//... 86

} } ComboBox snfnn dier elemanlar MSDN dkumanlar ndan okunabilir. Seenek Kutular: Check Boxes bir kk kutucuk ve yannda bir yazdan olumaktadr. Bir zelliin bir btne dahil edilip edilmeyeceini belirlemektedir. Kontrol den elde edilecek tek bilgi control n arplanp arplanmad dr. Seenek kutular CheckBox snfyla temsil edilmitir. Daha nce de bahsedildii gibi bu snf ButtonBase snfndan tretilmitir. Control

ButtonBase

Check Box

RadioButton

Button

Seenek Kutular yle kullanlr: 1. CheckBox trnden bir snf nesnesi snfn default balang fonksiyonu ile yaratlr. 2. Control n Bool trden AutoCheck property si seenek kutusunu otomatik ve ya manuel yapmak iin kullanlr. Otomatik modda arplanp arp nn kaldrlmas(uncheck) tklandnda kontrol tarafndan yaplr. Manuel biim modda ise control e tklandnda event oluur. arplama programc tarafndan yap lr. Default durum otomatik moddur. 3. Contol n Bool trden Read/Write Checked property si Control n arplanp arplanmadn ve programlama yoluyla arplamak iin kullanlr. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private CheckBox m_checkBox; private Button m_buttonOK;

87

public MyForm() { m_checkBox = new CheckBox(); m_checkBox.Text = "Backup alnsn m?"; m_checkBox.Bounds = new Rectangle(100, 100, 200, 100); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location= new Point(150, 200); m_buttonOK.Click += new EventHandler(m_buttonOK_Click);

m_checkBox.Parent = this; m_buttonOK.Parent = this; } void m_buttonOK_Click(object sender, EventArgs e) { MessageBox.Show(m_checkBox.Checked ? "Checked" : "Unchecked"); } //... } } Yaznn kutuya gre hizalanmas snfn CheckAlign property si ile salanabilir. Bu property ContentAlingment isimli enum trndendir. Bu enum trnn aadaki biimde hizalama salar. -

TestAlingment property si ise hizalamay yazya gre yapar. Radyo D meleri (Radio Button): Radio dmeleri genellikle bir gurup oluturacak biimde birden fazla kullanlr. Bir la seenekten yalnzca birinin seilecei durumlarda tercih edilmektedir. Radio dmesi bir kk yuvarlakk ve bir de yazdan oluur. rnein 5 seenekli bir radio dmesi gurubu oluturacaksak 5 ayr radio dmesi nesnesi yaratmalyz. st pencereleri ayn olan tm radio dmeleri ayn gurup iindedir. Bu nedenle dorudan bir form zerine birden fazla gurup radio dmesi yerletirilemez. Bunu salamak iin GroupBox denilen zel alt pencereler kullanlr. Bu durumda programc tipik olarak form zerine birden fazla groupBox penceresi olu turur. Radio dmelerini de bu GroupBox penceresinin iinde yaratr. Bir grup radio d mesi yle yaratlr: 1. Radio dmeleri RadioButton snfyla temsil edilmitir. Programc snfn default balang fonksiyonunu kullanarak birden fazla RadioButton nesnesi yaratr. 2. Nesnelerin Text propertyleri uygun yazlarla set edilir. 3. Radio dmeleri de otomatik ve manuel olabilmektedir. Default durum yine otomatik moddur. 4. Hangi radio dmesinin arplandn anlamak iin tek tek radio dmelerinin Checked property sine baklmaldr.

88

using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private RadioButton m_radio1, m_radio2, m_radio3, m_radio4; private Button m_buttonOK; public MyForm() { m_radio1 = new RadioButton(); m_radio1.Text = "A"; m_radio1.Location = new Point(50, 50); m_radio2 = new RadioButton(); m_radio2.Text = "B"; m_radio2.Location = new Point(50, 80); m_radio3 = new RadioButton(); m_radio3.Text = "C"; m_radio3.Location = new Point(50, 110); m_radio4 = new RadioButton(); m_radio4.Text = "D"; m_radio4.Location = new Point(50, 140); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 95); m_buttonOK.Click += new EventHandler(m_buttonOK_Click); this.Controls.AddRange(new Control[] { m_radio1, m_radio2, m_radio3, m_radio4, m_buttonOK }); } void m_buttonOK_Click(object sender, EventArgs e) { foreach (Control c in this.Controls) { RadioButton rb; 89

rb = c as RadioButton; if (rb != null) { if (rb.Checked) { MessageBox.Show(rb.Text + " Checked"); break; } } } } //... } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private GroupBox m_group1, m_group2; private RadioButton m_radio1, m_radio2, m_radio3, m_radio4; private RadioButton m_radio5, m_radio6, m_radio7, m_radio8; private Button m_buttonOK; public MyForm() { m_group1 = new GroupBox(); m_group1.Text = "Group1"; m_group1.Bounds = new Rectangle(30, 30, 150, 160);

m_group2 = new GroupBox(); m_group2.Text = "Group2"; m_group2.Bounds = new Rectangle(30, 200, 220, 220);

m_radio1 = new RadioButton(); m_radio1.Text = "A"; 90

m_radio1.Location = new Point(50, 50); m_radio2 = new RadioButton(); m_radio2.Text = "B"; m_radio2.Location = new Point(50, 80); m_radio3 = new RadioButton(); m_radio3.Text = "C"; m_radio3.Location = new Point(50, 110); m_radio4 = new RadioButton(); m_radio4.Text = "D"; m_radio4.Location = new Point(50, 140); m_group1.Controls.AddRange(new Control[] { m_radio1, m_radio2, m_radio3, m_radio4, }); m_radio5 = new RadioButton(); m_radio5.Text = "X"; m_radio5.Bounds = new Rectangle(0, 100, 50, 50); m_radio6 = new RadioButton(); m_radio6.Text = "Y"; m_radio6.Bounds = new Rectangle(50, 100, 50, 50); m_radio7 = new RadioButton(); m_radio7.Text = "Z"; m_radio7.Bounds = new Rectangle(100, 100, 50, 50); m_radio8 = new RadioButton(); m_radio8.Text = "K"; m_radio8.Bounds = new Rectangle(150, 100, 50, 50); m_group2.Controls.AddRange(new Control[] { m_radio5, m_radio6, m_radio7, m_radio8, }); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(160, 95); m_buttonOK.Click += new EventHandler(m_buttonOK_Click); this.Controls.AddRange(new Control[] {m_group1, m_group2, m_buttonOK }); } void m_buttonOK_Click(object sender, EventArgs e) { foreach (Control c in this.Controls) { RadioButton rb; rb = c as RadioButton; if (rb != null) 91

{ if (rb.Checked) { MessageBox.Show(rb.Text + " Checked"); break; } }

} } //... } } Kontrollerin Demirlenmesi: Pencereleri geniletip daralttmzda kontrollerin belirli kenarlara ayn uzaklkta kalmasn isteyebiliriz. Bunu gerekletirmek iin ilk akla gelen yntem resize mesajnda location property sini kullanarak control tekrar konumlandrmaktr. Control snfnn Anchor isimli property eleman AnchorStyles isimli enum trndendir. Anahtar Notlar: Bir enum trne FlagsAttribute znitelii atanmsa bu enum trnn elemanlar bir dzeyinde or ilemine sokulabilir. Bu durumdan birden fazla zelliin dahil edilmesi gibi bir anlam kmaktad r. Anchor property sine atanan deer hangi kenarlara demirleme yap lacan belirtir. rnein: m_buttonOK.Anchor = AnchorSteyles.Right | AnchorSteyles.Bottom; Bu property nin default deeri AnchorSteyles.Top | AnchorSteyles.Left; using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } } class MyForm : Form { private Button m_buttonOK; public MyForm() { this.Text = "Anchor Sample"; this.Size = new Size(400, 400); m_buttonOK = new Button(); 92

m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point((this.ClientSize.Width - m_buttonOK.Width) / 2, (this.ClientSize.Height - m_buttonOK.Height) / 2); m_buttonOK.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right; this.Controls.Add(m_buttonOK); } //... } } Bu property control snfnn OnResize sanal fonksiyonunda ele alnmaktad r. Yani biz st pencerenin OnResize sanal fonksiyonunu override edersek Control snfnn OnResize fonksiyonunun arlmasn salamalyz. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private Button m_buttonOK; public MyForm() { this.Text = "Anchor Sample"; this.Size = new Size(200, 200); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point((this.ClientSize.Width - m_buttonOK.Width) / 2, (this.ClientSize.Height - m_buttonOK.Height) / 2); m_buttonOK.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right; this.Controls.Add(m_buttonOK); } protected override void OnResize(EventArgs e) { base.OnResize(e); } 93

//... } } Controllerin Yuvalanmas: Bir alt pencere st pencerenin herhangi bir kenarna yuvalanrsa bu kenar tamamen kaplayacak duruma gelir. rnein menler, ara ubuklar st kenara yuvalanm kontrollerdir. Benzer biimde durum pencereleri(States Bar) alt kenara yuvalanm pencerelerdir. Control snfnn Dock isimli property eleman DockStyle isimli enum trndendir. DockStyle enum trnn, None, Top, Bottom, Left, Rigth ve Fill isimli elemanlar vardr. Bir kontrol n st pencerenini alma alann kaplar hale getirilmesi en pratik olarak DosckStyle.Fill propertsiile yaplabilir. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private Button m_buttonOK; public MyForm() { this.Text = "Anchor Sample"; this.Size = new Size(200, 200); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point((this.ClientSize.Width - m_buttonOK.Width) / 2, (this.ClientSize.Height - m_buttonOK.Height) / 2); m_buttonOK.Dock = DockStyle.Fill; this.Controls.Add(m_buttonOK); } protected override void OnResize(EventArgs e) { base.OnResize(e); } //... } 94

} Dock zellii de control snfnn OnResize fonksiyonunda salanmaktadr. Dolaysyla Anchor property si iin sylenenler bu property iinde sylenebilir. Diyalog Pencereleri: Diyalog pencereleri her zaman st pencerelerin zerinde grntlenen Owned penceredir. Diyalog pencereleri Modal ve Modeless olmak zere iki blme ayrlr. Modal diyalog penceresi en ok kullanlan tipik diyalog penceresidir. Modal diyalog penceresi aldnda kullanc arka plandaki st pencere ile etkileebilemez.Baka bir deyile arka plandaki pencereye gnderilen mesajlar dorudan atlmaktad r. Halbuki Modeless pencerelerde diyalog penceresi akken kullanc arka plandaki st pencereyle de etkileebilir. MessageBox tipik bir modal pencereyken Find and Replace tipik bir Modeless penceredir. GUI tabanl uygulamalarda diyalog pencereleri ok sk kullanlmaktad r. Aslnda bir ana pencerenin diyalog penceresinden tek fark Owned pencere olmamasdr. Biz Form snfndan yarattmz ana pencereyi owned pencere durumuna getirirsek diyalog penceresi yaratm oluruz. Bu ilem .net tw olduka pratik bir biimde yaplmaktadr. Bir form penceresi Show fonksiyonuyla deil de ShowDialog fonksiyonuyla grntlenirse Modal diyalog penceresi haline gelir. Anmsanaca gibi Form snfnn Show fonksiyonunu armakla Visible property sine true atamak ayn etkiyi yaratmaktad r. O halde bir form nesnesi show fonksiyonu ile grntlenirse normal bir ana pencere, ShowDialaog fonksiyonuyla grntlenirse Modal diyalog penceresi olur. O halde Modal diyalog penceresi oluturmak iin unlar yap lmaldr. 1. Form snfndan bir snf tretilir ve new operatryle bu snf trnden bir nesne yaratlr. 2. Form nesnesi ShowDialaog fonksiyonuyla grntlenir. Bir diyalog penceresinde en azndan Okey ve Cancel biiminde iki tu bulunur. using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private Button m_buttonOK; public MyForm() 95

{ m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(100, 100); m_buttonOK.Click += new EventHandler(m_buttonOK_Click);

m_buttonOK.Parent = this; } void m_buttonOK_Click(object sender, EventArgs e) { TestForm tf = new TestForm(); tf.ShowDialog();

} //... } class TestForm : Form { //... } } using System; using System.Windows.Forms; using System.Drawing; namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private Button m_buttonOK; public MyForm() { this.Text = "Sample Dialog"; this.Size = new Size(600, 400); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(100, 100); 96

m_buttonOK.Click += new EventHandler(m_buttonOK_Click);

m_buttonOK.Parent = this; } void m_buttonOK_Click(object sender, EventArgs e) { TestForm tf = new TestForm(); tf.Show(); } //... } class TestForm : Form { private Button m_buttonOK; private Button m_buttonCancel; public TestForm() { this.Text = "Dialog Test"; this.Size = new Size(400, 200); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(180, 130); m_buttonCancel = new Button(); m_buttonCancel.Text = "&Cancel"; m_buttonCancel.Location = new Point(280, 130);

this.Controls.AddRange(new Control[] { m_buttonOK, m_buttonCancel }); } } } Diyalog penceresinin ilk grn yerini ayarlamak iin yine form snfnn yine startPosition property si kullanlr. Modal diyalog penceresini kapatmak iin en pratik yntem Form snfnn DialogResult trnden DialogResult isimli property sine deer atamaktr. Bu property ye deer atandnda dialog penceresi otomatik kapatlr. ShowDialog fonksiyonu atanan bu deerle geri dner. rnein Dialog penceresindeki Cancel tuuna click yapld nda dialog penceresini yle kapatabiliriz. this.DialogResult=DialogResult.Cancel; using System; using System.Windows.Forms; using System.Drawing; 97

namespace CSD { class App { public static void Main() { Application.Run(new MyForm()); } }

class MyForm : Form { private Button m_buttonOK; public MyForm() { this.Text = "Sample Dialog"; this.Size = new Size(600, 400); m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(100, 100); m_buttonOK.Click += new EventHandler(m_buttonOK_Click);

m_buttonOK.Parent = this; } void m_buttonOK_Click(object sender, EventArgs e) { TestForm tf = new TestForm(); DialogResult dr = tf.ShowDialog(); if (dr == DialogResult.Cancel) MessageBox.Show("Cancel ile kld"); } //... } class TestForm : Form { private Button m_buttonOK; private Button m_buttonCancel; public TestForm() { this.Text = "Dialog Test"; this.Size = new Size(400, 200); this.FormBorderStyle = FormBorderStyle.FixedDialog; 98

this.MaximizeBox = false; this.StartPosition = FormStartPosition.CenterParent; m_buttonOK = new Button(); m_buttonOK.Text = "&Ok"; m_buttonOK.Location = new Point(180, 130); m_buttonCancel = new Button(); m_buttonCancel.Text = "&Cancel"; m_buttonCancel.Location = new Point(280, 130); m_buttonCancel.Click += new EventHandler(m_buttonCancel_Click);

this.Controls.AddRange(new Control[] { m_buttonOK, m_buttonCancel }); } void m_buttonCancel_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } } } ShowDialog fonksiyonu arldnda artk ak ShowDialaog fonksiyonunun iindedir. Ancak diyalog penceresi kapand nda fonksiyon geri dner. DialogResult property sine deer atandnda bir flag(bayrak) set edilir. Diyalog penceresinin kapatlmas ak mesaj dngsne geri dnd nde yaplr. Aslnda dialogResult property sine deer atandktan sonra hemen Close fonksiyonuyla da pencere kapatlabilir. rnein: this.DialogResult = DialogResult.OK; this.Close(); Fakat bu gereksizdir. Modal Diyalog Pencerelerinde Oluturulan Bilgilerin Elde Edilmesi: Bir diayalog penceresi kapatld nda programc kullancnn diyalog penceresinde oluturuduu bilgileri elde etmek ister. Bir pencerenin kapatlm olmas o pencere nesnesinin yok edilmi olduu anlamna gelmez. Pencere nesnesinin yok edilmesi p toplayc tarafndan yaplmaktad r. rnein bir diyalog penceresi zerine bir textBox yerletirmi olalm. class MyDialog:Form { private TextBox m_textBoxName; //... } imdi biz bu diyalog penceresini aadaki gibi am olalm. MyDialog md = new MyDialog(); md.ShowDialog(); Diyalog penceresi kapatldnda diyalog penceresi fiziksel olarak yok olur. Dolaysyla pencere zerindeki kontrollerde yok edilmitir. Ancak rnekteki md nesnesi ve onun iindeki 99

m_textBoxName nesnesi yaamaya devam etmektedir. Yani rnein yapabilsek md.m_textBoxName .Text ifadesiyle yok edilmi olan TextBox kontrolnn iineki yazy elde edebiliriz. Fakat tipik olarak bu kontroller MyDialog snfnn private blmnde olduu iin biz bu eriimi yapamayacaz. te nerilen tipik yntem udur: 1. Diyalog penceresinden elde edilecek her bilgi iin get ve set blmlerine sahip public property yazlr. class MyDialog:Form { private TextBox m_textBoxName; //... public string Name { get{return m_textBoxName;} set{m_textBoxName = value;} } } 2. Diyalog penceresi ShowDialaog ile almadan nce bu kontrollere ilk deerleri atanabilir. Pencere kapatldktan sonra kontrollerde oluan deerler alnabilir. rnein: MyDialog md = new MyDialog(); md.Name = "Kaan Aslan"; //... md.ShowDialog(); MessageBox(md.Name); Visual Shirbaznn Kullanlmas: Yeni bir proje yaratlrken template olarak baz seenekler bizim iin hazr bir balang kodu hazrlamaktadr. Ayn zamanda bu sihirbaz seenekleri form editrn kullanlmasna da olanak salamaktad r. En temel sihirbaz ablonu File/New/project mensnden template olarak Windows Form Appilication seilerek elde edilir. Bu ablon seenei ile proje yaratldnda sihirbaz u dosyalar olu turmaktadr. Program.cs: Bu dosya da program isimli br snf bildirilmi ve iine main fonksiyonu yerletirilmitir. Main fonksiyonu ierisinde klasik olarak Application.Run altrlm tr. Form1.cs: Bu dosyada form snfndan tretilmi olan Form1 isimli snf tanmlanm tr. Form1 snf partial olarak bildirilmitir. Bu snfn dier paras Form1.Designer.cs ierisindendir. Anahtar Notlar: Framework 2005 ile birlikte snflar iin partial bildirimi de eklenmitir. Ayn isim alannda ayn snf birden fazla partial belirleyicisi ile bildirilirse bu snf derleyici tarafndan birletirilmektedir. Partial anahtar szc snfn her paras iin bulundurulmak zorundadr. Sihirbazn(Wizard) yazd Form1 snfn balang fonksiyonunda InitializeComponent isiml ibir fonksiyon arlmtr. InitializeComponent fonksiyonu Form1.Designer.cs iinde tanmlanmtr. Form editr kullanlarak fare hareketleriyle yaplan ilemler kod a dntrlerek InitializeComponent iine yazlmaktad r. Programc manuel ekleme yapacaksa eklemeleri InitializeComponent iine deil balang fonksiyonunun iinde yapmald r. Form1.Designer.cs: Bu dosya da Form1 snfnn dier paras bulundurulmaktadr. InitializeComponent fonksiyonu buradadr ve sihirbaz dorudan bu dosya zerine kod eklemektedir. Ayrca bu dosyada Form1 Snfna bir Dispose kalb da eklenmitir.

100

AssemlyInfo.cs: Bu dosyada Assemly dzeyinde z nitelik bilgileri bulunmaktadr. Form1.resx: Bu dosya Form1 isimli Form a ynelik xml tarz kaynak bildirimlerini bulundurmaktad r. Kaynak konusu ileride ele alnacakt r. Resources.resx: Her Form iin ayr bir kaynak dosyas bulundurulabilir. Fakata Resources.resx dosyas global kaynak dosyasdr. Bu dosyada xml tabanl kaynaklar ierir. Resources.Designer.cs: Bu dosya global kaynak dosyasndaki trl(typed) kaynaklar bildirmektedir. Sihirbazn oluturdu u projede temel baz dll lere referans edilmitir. Aslnda bu referans edilen dll lerin bir ksmna gerek yoktur. Sihirbazn rettii kod zerinde hemen programc tarafndan hemen baz kk deiiklikleri yapmald r. ncelikle anapencereyi temsil eden snfn ismi deitirilmelidir. Solution Explorer de Form1.cs dosyas ismi deitirilmek istendiinde sihirbaz kodlarda bu snfn ismini de deitirmektedir. Ayrca programc isim alan isimini de deitirmek isteyebilir. Visual studio default olarak hereyi proje ismiyle belirtilen isim alanna yerletirmektedir. Maalesef isim alan deitirmenin henz pratik bir yolu yoktur. Fakat tipik olarak Find and Replace da Entire Solution seenei seilerek tm isimler deitirilir. Proje seeneklerinden default namespace ayrca deitirilmelidir. Buradaki deiiklik bildirilmi olana isimalanlarnn ismini deitirmez. Fakat daha sonra olu turulacak isim alanlarn deitirebilir. Form Editrn Kullanlmas: Sihirbazla almann en nemli faydas Form Editrdr. Form Editr yalnzca GUI ilemleri iin deil dier ilemle iin de kullanlabilen ilevsel bir aratr. Programc Form Editrde herhangi bir genin zerine gelip balan mensnden properties elemann seerse o geninin grsel olarak deitirlebilecek elemanlar grntlenebilir. Properties iinde snfn property elemanlar ve event elemanlar grntlenmekte ve bunlar zerinde grsel deiiklikler yap labilmektedir. Control snflarnn ve dier snflarn btn public propertyleri mende yer almaktadr. Ve bunlar hemen mende deitirilebilir. Form Editr yaplan deiiklii kod a yanstr. Properties mensnde event ksm na geildiinde ilgili snfn tm event elemanlar listelenmektedir. Listedeki bir event elemanna double click yaplrsa Form Editr ilgili event elemanna += ile event elemanna fonksiyon ekleyen kodu InitializeComponent iine ekler ve ilgili fonksiyonu da ii bo olarak tanmlar. Ayrca ayn delege trnden olan event elemanlarnda yazlm olan tm fonksiiyonlarda listelenmektedir. Bylece farkl event elemanlar iin ayn fonksiyonlarn verilmesi mmkn olabilir. Form Editrn en nemli zellii "ToolBox" dan seerek kontrol yerletirilebilmesidir. Form Editr bunlar iin gerekli kodlar oluturmaktadr. Controller kolaylkla hizalanmakta propertyleri ve event elemanlar kolaylkla set edilebilmektedir. Form editrde baz elemanlarn zerine double click yap ld nda en ok kullanlan event set edilir. rnein bir dmenin zerine double click yaptm zda d menin en ok kullanlan event i click olduu iin click ecent i set edilir. Baz controller forma yerletirildiinde control n sa st k esinde kk bir ok kar bu ok a tklandnda en ok kullanlan gelerle karlatrlr.

101

Form Editre yerletirilen her bir kontrolere Form Editr otomotik olarak Control ismi ve bir saydan olu an bir isim vermektedir. Programcnn da bunu dzeltmesi yerinde olacaktr. simlerin otomotik deitirilmesi iin control n main name propertysinin deitirilmesi yeterlidir. Anahtar Notlar: Visual Studio IDE sinde private bir veri elemann zerine gelinip farenin sa tuuyla balan mensnden refactor Encapsulet Field seilirse otomatik olarak o veri eleman iin temel property yazlr. File Seme Diyalog Penceresi: Windows da Dosya ama, saklama, renk seme, bul ve deitir, printer gibi diyalog pencereleri standart bir biimde bulundurulmaktadr. . Nette bu diyalog pencereleri CommonDialog snfndan tretilmi snflar la temsil edilmektedir. Bir dosyay amak zere dosyay semek iin OpenFileDialog saklamak iin SaveFileDialog pencereleri kullanlr. Bu pencereler ayn isimli snflarla temsil edilmitir. Common Dialog

File Dialog

Open File Dialog

Save File Dialog

OpenFileDialog ve SaveFileDialog pencerelerinden istediimiz yegane ey kullancnn setii dosyann isimin bize verilmesidir. Bu diyalog pencereleri isminin aksine seilen dosyay amazlar yalnzca bize kullancnn setii dosya ismini veriler. Dosyann almas bize kalmt r. OpenFileDialog snfnn CommonFileDialog snfndan gelen ShowDialaog fonksiyonu dosya seme diyalog penceresini aar. O halde Dosya seme diyalog penceresi tipik olarak yle alr. OpenFileDiyalog ofs = new OpenFileDiyalod(); if(ofd.ShowDialog() == DialogResult.OK) { //... } OpenFileDialog snfnn CommonFileDialog snfndan gelen String trnden FileName isimli property eleman seilen dosya ismini yol ifadesiyle vermektedir. Bu property Read/Write property dir. Bu property ye deer atanrsaa bu yaz Dialog penceresinin FileName ksmnda kar. OpenFileDialog penceresi default olarak seilen dosyann da varln aratrmaktadr. Eer dosya yoksa kmaya izin vermemektedir. OpenFileDialog snfnn FileDialog snfndan gelen string trnden Filter isimli property eleman filtreleme bilgilerini oluturur. Filtreleme yazs type karakterleriyle ayrlm iftlerden oluur. iftin solundaki yaz 102

grntlenecek yazd r. Bunun gerek filtre ile bir ilgisi yoktur. Sandaki yaz filtreleme bilgisini ierir. rnein: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace OpenFileDialogSample { public partial class OpenFileDialogForm : Form { public OpenFileDialogForm() { InitializeComponent(); } private void m_buttonOk_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "C Files (*.c)|*.c"; if (ofd.ShowDialog() == DialogResult.OK) { MessageBox.Show(ofd.FileName); } } } } Eer gerek filtreleme birden fazla seenekten oluuyorsa ikinci ksm ; lerle oaltlabilir. rnein: OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Image Files |*.BMP;*.JPEG"; Snfn FileDialog snfndan gelen int trden FilterIndex isimli property eleman Dialog penceresi ald nda hangi elemann aktif olacan belirtir. lk eleman 1 numaral indextedir. Property nin default deeri birdir yani ilk filtre aktiftir. ofd.Filter = "Image Files |*.BMP;*.JPEG|All Files|*.*"; ofd.FilterIndex = 2; Snfn String trden Read/Write InitialDirectory isimli property eleman Dialog Penceresi ald nda grntlenecek dizini belirtir. Bazen programclar son alan dizinin grntlenmesini isteyebilir. Bu durumda kta bu dizinin snfn bir veri elemannda saklanp diyalog penceresi almadan nce bu property ye atanmas gerekir. Bu ilem yle yap labilir. Anahtar Notlar: System.IO isim aslanndaki Path isimli snfn eitli statik fonksiyonlar bir yol ifadesini ayrt rmakta kullanlabilir. GetFileName yol ifadesinin sonundaki dosyann isimini 103

uzantsyla verir. GetExtention yalnzca dosyann uzantsn verir. GetDirectoryName dosyann iinde bulunduu dizinin yol ifadesini verir. Snfn baka pek ok faydal fonksiyonu da vardr. OpenFileDialog snfnn bool trden MultiSelect isimli property eleman oklu seime izin verir. Bu durumda seilen tm dosyalar FileNames property elemanndan elde edilmektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace OpenFileDialogSample { public partial class OpenFileDialogForm : Form { public OpenFileDialogForm() { InitializeComponent(); } private void m_buttonOk_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Image Files |*.BMP;*.JPEG|All Files|*.*"; ofd.FilterIndex = 2; ofd.Multiselect = true; if (ofd.ShowDialog() == DialogResult.OK) { string text = null; foreach (string file in ofd.FileNames) text += file + "\n"; MessageBox.Show(text); } } } } OpenFileDialog snfnn OpenFile isimli fonksiyonu seilmi dosyay Read/Write olarak aar. FileDialog snfnn bool trden CheckFileExists isimli property si seilen dosyann varln test etmekte kullanlr. Bu property nin default deeri true d r. OpenFileDialog snfn dier elemanlar MSDN dkumanlar ndan incelenmelidir. private void m_buttonOk_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Image Files |*.BMP;*.JPEG|All Files|*.*"; ofd.FilterIndex = 2; 104

if (ofd.ShowDialog() == DialogResult.OK) { textBox1.Text = File.ReadAllText(ofd.FileName); } } SaveFileDialog snf kullanm bakmndan OpenFileDialog snfna ok benzemektedir. Zaten pek ok eleman ortaktr. Renk Seme Diyalog Penceresinin Kullanm: Renk seme diyalog penceresi ColorDialog snf ile temsil edilmitir. Bu snfta CommonDialog snfndan tretilmitir. Programc nce ColorDialog snf trnden bir nesne yaratr ve snfn CommonDialog snfndan gelen ShowDialaog fonksiyonunu arr.Snfn Color trnden Color isimli property eleman seilen rengi vermektedir. private void m_buttonOk_Click(object sender, EventArgs e) { ColorDialog cd = new ColorDialog(); if (cd.ShowDialog() == DialogResult.OK) this.BackColor = cd.Color; } ColorDialog snfnn bool trden FullOpen isimli property eleman diyalog penceresinin btnsel almasn salar. Snfn int [ ] trnden CustomColors isimli property eleman kullancnn ayarlad renkleri RGB biiminde kodlanm bir dizi olarak elde eder. Bu deerler saklanp yeniden yklenerek kullancnn setii renklerin kalcl salanr. Diyalog penceresinin default Custom renklerle balatlmas iin int bir diziye renk deerlerinin int bir say olarak atanmas gerekir. Renk deerlerini int trle ifade etmenin ok pratik bir yolu yoktur. Programc istedii renklerin RGB bileenleriyle int trne dntrebilir. Men lemleri: Men sistemleri Framework 2.0 ile birlikte tamamen deitirilmitir. Her nekadar Framwork2.0 ve sonrasnda hala Framework 1.1 in menleri desteklense de obsulate yaplm tr. Zaten sihirbaz destei kaldrlmtr. Framework 2.0 n menleri birer kontrol biimindedir. Dolaysyla Men yukarya yuvaland nda alma alannn sol st kesi mennn altnda kalmaktad r. Framework 2.0 da menler, ara ubuklar ve durum ubuklar ortak zellie sahip birer erit(strip) kontrolleridir. Bunlarn hepsinin ortak zellikleri vardr ve ortak zellikler ToolStrip isimli snfta toplanmtr. Ara ubuklar ToolStrip snfnn kendisiyle oluturulur. Menler ToolStrip snfndan tretilmi olan MenuStrip snfyla oluturulmaktadr ve Durum ubuklar da ToolStrip snfndan tretilmi StatusStrip snfyla olu turulmaktadr.

105

Control

ToolStrip
(Ara ubuklar)

MenuStrip
(Menu)

StatusStrip
(Durumubuklar )

Bir men sistemi bir men ubuundan ve POPup menlerden olu maktad r. Popup pencereler men elemalanrna sahiptir. Men elemanlarda ayr popup pencereler biiminde olabilir. Bu durumda bir men sistemi iin mantksal olarak unlar yap lmaldr. 1.Men ubuu, popup pencerler ve men elemanlar birer snf nesnesi biiminde yaratlr. 2. Men elemanlar popup pencerelere popup pencereleri de men ubuuna balanr. Men ubu u MenuStrip snf trnden bir nesne yarat lp formun control kmesine eklendiinde otomatik olarak yaratlr. MenuStrip snfn ToolStrip snfndan gelen Item isimli property eleman ToolStripItemCollection isimli Collection snf trndendir. Bu collection snf ToolStripItem snf trnden nesneleri tutmaktadr. Ara ubuklar, menler, durum ubuklar zerindeki elemanlar ToolStripItem snfndan tretilmi snflarla temsil edilmektedir. Bir men eleman ya da popup men dolayl olarak ToolStripItem snfndan tretilmitir.

ToolStripItem

ToolStripDropDownIte m

ToolStripMenuItem

ToolStripMenuItem snf hem popup pencereleri hem de sradan men elemanlarn temsil eder. Bir ToolStripMenuItem nesnesinin sradan bir men elemanm yoksa bir popup m oldu u snfn DropDownItemsCollection property siyle belirlenmektedir. DropDownItems propertysi ToolStripItem isimli Collection snf trndendir. Anamsanaca gibi bu snf ToolStripItem 106

nesneleri tutmaktadr. .net Framwork bu collection elemann bo olup olmad na bakar eer bu elemana hibir ey eklenmediyse bu sradan bir men elemandr. Eklenmise bu bir popup elemandr ve ekleneler de bunun iindeki elemalar belirtir. MenuStrip imdi aadaki gibi bir men sisteminin nasl oluturulacana bakalm. File Open Save Exit

ToolStripMenuItem(herbiri)

ToolStripMenuItem

Bu sistemde toplam 5 farkl nesne yaratlmaldr. 1 men ubuu iin MenuStrip snf trnden 2 File popup iin ToolStripMenuItem snf trnden dier tanesi open, save, exit men elemalar iin ToolStripMenuItem snf trndendir. Open, Save ve Exit elemanlar iin yarattmz ToolStripMenuItem nesnelerini File popup n DropDownItem collectionna File popup da MenuStrip snfnn Items collectionna ekleriz. MenuStrip nesnesinide formun control listesine ekleriz. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace SampleMenu { public partial class Form1 : Form { private MenuStrip m_mainMenu; private ToolStripMenuItem m_filePopup; private ToolStripMenuItem m_openItem, m_saveItem, m_exitItem; public Form1() { InitializeComponent(); m_mainMenu = new MenuStrip(); 107

m_filePopup = new ToolStripMenuItem(); m_filePopup.Text = "&File"; m_openItem = new ToolStripMenuItem(); m_openItem.Text = "&Open"; m_saveItem = new ToolStripMenuItem(); m_saveItem.Text = "&Save"; m_exitItem = new ToolStripMenuItem(); m_exitItem.Text = "&Exit"; m_filePopup.DropDownItems.AddRange(new ToolStripItem[] { m_openItem, m_saveItem, m_exitItem }); m_mainMenu.Items.Add(m_filePopup);

this.Controls.Add(m_mainMenu); } } } ToolStripMenuItem snfnn check isimli bool trden property eleman menu elemann Checked ya da Unchecked yapmakta kullanlr. ToolStripMenuItem snfnn Enabled isimli bool trden property eleman ilgili men elemann aktif ya da pasif duruma getirir. ToolStripMenuItem snfnn Font isimli property eleman eleman yazsnn fontunu ayarlamakta kullanlr. Yine snfn klasik BackColor ve ForeColor propertyleri men elemann zemin ve ekil renklerini oluturur. ToolStripMenuItem snfnn Size isimli property eleman ile men elemannn genilik ve ykseklii ayarlanabilir. rnein biz men elemann dierlerinden daha yksek yapabiliriz. Bu durumda eleman yazs snfn TestAlingn propertysi ile ayarlanabilir. Men eleman iin ksayol tuu ShortcutKeys propertysi ile atanr. Bu property Keys isimli enum trndendir. Bir men eleman seildiinde snfn Click event eleman tetiklenir. Ksayol tuunun grntlenip grntlenmeyecei snfn bool trden ShowShortcutKeys propertysi ile belirlenmektedir. Eer istenirse ksayol iin istenilen bir yazda ShowShortcutDsiplayString propertysi ile grntlenebilir. ToolStripMenuItem snfnn ToolStripItem snfndan gelen ToolTipText propertysi ipucu yazsn kartmakta kullanlr. Fakat istenirse ipucu yazs ShowItemToolTips propertysi ile gsterilebilir ya da gsterilmeyebilir. Ayrca ToolStripMenuItem snfnn ToolStripItem snfndan gelen Bool trden AutoToolTip properyty si default olarak men yazsnn ipucu yazs olarak grntlenmesini salar. Ayrca bir popup iin men olaylarnn takip etmeye ynelik eitli event elemanlarda vardr. 108

rnein popup ald nda ve kapandnda eitli eventler tetiklenmektedir. Ya da rnein men elemanlar zerinde gezinirken yine eventler tetklenmektedir. Tm bu eventler MSDN dkumanlarndan incelenmelidir. Pek ok programda birden fazla men bulunmaktadr ve menler arasnda gei yaplmaktadr. Bunun iin eitli yntemler kullanlabilir. rnein btn men ubuklar Forma eklenebilir. Fakat yalnzca birinin Visible property si true yap lr. Duruma gre dierinin Visible propertysi tru yaplarak gei salanabilir. Ya da bu ilem ilgili men ubuu control nn formun control listesine eklenip karlarakta yap labilir. Bazen bir men elemann setiimizde baka popuplar ya da baka men elemanlarda eklenebilmektedir. Bu ilem menye dinamik olarak Add ve Remove fonksiyonlaryla ekleme karma yaplarak salanabilir. Ya da benzer teknik kullanlabilir. Programc tm popuplar ekler gerektiinde Visible propertysini true ya da False eker. Baz programlarda az kullanlan men elemanlarn popup ald nda grntlenmemektedir. Bu imdilik otomatik yaplan bir zellik deildir. Balam Menleri: alma alan zeride farenin sa tuuna baslarak grntlenen menye balam men(Context Menu) denilir. Balam mens de Framework2.0 ile birlikte deitirilmitir. Bunun iin eskiden Form snfnn ContextMenu propertysi kullanlyordu. Artk ContextMenuStrip propertysi kullanlmaktadr. Form snfnn ContextMenuStrip propertysi ContextMenuStrip isimli bir snf trndendir. Bu snfn tretme emas yledir. ToolStrip

ToolStripDropDown

ToolStripDropDownMenu

ContextMenuStrip Programc balam mensn manuel olarak yle olu turur. 1. ContextMenuStrip trnden bir nesne yaratlr. 2. ContextMenuStrip snfnn ToolStripItemCollection isimli Items propertysine ekleme yapar. ContextMenuStrip snfnn kullanm MenuStrip snfnn kullanmna ok benzemektedir. Pek ok programda birden fazla balam mens vardr ve fare belirli blgelerdeyken farkl balam menleri grntlenmektedir. Bu ilem bir ka biimde yap labilir. Birincisi Form snfnn ContextMenuStrip propertysini kullanmak yerine tamamen MouseDown Eventini kullanarak koordinatlara bakmak ve duruma gre ContextMenuStrip snfnn show fonksiyonu ile am yaplmal. Dier bir yntem farenin durumuna gre snfn ContextMenuStrip propertysini ayarlamaktr. Yani programc fare hareketlerini izler bir property e uygun eleman atar. Bu atama ilemi MouseMove mesajnda yaplabilecei gibi MouseDown mesajnda da yaplabilir. nk farenin sa tu una basldndan nce MouseDown eventi tetiklenmekte sonra balam mens grntlenmektedir.

109

using System.Text; using System.Windows.Forms; namespace SampleMenu { public partial class Form1 : Form { private MenuStrip m_mainMenu; private ToolStripMenuItem m_filePopup; private ToolStripMenuItem m_openItem, m_saveItem, m_exitItem; private ContextMenuStrip m_contextMenu; private ToolStripMenuItem m_appleItem, m_fruitItem; public Form1() { InitializeComponent(); m_mainMenu = new MenuStrip(); m_filePopup = new ToolStripMenuItem(); m_filePopup.Text = "&File"; m_openItem = new ToolStripMenuItem(); m_openItem.Text = "&Open"; m_openItem.ShortcutKeyDisplayString = "Kontrol O"; m_openItem.ShortcutKeys = Keys.Control | Keys.O; m_openItem.ToolTipText = "This is a sample"; m_openItem.Click += new EventHandler(m_openItem_Click); m_saveItem = new ToolStripMenuItem(); m_saveItem.Text = "&Save"; m_exitItem = new ToolStripMenuItem(); m_exitItem.Text = "&Exit"; m_filePopup.DropDownItems.AddRange(new ToolStripItem[] { m_openItem, m_saveItem, m_exitItem }); m_mainMenu.Items.Add(m_filePopup); m_contextMenu = new ContextMenuStrip(); m_appleItem = new ToolStripMenuItem(); m_appleItem.Text = "&Apple"; m_appleItem.Click += new EventHandler(m_appleItem_Click); m_fruitItem = new ToolStripMenuItem(); m_fruitItem.Text = "Fruit"; m_contextMenu.Items.AddRange(new ToolStripItem[] { m_appleItem, m_fruitItem }); //this.ContextMenuStrip = m_contextMenu; 110

this.Controls.Add(m_mainMenu); } void m_appleItem_Click(object sender, EventArgs e) { MessageBox.Show("Apple selected"); } void m_openItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { MessageBox.Show(ofd.FileName); } } private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { Rectangle rect = new Rectangle(100, 100, 100, 100); if (rect.Contains(e.Location)) this.ContextMenuStrip = m_contextMenu; } } } } Aslnda Form snfnn ContextMenuStrip propertysi Control snfndan gelmektedir. Yani her kontrol n ContextMenuStrip eleman zaten vardr. Bylece biz rnein bir dmenin zerinde sa tua bastmzda balam mensnn grntlenmesini salayabiliriz. Menlerin Form Editr Yoluyla Kullanlmas: Menller form editrde tamamen grsel biimde oluturulabilir. Form editr men ubuu iin, her popup iin ve her men eleman iin ayr birer nesne olu turmaktadr. Nesnelerin Seri Hale Getirilmesi: Seri hale getirme(Serialization) snf nesnelerinin bir kaynaa (muhtemelen disk) yazlmas ve oradan geri alnmasanlamna gelmektedir. Bir snf nesnesinin saklanmas aslnda onun datalarnn saklanmas anlamna gelir. Geri alma srasnda da o veri elemanlar yeniden doldurulur. Seri hale getirme otomatik ve manuel biimde yaplabilir. Manuel(custom) seri hale getirme kursumuzun kapsam d ndad r. Seri hale getirme ilemi u ad mlardan geiler yaplmaktad r. 1. Seri hale getirilecek snf yada yap serializable attribute znitelik snf kullanlarak zniteliklendirilmelidir. Bunun iin ilgili snf ya da yapnn nne [Serializable] 111

belirlemesinin yaplmas gerekir. [Serializable] class Sample { //... } 2. Seri hale getirilecek hedef yaratlr. Hedefin Stream snfndan tretilmi bir snf olmas gerekir. Tipik hedef dosyad r. Bunun iin FileStream snf trnden bir nesne yarat lr. 3. Seri hale getirme ilemi srasnda yazmann format deiebilir. Yazma dz binary yap labilecei gibi html/xml biiminde yaplabilir. te yazm formatna uygun bir nesnesinin yap lmas gerekir. Bu tr snflar genellikle XXFormatter biiminde isimlendirilmitir. rnein binary yazm iin BinaryFormatter snf kullanlabilir. rnein: BinaryFormatter bf= new BinaryFormatter(); 4. Tm XXXFormatter snflar IFormatter arayzn desteklemektedir. Bu arayzn de Serialize ve Deserialize fonksiyonlar vardr. Seri hale getirme ilemi ilgili formatter snfnn Serialize fonksiyonu arlarak yaplr. void Serialize( Stream serializationStream, Object graph ) Fonksiyonun birinci parametresi hedefi ikinci parametresi seri hale getirilecek nesneyi belirtmektedir. Geri alma ilemi Deseralize fonksiyonuyla yaplr. Object Deserialize( Stream serializationStream, ) Fonksiyon parametre olarak kayna almaktadr.Geri dn deeri yaratlm olan nesnedir. Fonksiyon nesneyi yarat iine bilgileri doldurur ve bize nesnenin referansn verir. Seri hale getirme ilemi basit bir ilem deildir. Seri hale getireceimiz snf ya da yap baka snflar trnden referans veri elemanlarna sahipse yalnzca ana nesnesinin hedefe yazlmas yetmez. Ayn zamanda referans veri elemalarnn gsterdikleri nesnelerin de hedefe yazlmas gerekir. Yani bir aa szkonusudur. Tm bir aacn belli bir srada yazlmas ve okunmas gerekir. Ayn durum taban snf iin de geerlidir. Biz bir tremi snf nesnesini hedefe yazacaksak onun tm taban snflarn da yazmak zorundayz. Bir snf ya da yapya biz Serializable zniteliini atamsak bu snfn tm taban snflarnn ve tm veri elemanlarnn da bu znitelie sahip olmas gerekir. Zaten .net in int32, int64, String gibi tm temel yap ve snflar bu znitelie sahiptir. .net iindeki baz collection snflarda Serializable durumdadr. rnein ArrayList snf byledir. Biz tewk hamlede bir ArrayList nesnesini diske yazp yine tek hamlede geri alabiliriz. Arka planda yap lan ilemler basit deildir. Mekanzima ArrayList nesnesinin elemanlarn onlarn tuttuu nesneleri yani btn bir aac zyinelemeli olarak hedefe yazabilmektedir. Geri alm srasnda tm bu nesneler mekanizma tarandan yeniden yaratlr. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace TestSerialization 112

{ class Program { static void OldMain(string[] args) { ArrayList al = new ArrayList(); al.Add(new Person("Kaan Aslan", 123)); al.Add(new Person("Ali Sere", 456)); al.Add(new Person("Necati Ergin", 43)); al.Add(new Person("Guray Sonmez", 876)); al.Add(new Person("Ertan Geyik", 1239)); al.Add(new Person("Gurbuz Aslan", 568));

FileStream fs = null; try { fs = new FileStream("test.dat", FileMode.CreateNew, FileAccess.Write); BinaryFormatter bf = new BinaryFormatter(); bf.Serialize(fs, al); } catch (Exception e) { Console.WriteLine(e.Message); } finally { if (fs != null) fs.Close(); } Console.WriteLine("Ok"); } public static void Main() { FileStream fs = null; ArrayList al; try { fs = new FileStream("test.dat", FileMode.Open, FileAccess.Read); BinaryFormatter bf = new BinaryFormatter(); al = (ArrayList) bf.Deserialize(fs); foreach (Person per in al) per.Disp();

113

} catch (Exception e) { Console.WriteLine(e.Message); } finally { if (fs != null) fs.Close(); } } } [Serializable] class Person { private string m_name; private int m_no; public Person() {} public Person(string name, int no) { m_name = name; m_no = no; } public void Disp() { Console.WriteLine("{0} {1}", m_name, m_no); } } } Resimlerle lemYapmak: .Netde her trl resimsel grnt image snf ile temsil edilmektedir. mage snfndan eitli snflar tretilmitir. Image snf abstract snftr.

Image

Bitmap

MetaFile

114

Bitmap snf resimsel grnty oluturdu umuz somut bir snftr. Bitmap snf (ismi bmp dosyalarn artrsa da) aslnda JPEG,GIF,PNG,TIFF,BMP,EXIF gibi pek ok dosya formatn desteklemektedir. Bir resim snf Bitmap balang fonksiyonu ile yaratlabilir. public Bitmap(string filename); fonksiyon parametre olarak resim dosyasnn yol ifadesini almaktadr. PictureBox isimli kontrol olduka basittir. Tek yapt ey bir resmi alp onu gstermektir. PicturteBox snfnn Image trden pro perty eleman grntlenecek resmi alr.
using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms;

namespace ImageSample { public partial class ImageSampleForm : Form { private Bitmap m_bitmap; public ImageSampleForm() { InitializeComponent(); } private void openToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Jpeg Files|*.jpg;*.jpeg|Bitmap Files|*.bmp|All Files|*.*"; if (ofd.ShowDialog() == DialogResult.OK) { m_bitmap = new Bitmap(ofd.FileName); m_pictureBox.Image = m_bitmap; }

} } }

PictureBox kontrol Debug olarak resmi gerek boyutu ile gsterir. resim buyuse biz onun yalnzsca sol ust kosesini goruruz. gsterim biimi snfn pictureBox.SizeMode isimli enum trnden sizeMode isimli property eleman ile ayarlanabilir. Bu enum trnn elemanlar unlardr: Normal: Bu default durumdur. Resim orijinal byklkte ve yalnzca sol st kesi grntlenir. StrechImage: Bu seenek resmi kontrol boyutuna getirir. AutoSize: Burada pictureBox kontrol resim boyutuna ekilir. CenterImage: burada resim Kontrolden kkse resim kontroln ortasnda grntlenir. fakat resim kontrolden buyukse resmin ortas goruntulenir. burada resim kontrol boyutuna getirilir fakat ayn 115

zamanda yatay-dey orant dikkate alnr. Duruma gre kontroln kenarlarnda bo luk b raklr.
namespace ImageSample { public partial class ImageSampleForm : Form { private Bitmap m_bitmap; public ImageSampleForm() { InitializeComponent(); } private void openToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Jpeg Files|*.jpg;*.jpeg|Bitmap Files|*.bmp|All Files|*.*"; ofd.InitialDirectory = @"e:\dotnetappbasic\ImageSample\ImageSample"; if (ofd.ShowDialog() == DialogResult.OK) { m_bitmap = new Bitmap(ofd.FileName); m_pictureBox.SizeMode = PictureBoxSizeMode.Zoom; m_pictureBox.Image = m_bitmap; }

} } }

Bitmap snfnn Image snfndan gelen size,width ve height propertyleri resmin boyutunu belirler.
namespace ImageSample { public partial class ImageSampleForm : Form { private Bitmap m_bitmap; public ImageSampleForm() { InitializeComponent(); } private void openToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Jpeg Files|*.jpg;*.jpeg|Bitmap Files|*.bmp|All Files|*.*"; ofd.InitialDirectory = @"e:\dotnetappbasic\ImageSample\ImageSample"; if (ofd.ShowDialog() == DialogResult.OK) { m_bitmap = new Bitmap(ofd.FileName); m_pictureBox.SizeMode = PictureBoxSizeMode.Zoom; m_pictureBox.Image = m_bitmap; this.Text = ofd.FileName + " " + m_bitmap.Size.ToString();//boyutu yazar } } } }

116

Bitmap snfnn RawFormat isimli property eleman nesneye tutulan resmin formatn verir.Bu property Image fo rmat isimli snf trndendir. Bu snfn eitli static propertyleri eitli formatlar belirtir. Bitmap snfnn pixcel format propertysi renk pixel yapsn verir. Bitmap snfnn getpixel ve setpixel fonksiyonlar resimndeki bir pixelin rengini alp set etmekte kullanlr.
OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Jpeg Files|*.jpg;*.jpeg|Bitmap Files|*.bmp|All Files|*.*"; ofd.InitialDirectory = @"e:\dotnetappbasic\ImageSample\ImageSample"; if (ofd.ShowDialog() == DialogResult.OK) { m_bitmap = new Bitmap(ofd.FileName); for (int i = 0; i < 100; ++i) for (int k = 0; k < 100; ++k) m_bitmap.SetPixel(100 + i, 100 + k, Color.Red); m_bitmap.RotateFlip// m_pictureBox.SizeMode = PictureBoxSizeMode.Zoom; m_pictureBox.Image = m_bitmap; this.Text = ofd.FileName + " " + m_bitmap.Size.ToString();

Bitmap snfnn RotateFlip isimli fonksiyonu resmi tersine evirir.


m_bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);

Bitmap snfnn Save fonksiyonu ilgili Bitmap nesnesini belirli boyutta diske saklamak iin kullanlr.
using using using using using using using using using System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Windows.Forms; System.Drawing.Imaging;

namespace ImageSample { public partial class ImageSampleForm : Form { private Bitmap m_bitmap; public ImageSampleForm() { InitializeComponent(); } private void openToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Jpeg Files|*.jpg;*.jpeg|Bitmap Files|*.bmp|All Files|*.*"; ofd.InitialDirectory = @"e:\dotnetappbasic\ImageSample\ImageSample"; if (ofd.ShowDialog() == DialogResult.OK) {

117

m_bitmap = new Bitmap(ofd.FileName); for (int i = 0; i < 100; ++i) for (int k = 0; k < 100; ++k) m_bitmap.SetPixel(100 + i, 100 + k, Color.Red); m_bitmap.RotateFlip(RotateFlipType.Rotate180FlipX); m_pictureBox.SizeMode = PictureBoxSizeMode.Zoom; m_pictureBox.Image = m_bitmap; this.Text = ofd.FileName + " " + m_bitmap.Size.ToString(); } }

private void saveToolStripMenuItem_Click(object sender, EventArgs e) { } private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog(); if (sfd.ShowDialog() == DialogResult.OK) { try { m_bitmap.Save(sfd.FileName, ImageFormat.Jpeg); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } }

Pek ok kontrol kullanmnda Image zellii vardr. rnein Menu elemanlarnn solunda istersek kk bir resim gsterebiliriz. ToolStripMenuItem snfnn Image propertysi Menu elemannn solunda grntlenecek resmi belirler. Ara ubuklar gibi menuler gibi kontroller de pek ok kk resme dolayl olarak gereksinim duyulmaktad r. Bu resimlerinin hepsinin RunTime srasnda dosyadan hareketle oluturulmas hataya ok ak bir durum olusturur. nk o resimlerin bir tanesi bile silinse proje bozulacaktr. te resimler gibi pek ok data Resorce kavram altnda Assambly dosyasna gmlebilmektedir. Resource konusu detayl ve ayr bir konudur. Fakat FormEditor bu kontrollerin Image propertysine tklandgnda secilen resmi Resource olarak gomup kullanmaktadr. Visiul Studio IDEsi Install edildiginde Comman7 dizini ierisinde VS2008ImageLibrary dizininde ok kullanlan pek ok kk icon goruntusu bulunmaktadr. D me kontrollerinde oldugu gibi baz kontrollerde Image propertyleri vardr.Eer kontrolumuzun Image propertysi varsa biz bu property ye resim girdiimizde kontrolun zemininde resim goruntulenir. Ara ubuklar(Tool Bar): Ara ubuklar ToolStrip snf ile temsil edilmektedir yani ToolStrip snf hem ToolStripMenuStrip,StatuStrip snfnn taban snnfdr.Fakat ayn zamanda ara ubugu olarak da kullanlr. 118

ToolStrip

MenuStrip

StatuStrip

Buradaki mant ga grte aslnda ara ubugu bir nevi menu cubugudur.Onun zel bir bbiimidir. Anmsanaca gibi Ara ubuklar ToolStripItem snfndan tretilmi snflarla temsil edilmektedir. ToolStripItem snf Abstract bir snftr. Menu elemanlar aslnda dolayl olarak bu snftan tretilmitir. ToolStripItem snfnn tretme emas yledir. ToolStripItem

Tool Strip Button

Tool Strip Label

Tool Strip Seperator

Tool Strip Control Host

Tool Strip DropDown Item

ToolStrip ComboBox

ToolStrip TextBox

ToolStrip ProgressBar

ToolStrip MenuItem

Ara ubuu eleman oluturmak iin ToolStripButton, ToolStripLabel, ToolStripSeperator, ToolStripConrolHost snflar kullanlr. ToolStripDropDownItem ve ondan tremi snflar menu oluturmak iin kullanlr. Tipik olarak ara ubuu eleman bir dmedir. Yani programc ToolStripButton trnden bir nesne yaratr ve bu nesneyi ToolStrip snfnn Items Collection na ekler. ToolStripButton nesnesi grnt olarak yalnzca bir yaz, yalnzca bir resim ya da hem yaz hem resim gsterebilmektedir. Default durum yaz ve resmin birlikte grntlenmesidir. Genellikle bu durum istenen bir durum deildir. Nesnenin ToolStripItem snfndan gelen DisplayStyle isimli property eleman bu belirlemeyi yapmakta kullanlr. ToolStripButton nesnesinin istediimiz nesneyi grntleyebilmesi iin Image trnden Image property si kullanlr. Anahtar Notlar: ok tipik ara ubuu ve icon boyutlar 16x16 32x32 trndendir. Ara ubu u elemanna tkland nda ToolStripButton snfnn ToolStripItem snfndan gelen click event i tetiklenir. ncelikle Ara ubuu elemanlarn bytmek iin ara ubuunun kendisini 119

AutoSize mod dan karmak gerekir. ToolStrip snfnn Size property eleman ancak Auto Size false ise etkili olmaktadr. Halbuki AutoSize true durumdad r. Ara ubuu elemanlarn bytmek iin srasyla unlar yaplmaldr. 1. ToolStrip nesnesi AutoSize moddan kartlp Size propertysi dzenlenir. phesizara ubuunun genilii yukarya yuvaland iin deiemez. Ama ykseklii deitirilebilir. 2. ToolStrip nesnesinin ImageScalingSize isimli property eleman ara ubuu elemanlar kaa ka olacaksa o biimde ayarlanr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace Toolbar { public partial class Form1 : Form { private ToolStripButton m_toolbutton; public Form1() { InitializeComponent(); try { m_toolbutton = new ToolStripButton(); m_toolbutton.Text = "Deneme"; m_toolbutton.DisplayStyle = ToolStripItemDisplayStyle.Image; m_toolbutton.Image = new Bitmap(@"E:\DotNetAppBasic\Toolbar\Toolbar\audio.bmp"); m_toolBar.Items.Add(m_toolbutton); m_toolbutton.Click += new EventHandler(m_toolbutton_Click); } catch (Exception ex) { MessageBox.Show(ex.Message); }

} void m_toolbutton_Click(object sender, EventArgs e) { MessageBox.Show("Click"); } } } 120

3. Ara ubu una yerletirilen ToolStripItem nesnelerinin ImageScaling propertyleri ayrca SizeToFit durumunda olmaldr. Normal olarak tm ara ubuu elemanlarnn ayn boyutta olmas arzu edilir. Fakat bu zorunlu deildir. stenirse her ara ubu u eleman farkl boyutlarda olabilir. Bunun iin ara ubuu elemanlarn autosize moddan karmak ve onlara yeni Size vermek gerekir. ToolStrip snfnn ImageScalingSize eleman ToolStrip nesnelerinin AutoSize true ise etkili olmaktadr. Bazen bir ara ubuu elemannn ComboBox olmas ve TextBox olmas durumu ile karlalmaktad r. ComboBox ToolStripComboBox snfyla temsil edilmitir. TextBox ise ToolStripTextBox snfyla temsil edilmitir. Ara ubuu eleman ProgressBar da olabilir. Bu da ToolStripProgressBar snfyla temsil edilmitir. Bu snflarn hepsi ToolStripControlHost snfndan tretilmitir. ToolStripItem

ToolStripControlHost

ToolStrip ComboBox

ToolStrip TextBox

ToolStrip ProgressBar

Nihayet ToolStripControlHost snf aslnda herhangi bir controle evsahiplii yapan bir snftr. Biz bu snfn Control Property sine herhangi bir control yerletirisek aslnda ara ubu u eleman olarak o control grntlenir. Bunun iin en iyi yntem ToolStripControlHost snfndan tretme yapmaktr. Zaten aslnda ToolStripComboBox isimli snflarda bu yntemle elde edilmitir. Tab Control: TabControl API terminolojisinde Property Sheet ismiyle bilinmektedir. TabControl sayfal diyalog penceresidir. Bir diyalog penceresi alr. Sayfalar vardr. Aslnda her sayfa bamsz bir diyalog penceresi gibidir. Bylece kullanc pek ok belirlemeyi bir arada yapabilir. TabConrol Control nn her bir sayfas TabPAge isimli snfla temsil edilmitir. Dolaysyla programc nce sayfalar iin TabPage nesnelerini olu turur. Sonra bu nesneleri TabControl snfnn TabPageCollection snfnn TabPages elemanna ekler. TabPAge snf Panel snfndan tretilmitir. Panel snf ise Form snf gibidir. Anahtar Notlar: Panel isimli snf Form snfna benzemekle birlikte bir alt pencere oluturmaktadr. Panel adeta alt pencere biiminde bir form gibidir. Bir TabControl Form Editrde ok pratik oluturulabilmektedir. FormEditr TabPage nesnelerini kendisi oluturup TabControl snfna eklemektedir. Fakat bu ilemlerin en az br defa manuel yntemle yaplmas tavsiye edilir. Pek ok yaygn programda grdmz Options men eleman iinde TabControl n bulunduu bir diyalog penceresini amaktadr. Tipik olarak TabControl diyalog penceresinin iine yerletirilir. 121

Yine tipik olarak diyalog penceresinin Ok, Cancel , Apply gibi tular olur. Apply tu u bu tr diyalog pencerelerinde sk karlalan bir tutur. Bu tu yaplan deiikliklerin o anda etki yapmasn salar ve diyalog penceresinin kapatlmasn salamaz. TabControl ieren bir diyalog penceresi kapatld nda tm sayfalardak bilgilerin ele geirilmesi gerekir. Bunun birka yolu olabilir. 1. Diyalog penceresini temsil eden form snfnn TabControl eleman ya public yaplr ya da bir property ile elde edilir. Diyalog penceresi kapatldktan sonra bu elemandan faydalnlarak TabPAge nesnelerine eriilip tm bilgiler elde edilir. 2. Klasik yntem uygulanr. Yani Tm sayfalarda elde edilecek bilgiler diyalog penceresini temsil eden Form snfna property olarak girilir. Diyalog penceresi ok tuu ile kapatlmadan nce bu propertylere yerletirme yap lr. Anahatar Notlar: Bir tab Kontroln sayafalarna kontroller yerletirildiinde form editr bu kontrolleri anaformun veri eleman olarak tanmlar. Fakat tab kontroln panellerine yerletirir. izim lemeleri: Bir pencerenin alma alanna izim yapld nda windows bu izimi bizim iin saklamaz. Eer penceremizin stne baka bir pencere gelirse ve bu pencere ekilirse grnt saklanmad iin yaptm z izimler kaybolacaktr. Bir pencerenin grnmeyen ksm grnr hale geldiinde windows pencereye paint mesaj gndermektedir. Bizimde paint mesaj geldiinde bozulmu olan izimi yeniden yaparak bozulmay telefi etmemiz gerekir. Grld gibi windows yap lan izimleri bizim iin tutup geri basmaz fakat grnt bozulduunda pencereye mesaj gndererek bizi uyarr. Paint mesaj pencerenin grnmeyen bir ksm grnr hale geldiinde gnderilmektedir. rnein tiik olarak pencereinin zerinde bulunan baka bir pencereyi ektiimizde daha nce grnmeyen ksm grnr hale gelmitir ve paint mesaj gnderilir. Ya da rnein pencerenin bir ksmn masastnn dna karm olalm ve yeniden o ksm masastne ekelim yine paint mesaj gnderilir. Pencere bytldnde ya da kltldnde paint mesajnn gelip gelmemesi .nette control snfnn bool trden ResizeRedraw property si ile tespit edilmektedir. Bu propertynin default durumu false biimindedir. Yani pencere resize edildiinde paint mesaj olu maz. Fakat paint mesaj baz durumlarda oluturulmamaktadr. Pencere tanrken windows pencere iindeki grnty pencere ile birlikte tar. Menler alr kapanrken pencerenin grnmeyen bir ksm grnr bir hale geldii halde yine paint mesaj gelmememektedir. nk bozulan grnty men snf kendisi tutup basmaktadr. ResizeRedraw yle etki gstermektedir. 1. Property false ise(default durum) pencere kltldnde paint mesaj olu maz. Fakat byrtldnde paint mesaj olu ur. Ancak gncelleme alan (update region) yalnzca geniletilmi olan blge olur. 2. Eer bu property true ise bu durumda pencere daraltlsa da geniletilse de paint mesaj oluur ve gncelleme alan tm alma alan olur. Denetim masas ayarlarnda srklerken pencere ieriini grntle modundaysak (xp ve vista da bu durum defaulttur.) Grnmeyen ksm grnr hale getirilirken bir tane deil bir dizi mesaj gnderilir. Yani srklerken srkleme boyunca mesaj gnderilir. Biz herhangi bir yerde ve herhangi bir zamanda izim yaparsak tm bu izim kaytlarn tutup paint mesaj geldiinde yeniden yapmalyz. Ya da daha pratik olarak tm izimleri paint te yapabiliriz. Genellikle uygulanan teknik tm izimlerin paint mesajnda yaplmasdr. izim ilemleri iin Graphics snf kullanlmaktadr. Graphics snfnn Drawxxx ve Fillxxx 122

biiminde bir gurup fonksiyonu vardr. Bu fonksiyonlar izimleri yapar. Graphics nesnesi new operatryle yaratlamaz. nk tasarmc bunu istememitir. Snfn balang fonksiyonunu snfn private blmne yerletirmitir. Graphics nesnesi elde etmenin 2 yolu vardr. 1. Control snfnn CreateGraphics fonksiyonunu armak. 2. Paint event i olutuunda framework event fonksiyonuna mesaj parametre snf olarak PaintEventArgs nesnesi geirir. Bu nesnenin Graphics isimli property eleman yaratlm Graphics nesnesini verir. zetle Paint event i olutu unda graphics nesnesini biz yaratmayz. Graphics nesnesi zaten yaratlm olarak bize verilir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace PaintMessage { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { MessageBox.Show("Paint"); } } } Graphics nesnesi nispeten kt bir kaynaktr. Dolays yle bunun p toplaycya braklmadan sisteme iade edilmesi uygun olur. Eer Graphics nesnesini biz CreateGraphics fonksiyonu ile yaratmsak iimiz bitince Dispose fonksiyonunu armalyz. Yok eer Graphics nesnesi Framework tarafndan yaratlp PaintEvent fonksiyonuna geirilmise bizim bir ey yapmamza gerek yoktur. Programdan kldnda framework zaten Dispose yapmaktadr. Tm izimlerin Paint mesajnda yap lmas ve kk bir bllge yznden tm izimlerin yeniden yap lmas normal bir durummudur? rnein biz Paint mesajnda yzlerce izim yapm olalm ve pencerenin ok kk bir alan grnr hale gelsin. Paint mesaj geldiinde aslnda bizim yalnzca bozulan blgeyi izmemiz yeterli olacaktr. Her nekadar bozulan blgeyi elde edebilirsekte yalnzca oray izmek mmkn olmayabilir. nk fonksiyonlar tm izim yapmak iin oraya yerletirilmitir. Windows ister alt pencere olsun ister ana pencere olsun her pencere iin gncelleme alan(update region) denile dikdrtgensel bir blge tutar. Pencerenin grnmeyen bir ksm grnr hale geldiinde gncelleme alan gncellenir ve windows belli periyotlarda gncelleme alanlarn inceleyerek gncelleme alan bo kme olmayan pencerelere paint mesaj gnderir. Gncelleme alannn bo kme olmas demek pencerenin hibir blmnn grnt olarak 123

bozulmam olmas demektir. Graphics snfnn bir izim fonksiyonunu ele alalm. izim fonksiyonlar aslnda iki aamada ilemini yapmaktadr. nce ekrana baslacak noktalar hesapla elde edilir.(Rendering) Sonra pixeller baslr. Pixel basma ilemi noktalarn hesaplama ilemine gre ok yavatr. te biz paint mesajnda yzlerce izim fonksiyonu arsak bile burada ciddi bir zaman kayb olumayacakt r. nk izim fonksiyonlar eer baslmak istenen pixel gncelleme alan iinde kalyorsa onlar gerekten basmak demektir. Anahtar Notlar: eitli sylentilere gre microsoft pencere iindeki grnty saklamayp bunun yerine paint mesaj gnderme stratejisini uzun dnemde deitirmek istemektedir. Gerektende Vista da grnty saklayp geri basma mekanizmas daha glendirilmitir. Vista default ayarlarda baka bir pencerenin pencereyi kaplayp almas durumunda grnty otomatik tutup basmaktad r. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace PaintMessage { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.ResizeRedraw = true;

} private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawLine(Pens.Red, 0, 0, this.ClientSize.Width, this.ClientSize.Height); } private void Form1_MouseDown(object sender, MouseEventArgs e) { } private void Form1_MouseMove(object sender, MouseEventArgs e) { } } 124

} izim Nesneleri: En nemli iki izim nesnesi kalem ve fradr. izgiler kalemle izilir. Boyamalar frayla yaplr. Kalem(Pen) nesnesinin en nemli property si rengi, izim biimi ve kalnldr. Fralarn ise en nemli property leri rengi ve desenidir. rnein biz bir resimden fra yapabiliriz. Bu durumda boyama yaptmzda aslnda o resim izilir. Kalem nesnesi Pen snf yla temsil edilmitir. Bir kalem nesnesini yaratabilmek iin Pen snfnn balang fonksiyonlar kullanlabilir. Pen snfnn balang fonksiyonu 1 birimlik istenilen renkte kalem yaratr. Color ve Float parametreli balang fonksiyonu belirlenen renkte istenilen kalnlkta kalem olu turur. Pen snfnn Color ve Witdh property elemanlar da bu zelliklerin deitirilmesinde kullanlabilir. Pen snfnn PenType isimli property eleman PenType isimli enum trndendir ve kalemin desen sitilini belilemekte kullanlr. DashStyle propert eleman ise kalemin biimini belirlemek iin kullanlr. Anahtar Notlar: Bir snfn pek ok zellii sz konusu olabilir. Tm bu zelliklerin snfn balang fonksiyonunda belirlenmesi mmkn olmad iin tasarmc en enmli baz zelliklerin balang fonksiyonunda belirlenmesini dierlerinin propert yoluyla set edilmesini salayabilir. Hatta bazen snfn o kadar ok zellii sz konusu olabilirki programc bunlardan hibirini balang fonksiyonunu kullancdan istemez. Tm bu deerler default deerlerle set edilir. (rnein Button snfnda ve TextBox snfnda olduu gibi) Kalemin biti ekli EndCap property si ile belirlenebilir. Balang ekil biimi ise StartCap ile belirlenebilir. Eer istenirse balang ve biti ekilleri programcnn istedii desne eklinde ayarlanabilir. Bu ilemler CustomStartCap ve CustomEndCap propertyleri ile belirlenebilir. Anahtar Notlar: Menler ve ara ubuklar Framework 2.0 da birer pencere olduklar iin ana pencerenin alma alannn zerinde grntlenmektedir. Bu durumda alma alannn sol st kesi men alannn altnda kalmaktad r. Bu durum istenmeyen bir durumdur. Bunun iin enrilen tipik bir yntem bir panel penceresi yaratp bunu alma alann kaplar hale getirmek ve izimide panel zerinde yapmaktr. ki izgi uc uca getirildiinde eer kalem kaln ise bunlar birbirini kapatmayabilir. Snfn LineJoin property eleman bu amala kullanlmaktadr. Ayrca izgili kalem biiminde izgilerin uzunluklarda DashPattern property si ile ayarlananbilmektedir. Pen snfnn dier elemanlar MSDN dkmanlar ndan izlenebilir. Ayrca Pens isimli bir snfn bir kalnlkta kalem veren pek ok static propertyleri vardr.(Kalnlk=Pixel) Yani bizw bir kalem gerektii zaman acil olarak onu Pens snfyla salayabiliriz. Fra nesneleri boyama amal kullanlr ve bu nesneler Abstract Brush snfndan tretilmi nesnelerle temsil edilmektedir. Brush snfndan SolidBrush, TextureBrush ve HatchBrush gibi snflar tretilmitir. SolidBrush dz renkli fray temsil etmektedir. using System; 125

using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace DrawingSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; Pen pen = new Pen(Color.Red, 10); pen.EndCap = System.Drawing.Drawing2D.LineCap.Triangle; pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; g.DrawLine(Pens.MediumSeaGreen, new Point(0, 0), new Point(100, 100)); LinearGradientBrush sb = new LinearGradientBrush(new Rectangle(100, 100, 100, 100), Color.Yellow, Color.Red, 0.5F); g.FillEllipse(sb, new Rectangle(100, 100, 100, 100)); } } } Temel izim Fonksiyonlar: Graphics snfnn Drawxxx ve Fillxxx biiminde 2 gurup izim fonksiyonlar vardr. Drawxxx fonksiyonlar bizden bir kalem ister ve eklin ylanzca snr izgilerini izer. Fillxxx ise bizden bir fra ister ve eklin iini boyar. DrawLine fomksiyonlar bir kalem iki nokta alarak doru izmektedir. DrawEllipse ve FillEllippse fonksiyonlar bir dikdrtgenin teet ve i teet elipslerini izmektedir. DrawRectangel ve FillREctangel fonksiyonlar bir dikdrtgeni izip boyamak iin kullanlrlar.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data;

126

using System.Drawing;

using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace DrawingSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawRectangle(Pens.Red, new Rectangle(100, 100, 100, 100)); g.FillRectangle(Brushes.Yellow, new Rectangle(101, 101, 99, 99)); } } } Ayrca Brushes isimli snf temel renklere ilikin dz renkli fra veren pek ok static property elemanlarna sahiptir. O halde bizden bir fra istendiinde biz Brushes snfn kullanarak bunu hemen salayabiliriz. DrawLines isimli fonksiyon bir point dizisi iindeki noktalar birletirerek krkl dorular izer. DrawPolygon fonksiyonu DrawLinesfonksiyonu gibidir. Fakat ilk nokta ile son noktay birletirir. FillPolygon fonksiyonu da kapal bir eklin iini boyamakta kullanlr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace DrawingSample { public partial class Form1 : Form 127

{ public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawRectangle(Pens.Red, new Rectangle(100, 100, 100, 100)); g.FillRectangle(Brushes.Yellow, new Rectangle(101, 101, 99, 99));

Point[] pt = { new Point(100, 150), new Point(150, 100), new Point(500, 500) }; g.FillPolygon(Brushes.Green, pt); } } } Bir resmi izmek iin bir grup DrawImage fonksiyonu kullanlmaktadr. rnein PictureBox controlleri de izimi DrawImage fonksiyonlaryla yapmaktadr. Uint parametreli DrawImage fonksiyonu resmi Orijinal boyutuyla bir noktadan balayarak btnsel olarak izer. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace DrawingSample { public partial class Form1 : Form { private Image m_image; public Form1() { InitializeComponent(); Environment.CurrentDirectory = @"E:\DotNetAppBasic\DrawingSample\DrawingSample"; 128

try { m_image = new Bitmap("forest.jpg"); } catch (Exception e) { MessageBox.Show(e.Message); } } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawImage(m_image, new Point(100, 100)); } } } Bu fonksiyonun sol st k e noktasn ayr int deerlerle alan biimi de vardr. Rectangel parametreli DrawImage fonksiyonu resmi belirtilen dikdrtgen boyutuna getirtir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace DrawingSample { public partial class Form1 : Form { private Image m_image; public Form1() { InitializeComponent(); Environment.CurrentDirectory = @"E:\DotNetAppBasic\DrawingSample\DrawingSample"; try { m_image = new Bitmap("forest.jpg"); 129

} catch (Exception e) { MessageBox.Show(e.Message); } } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawImage(m_image, new Rectangle(100, 100, 100, 100)); } } } Point dizi parametreli DrawImage fonksiyonlar 3 elemanl bir point dizisi alr ve ekli dndrerek izer. Dizinin birinci eleman sol st ke, 2. eleman sa st k e ve 3. eleman sol alt k eyi belirtir. Drdnc ke zaten bu deerlerden elde edilebilmektedir. Anahtar Notlar: Kontrol snfnn ResizeRedraw property eleman protected blmdedir. Bu nednele Maalesef form zerine panel atmzda panelin ResizeRedraw property sini set edemeyiz. Bu ilemi yapabilmek iin mecburen panel snfndan bir snf tretmemiz gerekir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; namespace DrawingSample { public partial class Form1 : Form { private Image m_image; public Form1() { InitializeComponent();

Environment.CurrentDirectory = @"E:\DotNetAppBasic\DrawingSample\DrawingSample"; try { 130

m_image = new Bitmap("forest.jpg"); } catch (Exception e) { MessageBox.Show(e.Message); } } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawImage(m_image, new Point[] {new Point(panel1.ClientSize.Width / 2, 0), new Point(panel1.ClientSize.Width, panel1.ClientSize.Height / 2), new Point(0, panel1.ClientSize.Height / 2)}); } } class MainPanel : Panel { public MainPanel() { this.ResizeRedraw = true; } } } Bu DrawImage fonksiyonu phesiz ayn zamanda ekli belirlenen boyuta da getirmektedir. Dier DrawImage fonksiyonlar MSDN dkmanlarndan incelenmelidir. Pencerenin alma alanna bir yaznn yazlmas aslnda bir izim faaliyetidir ve bu ilemler DrawString fonksiyonlaryla yap lmaktadr. Baka da yaz yazan bir fonksiyon yoktur. Yaz yazmak dorudan font konusuyla da ilgilidir. DrawString fonksiyonlar bizden bir font nesnesi ister. Yaz y o font nesnesindeki belirlemelere gre yazar. Bir font un temel zellikleri unlard r. Yaznn temel karakteristii(Typeface) Yaznn ikincil karakteristik zellikleri(Bold, italik) Yaznn yaz karaketrelerinin boyutu Dier zellikler. Font nesnesi Font snfyla temsil edilmitir. Bir Font nesnesi Font snfnn balang fonksiyonlaryla yaratlr. Font snfnn en ok kullanlan balang fonksiyonlarndan biri yledir. public Font( string familyName, float emSize ) Burada 1. parametre font ailesini belirten yazd r. 2. parametre font un bykln belirtir. Bir punto 1/71 dpi(dot per inch) dir. Fonksiyonun birinci parametresi yanl girilirse fonksiyon baarsz 131

olmaz fakat default font yklenir. Font snfnn dier bir balang fonksiyonu da 3 parametreli aadaki fonksiyondur. public Font( string familyName, float emSize, FontStyle style ) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace FontSample { public partial class Form1 : Form { private Font m_font; public Form1() { InitializeComponent(); m_font = new Font("Times new Raman", 20); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawString("This is a test...", m_font, Brushes.Red, new Point(100, 100)); } } } FontStyle paramtresi FontStyle isimli bir enum trndendir. Font un Bold, talik, UnderLine gibi zelliklerini belirtir. Birden fazla zellik ubuk operatr ile birletirilebilir. Elimizde mevcut bir font varsa biz o fontun dier zelliklerine dokunmadan italik, bold gibi bir versiyonunu elde edebiliriz. Bu ilem aadaki balang fonksiyonu ile salanabilir. public Font( Font prototype, FontStyle newStyle ) Font ailesi FontFamily isimli bir snfla temsil edilmitir. Font snfnn FontFamily property si bunu verir. 132

rnein: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace FontSample { public partial class Form1 : Form { private Font m_font; public Form1() { InitializeComponent(); m_font = new Font("Times new Roman", 50, FontStyle.Strikeout| FontStyle.Italic); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawString("This is a test...", m_font, Brushes.Red, new Point(100, 100)); } } } Burada Times new Romans a ilikin Font nesnesi elde edilmitir. Font snf da IDisposable arayzn deteklemektedir. Yani kullanm ndan sonra dispose fonksiyonunu armak iyi bir tekniktir. Bir font sabit geilikli ya da deiken genilikli olabilir. rnein Times New Roman deiken genilikte Courier new sabit genilikte fontlardr. Programla editrleri hemen her zaman sabit genilikli fontlar kullanr. Satr satr yaz yaqzabilmek iin font yksekliini bilmek gerekir. Font snfnn Heigth isimli property eleman pixel cinsinden font yksekliini vermektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; 133

using System.Text; using System.Windows.Forms; namespace FontSample { public partial class Form1 : Form { private Font m_font; public Form1() { InitializeComponent(); m_font = new Font("Times new Roman", 12);

foreach (FontFamily ff in FontFamily.Families) comboBox1.Items.Add(ff.Name); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; int y = 0; g.DrawString("Bu bir denemedir", m_font, Brushes.Red, new Point(0, y)); y += m_font.Height; g.DrawString("Bu bir denemedir", m_font, Brushes.Red, new Point(0, y)); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { m_font = new Font((string) comboBox1.SelectedItem, 50); this.Invalidate(); m_font.Dispose(); } } } Yaz yazmak iin kullanlan tek fonksiyon DrawString fonksiyonudur. En temel DrawString fonksiyonu aadaki gibidir. public void DrawString ( string s, Font font, Brush brush, float x, float y 134

) Fonksiyonun x, y parametresi yaznn yazlaca noktann sol st k esidir. Yani yazlacak yaz bir dikdrtgen iine alnsa bu dikdrtgenin sol st kesi bu koordinat olacaktr. Dier bir DrawString fonksiyonu yazy belirli bir dikdrtgensel alann ierisine yazar. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace FontSample { public partial class Form1 : Form { private Font m_font; public Form1() { InitializeComponent(); m_font = new Font("Times new Roman", 12);

foreach (FontFamily ff in FontFamily.Families) comboBox1.Items.Add(ff.Name); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawString("Bu bir denemedir evet evet denemedir", m_font, Brushes.Black, new RectangleF(100, 100, 100, 100)); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { m_font = new Font((string) comboBox1.SelectedItem, 50); this.Invalidate(); m_font.Dispose(); } } } public void DrawString ( 135

string s, Font font, Brush brush, RectangleF layoutRectangle ) Fonksiyonun bu versiyonu szcklerden sarmalama yapmaktadr. Yukardaki iki fonksiyonun StringFormat parametreli versiyonu da vardr. public void DrawString ( string s, Font font, Brush brush, PointF point, StringFormat format ) Bu fonksiyon belirtilen noktaya gre hizalama yapmaktadr. StringFormat snfnn Alignment ve LineAlignment property leri StringAlignment isimli Enum trndendir. Bu durumda rnein alma alannn tam ortasna yle bir yaz yazabiliriz. Yukardaki fonksiyonun ayrca Rectangel ieren versiyonu da vardr. public void DrawString ( string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format ) Ekrann ortasna yazma ilemi yle de yaplabilir. g.DrawString(Deneme, m_font, Brushes.Red, thisClientRectangle, sf); Dier DrawString fonksiyonlar Point-PointF farkll iermektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace FontSample { public partial class Form1 : Form { private Font m_font;

136

public Form1() { InitializeComponent(); this.ResizeRedraw = true; m_font = new Font("Times new Roman", 20);

foreach (FontFamily ff in FontFamily.Families) comboBox1.Items.Add(ff.Name); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; Rectangle rect = new Rectangle(100, 100, 100, 100); g.DrawRectangle(Pens.Red, rect); g.DrawString("Deneme", m_font, Brushes.Red, rect, sf); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { m_font = new Font((string) comboBox1.SelectedItem, 50); this.Invalidate(); } } } Graphics Nesnesi ve izim Alan: Graphics nesnesini elde etmenin temel olarak iki yolu vardr. Birinci yol Paint mesajdr. Paint mesaj ile bize verilen graphics nesnesini kullanarak pencerenin her yerine izim yapamayz. Yalnzca bozulmu olan bozulma alanna izim yapabiliriz. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; 137

namespace FontSample { public partial class Form1 : Form { private Font m_font; private Random m_rand; public Form1() { InitializeComponent(); m_rand = new Random(); this.ResizeRedraw = true; m_font = new Font("Times new Roman", 20);

foreach (FontFamily ff in FontFamily.Families) comboBox1.Items.Add(ff.Name); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; SolidBrush sb = new SolidBrush(Color.FromArgb(m_rand.Next(256), m_rand.Next(256), m_rand.Next(256))); g.FillRectangle(sb, this.ClientRectangle); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { m_font = new Font((string) comboBox1.SelectedItem, 50); this.Invalidate(); } } } Fakat Graphics nesnesi CreateGraphics fonksiyonu ile elde edilirse biz o Graphics nesnesi ile pencerenin her yerine izim yapabiliriz. Zaten Paint mesaj ilendikten sonra gncelleme alan bo kme haline getirilmektedir. Yani Biz rnein fare mesajlarnda izim yaptpmzda gncelleme alan bo kme durumunda olacaktr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; 138

using System.Linq; using System.Text; using System.Windows.Forms; namespace FontSample { public partial class Form1 : Form { private Font m_font; private Random m_rand; public Form1() { InitializeComponent(); m_rand = new Random(); this.ResizeRedraw = true; m_font = new Font("Times new Roman", 20);

foreach (FontFamily ff in FontFamily.Families) comboBox1.Items.Add(ff.Name); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = this.CreateGraphics(); SolidBrush sb = new SolidBrush(Color.FromArgb(m_rand.Next(256), m_rand.Next(256), m_rand.Next(256))); g.FillRectangle(sb, this.ClientRectangle); g.Dispose(); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { m_font = new Font((string) comboBox1.SelectedItem, 50); this.Invalidate(); } } } Bitmap'a izim Yapmak: Paint mesajndan elde ettiimiz Graphics nesnesi ya da CreateGraphics fonksiyonu ile elde ettiimiz Graphics nesnesi ekrana izim yapmak iin kullanlr. Eer Graphics snfnn FromImage static fonksiyonu ile birGraphics nesnesi elde edilirse biz bu Graphics nesnesi 139

ile izim yaptm zda ekrana deil ilgili resmin zerine izim yaplr. public static Graphics FromImage ( Image image ) rnein: Bitmap bmp = new Bitmap(1000, 1000); Graphics g = Graphics.FromImage(bmp); g.FillRectangle(Brushes.Red, new Rectangle(0, 0, 1000, 1000)); //... g.Dispose(); ekil Tama lemleri: Daha nceden kontrolleri tam tk. Kontroller kendi izimlerini yaptklar iin yani birer pencere olduklar iin tama ilemi problemsizdir. Control n Location property sinin gncellenmesi yeterlidir. Halbuki kendi izdiimiz bir dikdrtgeni ve Elipsi tarken eski eklin silinmesi eklin tanan blgede yeniden izilmesini gerektirir. Bir eklin silinmesi demek onun zemin rengiyle yeniden izilmesi demektir. Bir pencerenin grnmeyen bir ksmnn grnr hale geldiini dnelim .net PaintEvent fonksiyonunu armadan nce pencerenin bozulmu olan gncelleme alann belirlenen zemin rengiyle boyamaktadr. Yani ak Paint fonksiyonuna geldiinde bozulmu alann zemini boyanm durumdadr. Yani bozulmu alann zerindeki izimler de kaybolmu durumdad r. Biz Paint mesajnda izim yaparken zeminle hi uramadan dorudan ekilleri izebiliriz. nk zaten zemin o noktada yenidem boyanm durumdadr. Anahtar Notlar: Pens snfnn yansra SystemPens isimli bir snf da vardr. Bu snf da static elemanlardan olu mu tur. Bu snf bize denetim masas ayarlarna gre bir kalnlkta renkli kalem vermektedir. Benzer biimde SystemBrushes snf da denetim masas renklerine gre bize fra verir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace DraggingShape { public partial class Form1 : Form { private Rectangle m_rect; private Point m_prevPoint; private bool m_leftFlag; public Form1() { InitializeComponent(); 140

m_rect = new Rectangle(100, 100, 100, 100); } private void Form1_MouseMove(object sender, MouseEventArgs e) { if (m_leftFlag) { Graphics g = this.CreateGraphics(); int deltaX = e.X - m_prevPoint.X; int deltaY = e.Y - m_prevPoint.Y; g.FillEllipse(SystemBrushes.Window, m_rect); m_rect.Offset(deltaX, deltaY); g.FillEllipse(Brushes.Red, m_rect); m_prevPoint = e.Location; g.Dispose(); } } private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (m_rect.Contains(e.Location)) { m_leftFlag = true; m_prevPoint = e.Location; } } } private void Form1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { m_leftFlag = false; } } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.FillEllipse(Brushes.Red, m_rect); } } 141

} Invalidate Fonksiyonlar: Control snfnn invalidate fonksiyonlar paint mesajn programlama yoluyla oluturmak iin kullanlr. Parametresiz invalidate fonksiyonu tm alma alann geersiz hale getirir. Yani sanki pencerenin tamam kapalym dasonra grnr hale gelmi gibi bir etki yaratr. Tabi bu durumda paint mesaj geldiinde paint mesaj iinde yaplan izimler pencerenin her yerine yap lr. Bu durumda yavala yol aabilir. Rectangle parametreli invalidate fonksiyonu verilen rectangle geersiz hale getirerek paint mesaj oluturur. Ayrca bool parametreli invalidate fonksiyonlar da vard r. Bu fonksiyonlar alt pencerelerinde geersiz hale getirilp getirlimeyeceini belirtir. Tm izimlerin Paint Mesajnda Yaplmas: Uygulanan klasik teknik tm izimlerin paint mesajnda yaplmasdr. izim darda yaplacak olsa bile yap lacak izimin datalar saklanr sonra invalidate fonksiyonu arlr. izim yine paint mesajnda yap lm olur. Invalidate fonksiyonu arldnda zaten geersiz hale getirilmi zemin paint mesaj olu turulup event fonksiyonu arlmadan nce zemin rengiyle boyanm durumdad r. Yani bizim geersiz blgeyi silmemize gerek yoktur. O blge zaten paint mesaj dolaysyla silinmektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace DraggingShape { public partial class Form1 : Form { private Rectangle m_rect; private Point m_prevPoint; private bool m_leftFlag; public Form1() { InitializeComponent(); m_rect = new Rectangle(100, 100, 100, 100); } private void Form1_MouseMove(object sender, MouseEventArgs e) { if (m_leftFlag) { Graphics g = this.CreateGraphics(); int deltaX = e.X - m_prevPoint.X; int deltaY = e.Y - m_prevPoint.Y; 142

m_rect.Offset(deltaX, deltaY); this.Invalidate(); m_prevPoint = e.Location; g.Dispose(); } } private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (m_rect.Contains(e.Location)) { m_leftFlag = true; m_prevPoint = e.Location; } } } private void Form1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { m_leftFlag = false; } } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.FillEllipse(Brushes.Red, m_rect); } } } Tm izimlerin paint mesajnda yapld durumda geersiz hale getirilmek istenen alann minimal dzeyde tutulmas en etkin yntemdir. Bu hesabn yap lmas bazen zor olabilmektedir. Kesin bir hesap yerine kaba bir hesap yaplabilir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; 143

using System.Text; using System.Windows.Forms; namespace DraggingShape { public partial class Form1 : Form { private Rectangle m_rect; private Point m_prevPoint; private bool m_leftFlag; private Rectangle m_testRect; public Form1() { InitializeComponent(); m_rect = new Rectangle(100, 100, 100, 100); m_testRect = new Rectangle(0, 0, 100, 100); } private void Form1_MouseMove(object sender, MouseEventArgs e) { if (m_leftFlag) { Graphics g = this.CreateGraphics(); int deltaX = e.X - m_prevPoint.X; int deltaY = e.Y - m_prevPoint.Y; Rectangle temp = m_rect; m_rect.Offset(deltaX, deltaY); Rectangle invalidateRect = Rectangle.Union(temp, m_rect); this.Invalidate(invalidateRect); m_prevPoint = e.Location; g.Dispose(); } } private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (m_rect.Contains(e.Location)) { 144

m_leftFlag = true; m_prevPoint = e.Location; } } } private void Form1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { m_leftFlag = false; } } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.FillEllipse(Brushes.Red, m_rect); g.FillRectangle(Brushes.Yellow, m_testRect); } } } Titreme Problemi: Tm izimlerin paint mesajnda yap ldn varsayalm. Bir ekli fareyle srklediimizde invalidate fonksiyonunu ardm z zaman nce zemin, zemin rengiyle boyanacak sonra paint fonksiyonu alacaktr. Bu durumda eklin eski konumuyla yeni konumunun kesiim alan nce zemin rengiyle boyanp sonra yeniden ekil rengiyle boyanacaktr. Bu durum titremeye(flickering) yol aar. Titreme probleminin klasik zm izimlerin nce bir bitmap e yaplmas(Offscreen) sonrapaint mesaj geldiinde o bitmap in DrawImage fonksiyonuyla ekrana izilmesidir. Bitmap yntemini mauel uygulamak iin u ad mlar uygulanr. 1. Maksimum ekran boyutu kadar bir bitmap yaratlr. 2. Fareyle izim o anda bitmap stne yaplr. Ya da paint mesaj geldiinde izim bitmap zerine yaplr. 3. Nihayet paint mesajnda bitmap in ilgili blgesi DrawImage fonksiyonuyla ekrana izilir. Framework 2.0 ile birlikte yukarda aklanan yntem otomatik uygulanmaya balanm tr. Control snfnn bool trden protected DoubleBuffered isimli property eleman bu ilemi otomotize etmektedir. Bu property nin default deeri flase biimindedir. Bu property true yaplrsa unlar gerekleir: Ktphane sistemi Control snfnn OnPaint fonksiyonunda kendi ierisinde bir bitmap nesnesi yaratr ve bu bitmap e ilikin bir graphics nesnesi elde eder. Event fonksiyonunu bu graphics nesnesi ile arr. Bylece biz paint mesajnda bu graphics nesnesini kullanarak yaptm z izimleri aslnda ekrana deil birmap e yapm oluruz. Nihayet paint fonksiyonu bittiinde ktphane kendisi bu bitmap deki grnty geersiz olan gncelleme alanna izer. using System; using System.Collections.Generic; using System.ComponentModel; 145

using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace DraggingShape { public partial class Form1 : Form { private Rectangle m_rect; private Point m_prevPoint; private bool m_leftFlag; private Rectangle m_testRect; public Form1() { InitializeComponent(); this.DoubleBuffered = true; m_rect = new Rectangle(100, 100, 100, 100); m_testRect = new Rectangle(0, 0, 100, 100); } private void Form1_MouseMove(object sender, MouseEventArgs e) { if (m_leftFlag) { Graphics g = this.CreateGraphics(); int deltaX = e.X - m_prevPoint.X; int deltaY = e.Y - m_prevPoint.Y; Rectangle temp = m_rect; m_rect.Offset(deltaX, deltaY); Rectangle invalidateRect = Rectangle.Union(temp, m_rect); this.Invalidate(invalidateRect); m_prevPoint = e.Location; g.Dispose(); } } private void Form1_MouseDown(object sender, MouseEventArgs e) 146

{ if (e.Button == MouseButtons.Left) { if (m_rect.Contains(e.Location)) { m_leftFlag = true; m_prevPoint = e.Location; } } } private void Form1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { m_leftFlag = false; } } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.FillEllipse(Brushes.Red, m_rect); g.FillRectangle(Brushes.Yellow, m_testRect); } } } Timer lemleri: Pek ok uygulamada baz fonksiyonlarn periyodik olarak arlmas gerekmektedir. rnein bir oyun programnda bir eklin belirli bir hzda hareketini salamak iin byle bir mekanizma gerekmektedir. Bu tr ilemler Timer snflaryla yap lmaktadr. Kullanm birbirine ok benzeyen farkl isim alanlarnda bulunan timer snf vard r. System.Threading isim alanndaki Timer snf kendi iinde thread oluturarak Timer mekanizmasn salar. Baz uygulamalarda bu yntem zellikle tercih edilmektedir. System.Windows.Forms isim alan iindeki Timer snf windows un WM_TIMER mesaj sistemini kullanr. Dolaysyla hi Thread amaz. Bu en klasik yntemdir. Nihayet System.Timers isim alan iindeki Timer snf da yine thread kullanmaktadr. Bu snf Component snfndan tretildii iin tamamen form editrde kullanlabilmektedir. (System.Windows.Forms iinteki Timers snfda Component snfndan tretilmitir. Dolaysyla onun iin de ToolBox destei vardr) Timer snflarnn hepsinin kullanm birbirine ok benzer. Burada System.Windows.Forms isim alan iindeki Timers snf ele alnacaktr. Timer snfnn Interval isimli property eleman periyodu belirlemekte kullanlr. Default periyod 100 milisaniyedir.

147

Snfn bool trden Enabled property eleman Timer aktif ya da pasif duruma getirir. Default deer False biimdedir. Yani Timer nesnesi yaratldnda henz ilev grmemektedir. lemin balatlmas iin ya Enabled property si true yaplr ya da start fonksiyonu arlr. Benzer biimde Enabled property sini False yapmakla stop fonksiyonunu armak ayn anlamdad r. Timer snfnn Tick isimli event eleman EventHandler isimli delege trndendir ve arlacak fonksiyonu belirler. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace DigitalClock { public partial class Form1 : Form { private Timer m_timer; private string m_strClock; private Font m_font; public Form1() { InitializeComponent(); this.ResizeRedraw = true; this.DoubleBuffered = true; m_timer = new Timer(); m_timer.Interval = 1000; m_timer.Tick += new EventHandler(m_timer_Tick); m_timer.Start(); m_strClock = ""; m_timer_Tick(null, null);

m_font = new Font("Times New Roman", 100); } void m_timer_Tick(object sender, EventArgs e) { DateTime dt = DateTime.Now; m_strClock = string.Format("{0:D2}:{1:D2}:{2:D2}", dt.Hour, dt.Minute, dt.Second); this.Invalidate(); } private void Form1_Paint(object sender, PaintEventArgs e) { 148

Graphics g = e.Graphics; StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; g.DrawString(m_strClock, m_font, Brushes.Red, this.ClientRectangle, sf); } } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace DigitalClock { public partial class Form1 : Form { private Timer m_timer; private string m_strClock; private Font m_font; public Form1() { InitializeComponent(); this.ResizeRedraw = true; this.DoubleBuffered = true; m_timer = new Timer(); m_timer.Interval = 1000; m_timer.Tick += new EventHandler(m_timer_Tick); m_timer.Start(); m_font = new Font("Times New Roman", 100); m_strClock = "99:99:99"; Graphics temp = this.CreateGraphics(); SizeF sf = temp.MeasureString(m_strClock, m_font); this.MinimumSize = new Size((int) sf.Width + 10, (int) sf.Height + 10);

149

temp.Dispose();

m_timer_Tick(null, null);

} void m_timer_Tick(object sender, EventArgs e) { DateTime dt = DateTime.Now; m_strClock = string.Format("{0:D2}:{1:D2}:{2:D2}", dt.Hour, dt.Minute, dt.Second); this.Invalidate(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; g.DrawString(m_strClock, m_font, Brushes.Red, this.ClientRectangle, sf); } } } Region ve GraphicsPath lemleri: Region alma alan iindeki izim iin kullanlabilecek bir blgeyi belirtir. GraphicsPath kavram Region kavramndan daha sonra onun ilevini geniletecek biimde tasarlanmtr. Programc nce Region Ya da GraphicsPath tanmlamasn yapar sonra bu tanmlanm alan zerinde eitli ilemleri yapar. Bir Region Region snfyla temsil edilmektedir. Region nesnesi default balang fonksiyonu ile yaratlabilir. Bir GraphicsPath Regiona dn trlebilir. Ya da bir dikdrtgensel blgeden Region oluturulabilir. Region snfnn baz faydal fonksiyonlar vardr. rnein intersect fonksiyonu Region nn belirttii alanla verilen dikdrtgenin kesiim alann belirler Regionu bu kesim alan haline dntrr. Ya da iki Region nn kesiim kmesinden bir Region elde edilebilir. Benzer biimde snfn Union fonksiyonlar kesiim yerine birleim ilemi yapar. XOR fonksiyonlar da kesiim d ndaki alan Region yapar. Region snf System.Drawing isim alan iindedir. using System; using System.Collections.Generic; using System.ComponentModel; 150

using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace RegionSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; Region reg1 = new Region(new Rectangle(100, 100, 100, 100)); Region reg2 = new Region(new Rectangle(150, 150, 100, 100)); reg1.Union(reg2);

g.FillRegion(Brushes.Red, reg1); } } } GraphicsPath ilemleri de GraphicsPath snfyla temsil edilmitir. Bu snf System.Drawing.Drawing2D isim alan iindedir. GraphicsPath snf daha gelikin bir Region kavam sunmaktadr. Bu snf sayesinde dzgn olmayanblgeler tanmlayabiliriz. Snfn bir gurup Addxxx fonksiyonu vardr. Her Add fonksiyonu arld ka blgeye yeni eleman eklenir. CloseFigure fonksiyonu son eklenen elemanla ilk noktay birletirerek ekli kapatr. Tabi bu fonksiyon kapal olmayan izimlerde nemlidir. Bir GraphicsPath Region biimine dntrlebilir. Graphics snfnn nasl FillRegion DrawRegion gibi fonksiyonlar varsa DrawPath, FillPath gibi fonksiyonlar da vardr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Windows.Forms; 151

namespace RegionSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; GraphicsPath gp = new GraphicsPath(); gp.AddLine(50, 300, 100, 200); gp.AddArc(new Rectangle(100, 100, 100, 100), 135, 270); gp.AddLine(200, 200, 250, 300); gp.CloseFigure();

g.FillPath(Brushes.Red, gp); g.DrawPath(Pens.Black, gp); } } } Bir noktann bir Region nn veya bir GraphicsPath iinde olup olmadn anlamak iin Region snfnn ve GraphicsPath snfnn isVisible fonksiyonlar kullanlr(Hit Testing). Region ve GraphicsPath snflarnn Translate fonksiyonlar blgeyi belirli bir miktar telemek iin kullanlr. Bylelikle belirli bir Region ya da GraphicsPath nesnesini tayabiliriz. Anmsanaca gibi Control snfnn invalidate fonksiyonlar tm alma alann veya bir blgesini sanki grnt bozulmu gibi gbcelleme alan haline getirebilir. Bylece paint mesaj olumakta ve nce gnceleme alannn resmi silinmektedir. te Region parametreli invalidate fonksiyonlar da vardr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Windows.Forms; namespace RegionSample 152

{ public partial class Form1 : Form { private bool m_flag; private int m_prevX, m_prevY; private Region m_reg; public Form1() { InitializeComponent(); this.DoubleBuffered = true; GraphicsPath gp = new GraphicsPath(); gp.AddLine(50, 300, 100, 200); gp.AddArc(new Rectangle(100, 100, 100, 100), 135, 270); gp.AddLine(200, 200, 250, 300); gp.CloseFigure(); m_reg = new Region(gp); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.FillRegion(Brushes.Red, m_reg); } private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (m_reg.IsVisible(e.Location)) { m_flag = true; m_prevX = e.X; m_prevY = e.Y; } } } private void Form1_MouseMove(object sender, MouseEventArgs e) { if (m_flag) { this.Invalidate(m_reg); m_reg.Translate(e.X - m_prevX, e.Y - m_prevY); 153

this.Invalidate(m_reg); m_prevX = e.X; m_prevY = e.Y; this.Text = (e.X - m_prevX).ToString() + " " + e.X.ToString(); this.Invalidate(); } } private void Form1_MouseUp(object sender, MouseEventArgs e) { m_flag = false; } } } Windows aslnda gncelleme alanna deil Clip alanna pikselleri yerletirir. Clip alan normal olarak gncelleme alanyla ayn aland r. Fakat biz clip alann ayr bir biimde tanmlayabiliriz. Bu durumda izim paint mesaj iinde gncelleme alan iinde kalan clip alanna yap lr. Yani izimler paint mesaj iinde gncelleme alanyla clip alannn kesiim blgesine yaplmaktadr. Graphics snfnn Region trnden Clip isimli property eleman Clip blgesini belirlemede kullanlr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Windows.Forms; namespace CircleImage { public partial class Form1 : Form { private GraphicsPath m_gp; public Form1() { InitializeComponent(); this.ResizeRedraw = true; m_gp = new GraphicsPath(); m_gp.AddEllipse(this.ClientRectangle); 154

} private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clip = new Region(m_gp); try { g.DrawImage(Image.FromFile(@"E:\DotNetAppBasic\CircleImage\forest.jpg"), this.ClientRectangle); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void Form1_Resize(object sender, EventArgs e) { m_gp = new GraphicsPath(); m_gp.AddEllipse(this.ClientRectangle); } } } Graphics snfnn Clip isimli property elemann set etmek yerine SetClip fonksiyonu da ayn ii grr. Graphics snfnn IntersectClip isimli fonksiyonlar mevcut clip alanna baka bir dikdrtgen ya da regionla kesitirerek kesiimi clip alan yapar. Benzer biimde ExcludeClip isimli fonksiyon belirli bir region ya da dikdrtgeni clip alanndan atar. ResetClip fonksiyonu Clip alann bo kme yapar. Yani onu bo altr. Translate Clip fonksiyonlar klip alann deltax-deltay kadar teler. Ekrandan grntnn belli bir blgeye kopyalanmas: Framework 2.0 ile birlikte ok gereksinim duyulan ekran grntsnn elde edilmesi ok kolaylatrlm tr. Graphics snfnn CopyFromScreen fonksiyonlar ekrann belli bir dikdrtgensel alann izebilmektedir. CopyFromScreen fonksiyonlarnn en ok kullanlan biimi yledir. Fonksiyonun ilk iki parametresi ekran blgesinde kopyalanmak istenen yerin sol st k esini belirtir. Fonksiyonun 3. ve 4. parametreleri hedef izim alannda bir sol st ke belirtir. Son parametre belirlenen noktadan itibaren kopyalanacak dikdrtgenin genilik ve uzunluunu belirtir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CopyFromScreen 155

{ public partial class Form1 : Form {

public Form1() { InitializeComponent(); this.ResizeRedraw = true; } private void captureToolStripMenuItem_Click(object sender, EventArgs e) { panel1.Invalidate(); } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.CopyFromScreen(0, 0, 0, 0, new Size(200, 200)); } } } Ekran kopyalama uygulamalarnda programc ekrann (yani masastnn) yatay ve dey pixel znrln bilmek isteyebilir. Gelimi donanmlarda artk bilgisayara bal birden fazla ekran szkonusu olabilmektedir. Gerektende .net snf sisteminde eer bilgisayarmza birden fazla monitr balysa bunlarn hepsini elde edebilmekteyiz. Fakat ekranlardan biri iletim sistemi tarafndan birincil ekran olarak deerlendirilmektedir. Screen isimli snf ekran kavramn temsil etmektedir. Bu snfn Bounds isimli property eleman sol st kesi sfr sfr olacak biimde ekrann pixel znrln rectangle olarak verir. Screen snfnn static PimaryScreen isimli property eleman birincil ekrana ilikin screen nesnesini vermektedir. Yine Screen snfnn static AllScreens isimli property eleman tm ekranlarn bilgilerini bir dizi halinde alr. Screen snfnn BitsPerPixel propertysi ayn zamanda ekrann renk znrl n vermektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CopyFromScreen { public partial class Form1 : Form 156

public Form1() { InitializeComponent(); this.ResizeRedraw = true; } private void captureToolStripMenuItem_Click(object sender, EventArgs e) { panel1.Invalidate(); } private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.CopyFromScreen(0, 0, 0, 0, new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height));

} } } Screen snfnn WorkingArea isimli property eleman masastnn kullanlabilir blgesini rectangle olarak vermektedir. Yani bu verilen alanda grev ubuu ve dier erevesel farklar kart lmaktadr. Ekran grntsn bir bitmap olarak save etmek de olduka kolaydr. Yaplacak ilem yeni bir bitmap yaratmak bu bitmap iin bir graphics nesnesi elde etmektir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CopyFromScreen { public partial class Form1 : Form {

public Form1() { 157

InitializeComponent(); this.ResizeRedraw = true; } private void captureToolStripMenuItem_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); Graphics g = Graphics.FromImage(bmp); } private void panel1_Paint(object sender, PaintEventArgs e) {

} } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CopyFromScreen { public partial class Form1 : Form { private Bitmap m_bmp; public Form1() { InitializeComponent(); this.ResizeRedraw = true; } private void captureToolStripMenuItem_Click(object sender, EventArgs e) { m_bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height); Graphics g = Graphics.FromImage(m_bmp); g.CopyFromScreen(0, 0, 0, 0, new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)); panel1.Invalidate(); 158

} private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; if (m_bmp != null) g.DrawImage(m_bmp, panel1.ClientRectangle); } } } Yansyan Top rnei: Tula krmaca gibi, tenis gibi pek ok oyunda bir top hareket etmekte bir engelle karlatnda arparak uzaklamaktad r. Top engele arp ca dzgn yansmas ilemi basit trigonometrik bir hesapla yaplabilir. Topun balangta bir gidi as vard r. Bu a yansmadan sonra deitirilir. Topun yatayla alfa asyla hareket ettiini d nelim bu ada topun a birim hareket edebilmesi iin deltax ve deltay uzunluklar yle olmald r.

a y x

O halde topun hareketi iin balangta bir alfa as ve a deeri tespit edililir. Sonra timer belirli bir periyoda kurulur. Her timer mesaj geldiinde top deltax, deltay miktar kadar hareket ettirilir. ekil dey ya da yatay engelle karlatnda a deitirilir. Yatay arpmalarda a negatif deere ekilmelidir.

D ey arp malarda a pi-a biimine gelmektedir(radyan cinsinden(2piRadyan 360 dr))

159

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace ReflectingBall { public partial class Form1 : Form { private Rectangle m_ball; private const int DefMoveUnit = 10; private const int Radius = 20; private double m_angle; public Form1() { InitializeComponent(); this.DoubleBuffered = true; m_angle = Math.PI / 6; m_ball = new Rectangle(this.ClientSize.Width / 2 - Radius, this.ClientSize.Height / 2 Radius, 2 * Radius, 2 * Radius);

timer1.Start(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.FillEllipse(Brushes.Purple, m_ball); 160

} private void timer1_Tick(object sender, EventArgs e) { this.Invalidate(m_ball); double deltaX = Math.Cos(m_angle) * DefMoveUnit; double deltaY = Math.Sin(m_angle) * DefMoveUnit; m_ball.Offset((int) deltaX, (int) deltaY); this.Invalidate(m_ball); } } } Form1 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class Form1 : Form { private ReflectingBall m_rb1; private ReflectingBall m_rb2; private ReflectingBall m_rb3; public Form1() { InitializeComponent(); this.DoubleBuffered = true; m_rb1 = new ReflectingBall(100, 100, this.ClientRectangle); m_rb1.Radius = 20; m_rb1.Angle = Math.PI / 6; m_rb1.Color = Color.Blue; m_rb1.Speed = 1; m_rb1.Move += new BallEventHandler(m_rb_Move); m_rb1.Start(); m_rb2 = new ReflectingBall(200, 100, this.ClientRectangle); m_rb2.Radius = 10; m_rb2.Angle = -Math.PI / 6; m_rb2.Color = Color.Red; m_rb2.Speed = 80; m_rb2.Move += new BallEventHandler(m_rb_Move); m_rb2.Start(); 161

m_rb3 = new ReflectingBall(200, 200, this.ClientRectangle); m_rb3.Radius = 10; m_rb3.Angle = -Math.PI / 6; m_rb3.Color = Color.Purple; m_rb3.Speed = 50; m_rb3.Move += new BallEventHandler(m_rb_Move); m_rb3.Start(); } void m_rb_Move(object o, BallEventArgs bea) { this.Invalidate(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; m_rb1.Draw(g); m_rb2.Draw(g); m_rb3.Draw(g); } private void Form1_Resize(object sender, EventArgs e) { m_rb1.Frame = this.ClientRectangle; m_rb2.Frame = this.ClientRectangle; m_rb3.Frame = this.ClientRectangle; } private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) StopBalls(); else if (e.Button == MouseButtons.Left) StartBalls(); } private void StartBalls() { foreach (ReflectingBall rb in ReflectingBall.Balls) rb.Start(); } private void StopBalls() { foreach (ReflectingBall rb in ReflectingBall.Balls) rb.Stop(); } } } 162

Ball.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Windows.Forms; namespace CSD { class BallEventArgs : EventArgs { private int m_x; private int m_y; public BallEventArgs(int x, int y) { m_x = x; m_y = y; } public int X { get { return m_x; } } public int Y { get { return m_y; } } } delegate void BallEventHandler(object o, BallEventArgs bea); class ReflectingBall { private Rectangle m_frame; private int m_centerX, m_centerY; private Color m_color; private int m_speed; private int m_radius; private double m_angle; private Timer m_timer; private Brush m_brush; private const int DefMoveUnit = 5; private static List<ReflectingBall> ms_balls; public event BallEventHandler Move; static ReflectingBall() { 163

ms_balls = new List<ReflectingBall>(); } public ReflectingBall(int centerX, int centerY, Rectangle frame) { m_centerX = centerX; m_centerY = centerY; m_frame = frame; m_color = Color.Red; m_brush = new SolidBrush(m_color); m_speed = 50; m_radius = 10; m_angle = Math.PI / 6; m_timer = new Timer(); m_timer.Interval = 1000 / m_speed; m_timer.Tick += new EventHandler(defaultTimerProc); ms_balls.Add(this); } public static List<ReflectingBall> Balls { get { return ms_balls; } } public Rectangle Frame { get { return m_frame; } set { m_frame = value; } } public Point Center { get { return new Point(m_centerX, m_centerY); } set { m_centerX = value.X; m_centerY = value.Y; } } private void defaultTimerProc(object o, EventArgs e) { this.Move(this, new BallEventArgs(m_centerX, m_centerY)); } public void Draw(Graphics g) { if (m_centerX + m_radius > m_frame.Right || m_centerX - m_radius < m_frame.Left) m_angle = Math.PI - m_angle; if (m_centerY + m_radius > m_frame.Bottom || 164

m_centerY - m_radius < m_frame.Top) m_angle = -m_angle; double deltaX = Math.Cos(m_angle) * DefMoveUnit; double deltaY = Math.Sin(m_angle) * DefMoveUnit; m_centerX += (int)deltaX; m_centerY += (int)deltaY; g.FillEllipse(m_brush, m_centerX - m_radius, m_centerY - m_radius, m_radius * 2, m_radius * 2); } public void Start() { m_timer.Start(); } public void Stop() { m_timer.Stop(); } public Color Color { get { return m_color; } set { m_color = value; m_brush = new SolidBrush(m_color); } } public int Speed { get { return m_speed; } set { m_speed = value; m_timer.Interval = 1000 / m_speed; } } public int Radius { get { return m_radius; } set { m_radius = value; } } public double Angle { get { return m_angle; } 165

set { m_angle = value; } } } } Komut Satr Argmanlar: Komut satrndan program altrrken programn isminin yanna yazlan yazlara komut satr argmanlar denilmektedir. rnein. Test.exe ali veli selami: Burada programn ismi test.exe dir. Ali veli selami komur satr argmanlard r. C# standartlarna gre main fonksiyonunun parametrik yaps aadakilerden biri biiminde olabilir. static void Main() {...} static void Main (string[] args ){...} static int Main (){...} static int Main (string[] args ){...} Grld gibi Main fonksiyonun geri dn deeri void ya da int olabilir. Parametresi olmayabilir ya da String dizisi olabilir. String dizisinin ilk eleman program isminden sonraki ilk komut satr argmann belirtir. Programc isterse tm komut satr argmanlarn tek bir yz biiminde de alabilir. Bunun iin Environment snfnn String trnden static CommentLine property si kullanlabilir. Bu property bize program ismi ile birlikte bize tm komut satrn tek bir string olarak vermektedir. Ayrca Environment snfnn GetCommentLneArgs isimli static fonksiyonu bize program ismi de dahil olmak zere komut satr argmanlarn bize bir string dizisi olarak vermektedir. Komut satr argmanlar ayrca proje propertylerinde debug sekmesinde IDE den de girilebilir. System.Environment Snf: Bu snf static bir snftr yani hep static elemanlardan olumaktadr. Bu snfta hem almakta olan uygulamaya ynelik hm de baz sisteme ynelik ilemler yapan elemanlar bulunmaktadr. Snfn faydal tipik elemanlar unlardr. Yukarda sylenildii gibi komut satr argmanlarn alan property ve fonksiyonlar vardr. Prosesin evredeikenlerini get eden ve set eden fonksiyonlar vardr. Gerek konsol gerekse GUI uygulamalar nda program sonland rmak iin Exit fonksiyonu kullanlabilir. Sistemdeki tm srclerin listesi GetLogicalDrives fonksiyonuyla elde edilebilir. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; namespace ConsoleApp { class Program { public static int Main() 166

{ foreach (string s in Environment.GetLogicalDrives()) Console.WriteLine(s); return 0; } } }

S nfn CurrentDirectory isimli property eleman prosesin aktif alma dizinini alp set etmekte kullan lr.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; namespace ConsoleApp { class Program { public static int Main() { string cmd; for (; ; ) { Console.Write("{0}>", Environment.CurrentDirectory); cmd = Console.ReadLine(); } return 0; } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; namespace ConsoleApp { class Program { public static int Main() { string cmd; 167

string [] cmdParams; for (; ; ) { Console.Write("{0}>", Environment.CurrentDirectory); cmd = Console.ReadLine(); cmdParams = cmd.Split(' ', '\t'); if (cmdParams.Length == 0) continue; switch (cmdParams[0]) { case "cd": try { Environment.CurrentDirectory = cmdParams[1]; } catch (DirectoryNotFoundException e) { Console.WriteLine("System cannot find specified directory.\n"); } break; case "exit": goto EXIT; } } EXIT: return 0; } } }

Adaki bilgisayar ismi MachineName propertysi ile elde edilebilir. Snfn dier elemanlar MSDN dkmanlarndan izlenmelidir.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; namespace ConsoleApp { class Program { public static int Main() { string cmd; string [] cmdParams; 168

for (; ; ) { Console.Write("{0}>", Environment.CurrentDirectory); cmd = Console.ReadLine(); cmdParams = cmd.Split(' ', '\t'); if (cmdParams.Length == 0) continue; switch (cmdParams[0]) { case "cd": try { Environment.CurrentDirectory = cmdParams[1]; } catch (DirectoryNotFoundException e) { Console.WriteLine("System cannot find specified directory.\n"); } break; case "exit": goto EXIT; } } EXIT: Console.WriteLine("Processor Count: {0}", Environment.ProcessorCount); return 0; } } } Programn Sonlandrlmas: Bir C# programnn sonland rlmas iin birka yntem kullanlabilir. 1. Uygulama ister Console isterse GUI olsun Environment.Exit fonksiyonu sonlandrmada kullanlabilir. Ancak GUI uygulamalar nn bu fonksiyonla sonland rlmas tavsiye edilen bir durum deildir. nk bu program arka planda ExitProces API fonksiyonunu armaktad r. k veya sonland rma ilemi ani bir biimde mesaj dngs dikkate alnmadan yaplr. 2. Anmsanaca gibi programn normal sonlanmas anapencerenin kapatlmas nedeniyle Appilication.Run fonksiyonundan klmas ve Main fonksiyonunun bitmesiyle olmaktadr. O halde ana k programn anapenceresini kapatmaya allarak yap lan ktr. Bu yolla yine FormClosing mesaj oluturulur ve k duruma gre yine engellenebilir. 3. Prosesin sonlandrlmas ayrca Appilication snfnn Exit fonksiyonuyla da yaplabilir. Aslnda bu yntem ikinci yntemi kapsamaktadr. Ancak bu fonksiyon arld nda her ana pencere iin Form Closing mesaj gnderilir. Ayn zamanda her thread ayn yntemle sonlandrlmaktad r. Bu yntem programn ok fazla ana penceresi varsa ve programmz zellikle GUI threadler ieriyorsa tavsiye edilebilir. Anahtar Notlar: Microsoftun Framework SDK s iinde aa seviyeli iki nemli ara ilasm.exe ve ildasm.exe programlardr. lasm program sembolik Makine dilinde yazlm olan programlar arakoda dntrr. ldasm ise bunun tam tersini yapar. 169

lasm ve idasm programlarnn dnda ayrca sdk iinde bulunmayan Decompiler programlarda mevcuttur. Decompiler programlar arakod ieren exe. Ya da dll dosyalarn C# kaynak kaduna dntrebilmektedir. En ok kullanlan Decompiler programlar Salamander ve Dis# programlard r. Process Kavram: Program kavram daha ok programn kaynak kodunu ya da altrlabilir dosyay belirtmektedir. Bir program altrldnda artk ona process denir. letim sistemi prgram altrd nda yani onu process haline getirdiinde eitli tablolar kurarak almakta olan program izlemektedir. letim sistemi dzeyinde proces gibi eitli kaynaklarn ynetimi iin System.Diagnostics isim alan iindeki snflar kullanlmaktadr. letim sistemi dzeyinde almakta olan programlar process snfyla temsil edilmektedir. Process snf trnden bir nesne almakta olan bir programn bilgilerini iermektedir. Process snfnn static GetProcesses isimli fonksiyonu o anda almakta olan tm programlara ilikin bilgileri Process snf trnden bir diziye yerletirir ve o diziyi verir. public static Process[] GetProcesses() Process snfnn ProcessName isimli property eleman almakta olan programn ismini elde etmek iin kullanlr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; namespace ProcessSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { foreach (Process p in Process.GetProcesses()) listBox1.Items.Add(p.ProcessName); } } } Anahtar Notlar: .net iin usenet haber guruplar microsoft.public.dotnet dizininin altndaki guruplard r. Process snfnn pek ok faydal fonksiyonu ve eleman vardr. rnein Process.CloseMainWindow isimli fonksiyon process bir GUI programna ilikinse onun anapenceresini kapatmaya alr. 170

CloseMainWindow fonksiyonu programn ana penceresine WM_CLOSE mesaj gndermektedir. Yani yaratlan etki tamamen sanki form snfnn Close fonksiyonunun arlmas gibi olmaktadr. Bir GUI programnn d ardan sonlandrlmasna ilikin en doal yntem nce onun mesaj dngs yoluyla normal bir biimde sonlandrlmasna almaktr. Anmsanaca gibi bu ilem CloseMainWindow fonksiyonuyla gerekletirilebilir. Daha nceden de belirtildii gibi bu mesajn gnderilmesi adeta anpencerenin arp dmesine tklanmas etkisi yaratmaktadr. Bu ilem sonucunda eer program sonlanmazsa artk gerekten biz killfonksiyonunu ararak vzorla sonlandrma yapabiliriz. phesiz kill fonksiyonu ancak yetkili olduumuz prosesleri sonlandrabilir. Prosesin sonlanm olup olmad bool trden HasExited property si ile belirlenebilir. Windows un kendisinin yapt gibi genel eilim Close ileminden sonra 5 saniye civarnda beklemektir. Bu bekleme ilemi WaitForExit fonksiyonlaryla yaplabilir. public bool WaitForExit(int milliseconds) fonksiyon ilgili proses sonlanana kadar ya da en fazla parametresiyle belirtilen milisaniye kadar aran thread i bloke eder. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; namespace ProcessSample { public partial class Form1 : Form { private Process[] m_processes; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { listBox1.Items.Clear(); m_processes = Process.GetProcesses(); foreach (Process p in m_processes) listBox1.Items.Add(p.ProcessName);

} private void listBox1_DoubleClick(object sender, EventArgs e) { Process p = m_processes[listBox1.SelectedIndex]; 171

try { p.CloseMainWindow(); if (!p.WaitForExit(5000)) { p.Kill(); } button1_Click(null, null); } catch (Exception ex) { MessageBox.Show(ex.Message); }

} } } Process snf yalnzca alan prosesleri kontrol etmekte deil ayn zamanda yeni proses oluturmakta yani yeni program altrmakta da kullanlabilir. Bir program altrabilmek iin yap lacak ey static Start fonksiyonunu armaktr. Pekok start fonksiyonu vardr. En tipik olan aadakidir. public static ;Process Start(string FileName) Fonksiyon parametre olarak bir dosya ismi istemektedir. Dosya olarak .exe dosya verilebilir ya da ilikilendirilmi bir dosya verilebilir. rnein biz parametre olarak .doc uzantl bir dosya verirsek Start fonksiyonu word programn altrp bu dosyay aacaktr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; namespace ProcessStart { public partial class Form1 : Form { private Process m_proc; public Form1() { InitializeComponent(); 172

} private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { try { m_proc = Process.Start(ofd.FileName); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } } static Start fonksiyonu yerine static olmayan Start fonksiyonu da kullanlabilir. Fakat bunun iin dosya isminin ProcessName elemanna girilmesi gerekmektedir. Dier bir start fonksiyonu 2 parametre alan fonksiyondur. public static Process Start(string fileName, string arguments) public static Process Start(processStartInfo, startInfo) En geni Start fonksiyonu phesiz process Start info parametreli fonksiyondur. ProcessStartInfo snf eitli belirlemeleri set etmek iin kullanlan pek ok elemana sahiptir. Yani programc bu snf trnden nesnenin iini doldurur. Onu Start programna parametre olarak geer. ProcessStartInfo snfnn CreateNoWindow isimli property eleman Console uygulamalarnda Console penceresinin almamasn salamaktadr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.IO; namespace BasicIDE { public partial class Form1 : Form { public Form1() { InitializeComponent(); 173

} private void compileToolStripMenuItem_Click(object sender, EventArgs e) { saveToolStripMenuItem_Click(null, null); try { ProcessStartInfo psi = new ProcessStartInfo( @"C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe", "test.cs"); psi.CreateNoWindow = true; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void saveToolStripMenuItem_Click(object sender, EventArgs e) { try { File.WriteAllText("test.cs", textBox1.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } Bir Console programn altrp onun ekrana yazd klarn elde etmek iin srasyla u ilemler yap lmald r: 1. ProcessStartInfo trnden bir snf nesnesi yaratlr. altrlacak programn ismi fileName property sinne ve komut satr argmanlar arguments propertysine girilir. Fakat zaten bu iki deeri set eden iki parametreli bir balang fonksiyonu da vardr. 2. ProcessStartInfo nesnesinin CreatNoWindow propertysi false olarak girilir. Ayrca yine snfn UseShellExecute propertysine false girilir. 3. imdi stdout dosyasnn ynlendireleceini belirtmek iin RedirectStandartOutput property si true yap lmaldr. 4. Process snfnn standartOutputisimli property eleman bize bir StreamReader nesnesi verir. Biz bu StreamReader nesnesinden okuma yaptm zda aslnda altrdmz programn ekrana yazdrd bilgileri okumu olacaz.

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; 174

using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.IO; namespace BasicIDE { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void compileToolStripMenuItem_Click(object sender, EventArgs e) { saveToolStripMenuItem_Click(null, null); try { ProcessStartInfo psi = new ProcessStartInfo( @"C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe", "test.cs"); psi.CreateNoWindow = true; psi.UseShellExecute = false; psi.RedirectStandardOutput = true; Process p = Process.Start(psi); StreamReader sr = p.StandardOutput; textBox2.Text = ""; string str; while ((str = sr.ReadLine()) != null) { textBox2.Text += str + "\r\n"; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void saveToolStripMenuItem_Click(object sender, EventArgs e) { try 175

{ File.WriteAllText("test.cs", textBox1.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void runToolStripMenuItem_Click(object sender, EventArgs e) { try { Process.Start("test.exe"); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } /* class App { public static void Main() { System.Console.WriteLine("kjhkjhkjhkjhkj"); System.Console.ReadLine();asd } } */ Process in Modl Listesi: exe, dll gibi process alanna bamsz yklenebilen dosyalara modl denilmektedir. (Modl terimi sistem programlama terminolojisine ilikindir. .net teki assembly terimi tam olarak buradaki modl anlamna gelmemektedir.) te exe, dll gibi modller ProcessModule snfyla temsil edilmitir. ProcessModul snfnn FileName isimli property eleman modul dosyasnn tm yol ifadesiyle ModulName isimli property eleman bunun yalnzca ismini elde etmek iin kullanlr. Process snfnn Modules isimli property eleman bir Collection snf trndendir. Process in tm modllerini vermektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; 176

namespace ProcessSample { public partial class Form1 : Form { private Process[] m_processes; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { listBox1.Items.Clear(); m_processes = Process.GetProcesses(); foreach (Process p in m_processes) listBox1.Items.Add(p.ProcessName);

} private void listBox1_DoubleClick(object sender, EventArgs e) { Process p = m_processes[listBox1.SelectedIndex]; try { p.CloseMainWindow(); if (!p.WaitForExit(5000)) { p.Kill(); } button1_Click(null, null); } catch (Exception ex) { MessageBox.Show(ex.Message); }

} private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { listBox2.Items.Clear(); Process p = m_processes[listBox1.SelectedIndex]; foreach (ProcessModule pm in p.Modules) { listBox2.Items.Add(pm.ModuleName); 177

} } } } Thread lemleri: Multiprocessing iletim sistemlerinde izelgeleme ilemi zaman paylaml olarak yap lmaktadr. Yani iletim sistemi bir process i belirli bir sre altrr sonra onun almasna ara verir dierine geer ve bu biimde zaman paylaml bir alma sz konusudur.

t1 p1 t2 letim Sistemi t1 p2 t1 t2 Bir process in paral alma sresine quanta sresi denirWindows sistemlerinde tipik olarak 20ms, 60 ms, 120ms deerleri kullanlmaktadr. Bir programn bamsz olarak izelgelenen her farkl akna thread denilmektedir. rnein iki threadli bir process de bamsz iki ak sz konusu olabilir. Thread mekanizmasna sahip olan windows, Unix/Linux gibi sistemler thread temelinde izelgeleme uygulamaktadr. Yani her bir quanta sresi doldu unda bir thread in almasna arar verilir. Yeni bir threade geilir. Bylece bir process in threadleri sanki bamsz programlarm gibi birlikte alabilmektedir. Threadler Neden Kullanlr? 1. Threadler arkaplan olaylarn etkin bir biimde izlenmesi iin kullanlabilir. rnein asl ak yoluna devamederken dier bir thread ak bir portu kontrol edebilir. ThreadConsole1 yerletir. 2. Threadler bizim toplamda daha fazla CPU zaman elde etmemizi salayabilir. rnein programmz Birka thread ile dzenlersek birim zamanda programmzn toptan altrd kod miktar fazlalar. 3. Threadler sayesinde paralel programlama yapabiliriz. Eer makinamzda birden fazla ilemci Ya da ilemci ekirdei varsa gerekten programmzn farkl aklar ayn anda alabilir. Bloke Kavram ve Threadlerin Bloke Edilmesi: Klavye, dosya, network ilemleri ve buna benzer ilemler uzun sre beklemeye yol amaktadr. te bu tr olaylarda iletim sistemi thread igeici olarak izelge dna kararak arka planda olay izlemektedir. Bylece dsal olay bekleyen thread bouna CPU zaman harcamaz. Arka plan olay gerekletiinde iletim sistemi bunu belirler ve thread i yenideen izelgeye koyar. te thread in bu biimde geici olarak izelge dna kart lmasna thread in bloke edilmesi diyoruz. Bylece aslnda sistemde yzlerce thread alyor olabildii halde bunlardan ok az gerekten izelgede aktif durumdadr. rnein bir thread dosyadan bir okuma yapacak olsun. Tipik olarak iletim sistemi thread i izelge dna kararak bekletir. Bu srada dier threadler altrlr. Disk ilemi gerekleip de okuma bitirilince thread yeniden izelgeye konulur ve Read fonksiyonu geri dner. Okuma ilemini yapmak isteyen thread 178 t2

p3

iin yine bir deiiklik yoktur. O yine beklemektedir. GUI programlama modelinde anmsanaca gibi bir GUI uygulamas yaamn Application.Run fonksiyonunda yani mesaj dngsnde geirir. te Application.Run fonksiyonu eer mesaj kuyruunda mesaj bulamazsa yani kuyruk bo sa blokeye yol amaktadr. Bylece bir pencereye hi mesaj gitmiyorsa muhtemelen pencereye ilikin threadde CPU zaman harcamyor durumdad r. Bir thread in yaam dngs yledir. Yaratm Run Wait Ready .nette Thread lemleri: Thread ilemleri System.Threading isimalanndaki snflarla gerekletirilmektedir. Thread kavram Thread snfyla temsil edilmitir. Thread nesnesi aadaki balang fonksiyonuyla yaratlabilir. public Thread(ParameterizedThreadStart start) ParameterizedThreadStart yle bir delegedir. public delegate void ParameterizedThreadStart(Object obj) Grld gibi Thread fonksiyonu olacak fonksiyonun geri dn deeri void paramtresi object trnden olmald r. Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); Burada ThreadProc fonksiyonunun geri dn deeri void parametresi object trden olmaldr. Bu fonksiyon thread aknn balatlaca fonksiyondur. Aslnda Framework 2.0 dan nce maalesef aadaki biimde olan balang fonksiyonu kullanlmaktayd : public Thread(ThreadStart start) ThreadStart isimli delege yledir: public delegate ThreadStart() Bir thread nesnesi yaratld nda thread yaratlr fakat henz alm yor durumdad r. Thread in almas Start fonksiyonlaryla salanr. ki Start fonksiyonu vardr: public void Start(Onject parameter) Bu fonksiyon eer thread parameterizedThreadStart delegesi ile yaratlm sa kullanlr. Aadaki ise ThreadStart delegesi ile yaratlm sa kullanlr. public void Start () Bu durumda aadaki gibi yaratlp arlabilir: Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); t.Start(obj); Threadlerin stack leri tamamen birbirinden ayrlmtr. Yani her thread yerel deikenlerin kendine zg bir kopyasn kullanr. Bylece farkl iki thread ayn fonksiyon zerinde ilerlerken aslnda yerel deikenlerin farkl kopyalarn kullanyor durumdad r.

using System; using System.Threading; 179

namespace CSD { class App { public static void Main() { Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); t.Start(null); Foo("Main thread"); } private static void ThreadProc(object o) { Foo("Other thread"); } private static void Foo(string s) { for (int i = 0; i < 10; ++i) { Console.WriteLine("{0}: {1}", s, i); Thread.Sleep(1000); } } } } Ancak snfn statik veri elemanlarnn toplam bir kopyas vard r ve her thread ayn kopya zerinde alr. Benzer biimde Heap alan da ortak paylalmaktad r. using System; using System.Threading; namespace CSD { class App { private static Thread [] m_threads; public static void Main() { m_threads = new Thread[10]; for (int i = 0; i < 3; ++i) { m_threads[i] = new Thread(new ParameterizedThreadStart(ThreadProc)); m_threads[i].Start(i); }

180

Console.ReadLine(); } private static void ThreadProc(object o) { for (int i = 0; ; ++i) { Console.WriteLine("{0}.Thread: {1}", o.ToString(), i); Thread.Sleep(1000); } }

} } Anahtar Notlar: Sistemde hanggi proseslerin bulunduunu o proseslerin hangi threadlere sahip olduunu spy ++ program ile renebiliriz. Threadlerin Sonlanmas: Threadlerin birka biimde sonlanabilir. 1. Thread fonksiyonu sonland nda thread de otomatik sonlanr. 2. Herhangi bir thread alrken thread snfnn Abort fonksiyonuyla sonland rlabilir. Aslnda Abort fonksiyonu thread zerinde ThreadAbortException isimli bir Exception oluturur. Bu Exception ele alnmasd iin bu thread sonlandrlmaktad r. usinng System; using System.Threading; namespace CSD { class App { private static Thread [] m_threads; public static void Main() { m_threads = new Thread[10]; for (int i = 0; i < 3; ++i) { m_threads[i] = new Thread(new ParameterizedThreadStart(ThreadProc)); m_threads[i].Start(i);

} Console.ReadLine(); m_threads[2].Abort(); Console.ReadLine(); } 181

private static void ThreadProc(object o) { for (int i = 0; i < 10; ++i) { try { Console.WriteLine("{0}.Thread: {1}", o.ToString(), i); Thread.Sleep(1000); } catch (Exception e) { Console.WriteLine(e); }

} }

} } 3. Abort fonksiyonu uygulandnda thread zerinde ThreadAbortException isimli Exception oluur. Bu Exception try catch blou ile yakalanabilir eer catch blounda ResertAbort isimli fonksiyon arlmazsa catch blounun sonunda otomatik yeniden throw ilemi yap lr. Bylece thread yine sonlandrlm olur. Eer Abort ilemine kar threadimizin sonlandrlmasn istemiyorsak static ResertAbort fonksiyonu arlmaldr. using System; using System.Threading; namespace CSD { class App { private static Thread [] m_threads; public static void Main() { m_threads = new Thread[10]; for (int i = 0; i < 3; ++i) { m_threads[i] = new Thread(new ParameterizedThreadStart(ThreadProc)); m_threads[i].Start(i);

182

Console.ReadLine(); m_threads[2].Abort(); Console.ReadLine(); } private static void ThreadProc(object o) { for (int i = 0; i < 10; ++i) { try { Console.WriteLine("{0}.Thread: {1}", o.ToString(), i); Thread.Sleep(1000); } catch (Exception e) { Console.WriteLine(e); Thread.ResetAbort(); }

} }

} } 4. Threadler nplan(forground) ve arkaplan(background) olmak zere ikiye ayrlr. Threadin nplan Ya da arkaplan olmasnnn tek etkisi sonlanma ksmnda ortaya kmaktad r. Prosesin son nplan threadi sonlandnda tm arkaplan threadlerde otomatik olarak sonlandrlr. Bylece proses sonlandrlm olur. Thread yaratldnda default olarak nplan d r. Ana threadde nplandr. using System; using System.Threading; namespace CSD { class App { private static Thread [] m_threads; public static void Main() { m_threads = new Thread[10]; for (int i = 0; i < 3; ++i) { m_threads[i] = new Thread(new ParameterizedThreadStart(ThreadProc)); 183

m_threads[i].Start(i); m_threads[i].IsBackground = true; } } private static void ThreadProc(object o) { for (int i = 0; i < 10; ++i) { try { Console.WriteLine("{0}.Thread: {1}", o.ToString(), i); Thread.Sleep(1000); } catch (Exception e) { Console.WriteLine(e); Thread.ResetAbort(); }

} }

} } Ana threadin dier threadlerden hibir fark yoktur. Yani ana thread sonland halde dier threadler almaya devam ediyor olabilir. Prosesin son threadi de sonlandnda program otomatik olarak sonlanr. Threadlerin stackleri tamemen ayrlm olmasna karn heap alan ortak kullanlmaktadr. Bu nedenle snfn ortak veri elemann ortaklaa bir biimde kullanabilmektedirler. Threadlerin Sonlanmasnn Beklenmesi: Thread snfnn Join isimli fonksiyonlar bir thread sonlanana kadar fonksiyonu aran thread i bekletmektedir. Parametresiz Join fonksiyonu thread sonlanana kadar bekleme yapar. Int parametreleri Join fonksiyonu ve TimeSpan parametreli join fonksiyonu belli bir zamanam parametresi de almaktadr. using System; using System.Threading; namespace CSD { class App { private static Thread m_thread; public static void Main() { 184

m_thread = new Thread(new ParameterizedThreadStart(ThreadProc)); m_thread.Start("other thread"); m_thread.IsBackground = true; m_thread.Join(); Console.WriteLine("ends..."); } private static void ThreadProc(object o) { for (int i = 0; i < 10; ++i) { Console.WriteLine("{0}.Thread: {1}", o.ToString(), i); Thread.Sleep(1000); } }

} } GUI ve Worker Threadler: Microsoft threadleri GUI ve Worker Threadler olmak zere ikiye ayrmaktad r. Eer bir threadde en az bir pencere yaratlmsa bu tr threadlere GUI thread denilmektedir. Eer Threadde hibir pencere yaratlmamsa bunlara worker threadler denir. Windows sistemlerinde her thread iin ayr bir mesaj kuyruu olu turuldu u iin yeni bir pencere yaratldnda o threadde yeniden mesaj dngsne girmek gerekir. Yani yeni yaratlan threadde Appilication.Run fonksiyonunun arlmas gerekir. Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace GUIThread { public partial class Form1 : Form { private Thread m_thread; public Form1() { InitializeComponent(); }

185

private void button2_Click(object sender, EventArgs e) { for (long i = 0; i < 10000000000; ++i) ; } private void button1_Click(object sender, EventArgs e) { m_thread = new Thread(new ParameterizedThreadStart(ThreadProc)); m_thread.Start(); } private void ThreadProc(object o) { Form2 f = new Form2(); Application.Run(f);

} } } Form2.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace GUIThread { public partial class Form2 : Form { public Form2() { InitializeComponent(); } } } Bu durumda rnein bir GUI thread tipik olarak yle olu turulmaldr. private void ThreadProc(object o) { Application.Run(new myForm()); } Grld gibi bu thread kodu tamemen main fonksiyonunda olduu gibidir. 186

.nette pekok snf kendi iinde zaten bir thread amaktadr. rnein System.Threading isim alanndaki Timer snf kendi iinde bir thread aar ve delege fonksiyonunu bu threadle arr. Buna benzer bir timer snf yle yazlabilir. ThreadSample2 Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace ThreadSample { public partial class Form1 : Form { private Thread m_thread; private bool m_bFlag; private CSD.Timer m_timer; private int m_i; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { m_timer = new CSD.Timer(1000); m_timer.Start(null); m_timer.Tick += new CSD.TimerProc(m_timer_Tick); } void m_timer_Tick(object o) { label1.Text = m_i.ToString(); ++m_i; } } } Timer.cs using System; using System.Collections.Generic; 187

using System.Linq; using System.Text; using System.Threading; namespace CSD { delegate void TimerProc(object o); class Timer : IDisposable { private Thread m_thread; private int m_period; public event TimerProc Tick; public Timer(int period) { m_period = period; m_thread = new Thread(new ParameterizedThreadStart(timerThreadProc)); m_thread.IsBackground = true; } public void Start(object o) { m_thread.Start(o); } public void Resume() { m_thread.Resume(); } public void Suspend(object o) { m_thread.Suspend(); } public void Dispose() { m_thread.Abort(); } private void timerThreadProc(object o) { for (; ; ) { Thread.Sleep(m_period); Tick(o); } } } 188

} ThreadSample3 Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace ThreadSample { public partial class Form1 : Form { private Thread m_thread; private bool m_bFlag; private CSD.Timer m_timer; private int m_i; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { m_timer = new CSD.Timer(1000); m_timer.Start(null); m_timer.Tick += new CSD.TimerProc(m_timer_Tick); } void m_timer_Tick(object o) { label1.Text = m_i.ToString(); ++m_i; } } } Timer.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;

189

namespace CSD { delegate void TimerProc(object o); class Timer : IDisposable { private Thread m_thread; private int m_period; public event TimerProc Tick; public Timer(int period) { m_period = period; m_thread = new Thread(new ParameterizedThreadStart(timerThreadProc)); m_thread.IsBackground = true; } ~Timer() { m_thread.Abort(); GC.SuppressFinalize(this); } public void Start(object o) { m_thread.Start(o); } public void Resume() { m_thread.Resume(); } public void Suspend(object o) { m_thread.Suspend(); } public void Dispose() { m_thread.Abort(); } private void timerThreadProc(object o) { for (; ; ) { Thread.Sleep(m_period); Tick(o); } 190

} } } Threadlerin Senkronizasyonu: Threadler konusunun nemli bir blmn thread senkronizasyonu iermektedir. Birden fazla thread ortak bir ama iin alrken kimi zaman birbirlerini beklemeleri gerekir. Kritik Kod Bloklarnn Oluturulmas: Threadlerin almasna ara verilmesi preemptive bir biimde gerekletirilmektedir. Bir thread henz kmadan baka bir threadin girmemesi gerekn kod bloklarna kritik kod bloklar denilmektedir. Kritik kod bloklar zellikle ortak kaynaklara eriilirken dikkat edilmesi gerekn bir konudur. rnein iki thread ortak bir ArrayList te eleman insert ediyor olsun bir thread ilemini bitirmeden arada kesilirse dier threadin obr thread kana kadar onu beklemesi gerekir. Kritik kodlarn manuel bir biimde oluturulmas mmkn deildir. Bunlar iin zel fonksiyonlar kullanlmaktadr. rnein aadaki manuel flag yntemi garanti bir yntem deildir. flag = false; while(flag) ; //Kod burada kesilirse ne olu? flag = true; ... // Kritik kod flag = false; Kritik kod oluturmak iin Monitor snfnn Enter ve Exit fonksiyonlar kullanlmaktadr. Monitor.Enter(...); ... //Kritik kod

Monitor.Exit(...); Critical Section1 yerletir. Monitor sisteminde threadlerden biri Monitor.Enter fonksiyonundan girdiindehenz kritik koddan kmadan dier bir thread kritik koda girmeye alrsa Enter fonksiyonunun ierisinde blokeye yol aar. Kritik kodun iindeki thread Exit fonksiyonunu grdnde Enter dolaysyla bakleyen thread ieriye girer. Kritik kod rnei gerekliliini anlatan rnek: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Collections; 191

namespace CriticalSection { class Program { private static Random m_rand; static void Main(string[] args) { m_rand = new Random(); Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); t.Start(null); for (int i = 0; i < 10; ++i) Test(); t.Join();

} public static void ThreadProc(object o) { for (int i = 0; i < 10; ++i) Test(); } public static void Test() { Monitor.Enter(m_rand); Console.WriteLine("-------"); Console.WriteLine("1. Adm"); Thread.Sleep(m_rand.Next(100)); Console.WriteLine("2. Adm"); Thread.Sleep(m_rand.Next(100)); Console.WriteLine("3. Adm"); Thread.Sleep(m_rand.Next(100)); Console.WriteLine("4. Adm"); Thread.Sleep(m_rand.Next(100)); Console.WriteLine("5. Adm"); Thread.Sleep(m_rand.Next(100)); Console.WriteLine("-------"); Monitor.Exit(m_rand); } } } Eer birden fazla thread Enter fonksiyonu dolaysyla kritik koda girmeden bekliyorsa kritik kod iindeki thread kritik koddan ktnda bekleyen hangi threadin girecei konusunda garanti bir 192

belirleme yoktur. Fakat adil bir sistem uygulanmaktadr. Enter ve Exit fonksiyonlar object trnden parametre almaktad r. Fonksiyonlarn object parametresi kritik kodu betimlemektedir. rnein kodumuzda iki farkl yerde Monitor.Enter ve Monitor.Exit ile oluturulmu kritik kod olsun. Threadlerden biri bunlardan birine girmise dierinin dierine girebilmesi istenebilir. nk bunlar farkl konulara ilikin kritik kodlar olabilir. te biz Enter fonksiyonuna ayn object deerini verirsek ayn konuya ilikin kritik kod oluturmu oluruz. Bu durumda bir thread bir kritik koda girdiinde dieri de dierine giremez. Kritik kod iinde bir exception oluursa ak baka bir blgeye atlar. te karken kilidi amak gerekebilir. Bu nedenle Exit ileminin Finally blounda yap lmas ygun olur. try { Monitor.Enter(o);

.... Kritik Kod

} finally { Monitor.Exit(o); } Monitor.Enter ve Exit ilemini yapan C# da Lock deyimi vardr. Lock deyiminin genel biimi yledir. lock(<ifade>) <deyim> Lock deyimi tamamen aadaki ile edeerdir. Monitor.Enter(<ifade>) try { <deyim> } finally { Monitor.Exit(<ifade>); } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Collections; namespace CriticalSection 193

{ class Program { private static ArrayList m_al; private static Random m_rand; static void Main(string[] args) { m_rand = new Random(); m_al = new ArrayList(); Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); t.Start(null); for (int i = 0; i < 10000; ++i) { lock (m_al) { m_al.Insert(0, i); } } t.Join(); Console.WriteLine("Ok = {0}", m_al.Count);

} public static void ThreadProc(object o) { for (int i = 0; i < 10000; ++i) { lock (m_al) { m_al.Insert(0, i); } } }

} }

Kernel Senkronizasyon Nesneleri ile Thread Senkronizosyonu: Event, Mutex, Semaphore gibi Senkronizsayon nesnelerine windows da kernel senkronizasyon nesneleri denilmektedir. Tm senkronizasyon nesnelerine ilikin snflar WaitHandle isimli snftan tremitir. WaitHandle abstract bir snftr. Bu snftan EventWaitHandle, Mutex ve Semaphore snflar tretilmitir. WaitHandle 194

EventWaitHandl e

Mutex

Semaphore

Her senkronizasyon nesnesinin ak (signaled) ve kapal(nonsingaled) olmak zere iki durumu vardr. WaitHandle snfnn WaitOne fonksiyonlar eer nesne aksa gei yapar kapalysa threadi bloke ederek izelge dna karr. Nesnelerin ak ya da kapal olma durumu ilgili nesneye gre belirlenmektedir. EventWaitHandle Nesnesi: EventWaitHandle nesnesi bir olay gerekleene kadar threadi blokede bekletmek iin kullanlr. Nesne aadaki balang fonksiyonu ile yaratlabilir. public EventWaitHandle( bool initialState, EventResetMode mode) Fonksiyonun birinci parametresi nesnenin balangtaki durumunu belirtir. True ise nesne ak False ise kapaldr. kinci parametre EventResetMode isimli Enum trndendir. AutoReset ve ManuelReset biiminde iki eleman vard r. Event nesnesi Manuel ise Wait fonksiyonlarna gei yap ld zaman Resetleme ilemi programcnn sorumlulu undadr. AutoReset durumunda ise gei yap ld nda nesne otomatik olarak kapal duruma geer. Event nesnesi tipik olarak yle kullanlr. 1. EventWaitHandle trnden bir nesne snfn veri eleman olarak bildirilir. Bylece her nesne eriebilir. Nesne iin banda kapal ve AutoReset biiminde yaratlabilir. 2. Bekleme yapmak isteyen thread Event nesnesi ile WaitOne fonksiyonunu arr. 3. Dier thread iini bitirince EventWaitHandle snfnn Set fonksiyonu arlr. Set fonksiyonu nesneyi ak duruma getirmektedir. Benzer biimde kapal duruma getirmek iinde Reset fonksiyonu vardr. Event AutoReset ise nesne otomatik olarak yeniden kapal duruma geer. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace EventSample { public partial class Form1 : Form { private Thread m_thread; private EventWaitHandle m_event; public Form1() { InitializeComponent();

195

m_event = new EventWaitHandle(false, EventResetMode.AutoReset); } private void button1_Click(object sender, EventArgs e) { m_thread = new Thread(new ParameterizedThreadStart(ThreadProc)); m_thread.Start(); } private void button2_Click(object sender, EventArgs e) { m_event.Set(); } private void ThreadProc(object o) { m_event.WaitOne(); MessageBox.Show("Ok"); } } } retici Tketici Problemi: retici tketici problemi gerek uygulamalarda ok sk karlalan tipik bir problemdir. Bu problemde bir retici ve bir de tketici thread vardr. retici thread bir faaliyet sonucunda bir deer elde eder ve bu deeri bir deikene yerletirir. Tketici threadde bu deeri alarak kullanr. retici thread tketici thread henz almadan yeni bir deeri yerletirmemeli tketici thread de retici thread yeni bir deeri koymadan ikinci kez almamaldr. retici Tketici probleminde karlan tipik sorun kodu: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace Producer_Consumer { public partial class Form1 : Form { private Thread m_producer; private Thread m_consumer; private Random m_rand; private int m_shared; 196

public Form1() { InitializeComponent(); m_rand = new Random(); m_producer = new Thread(new ParameterizedThreadStart(ProducerThreadProc)); m_producer.Start(null); m_producer.IsBackground = true; m_consumer = new Thread(new ParameterizedThreadStart(ConsumerThreadProc)); m_consumer.Start(null); m_consumer.IsBackground = true; } private void ProducerThreadProc(object o) { int i = 0; for (; ; ) { Thread.Sleep(m_rand.Next(200)); m_shared = i; if (i == 50) break; ++i; } } private void ConsumerThreadProc(object o) { for (; ; ) { Thread.Sleep(m_rand.Next(200)); listBox1.Items.Add(m_shared); if (m_shared == 50) break; } } } }

reticiTketici Probleminin EventWaitHandle Nesneleri ile zm: retici-tketici problemi Event nesneleri ile aadaki gibi tipik olarak zlebilir. EventWaitHandle m_producerEvent = new EventWaitHandle(false, EventResetMode AutoReset); EventWaitHandle m_consumerEvent = new EventWaitHandle(true, EventResetMode AutoReset); retici Tketici for(;;) for(;;) { { m_consumer m_producer 197 EventWaitOne(); EventWaitOne(); //get value //get value

Dzeltilmi program: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace Producer_Consumer { public partial class Form1 : Form { private Thread m_producer; private Thread m_consumer; private EventWaitHandle m_eventProducer; private EventWaitHandle m_eventConsumer; private Random m_rand; private int m_shared; public Form1() { InitializeComponent(); m_rand = new Random(); m_eventConsumer = new EventWaitHandle(true, EventResetMode.AutoReset); m_eventProducer = new EventWaitHandle(false, EventResetMode.AutoReset); m_producer = new Thread(new ParameterizedThreadStart(ProducerThreadProc)); m_producer.Start(null); m_producer.IsBackground = true; m_consumer = new Thread(new ParameterizedThreadStart(ConsumerThreadProc)); m_consumer.Start(null); m_consumer.IsBackground = true; }

198

private void ProducerThreadProc(object o) { int i = 0; for (; ; ) { m_eventConsumer.WaitOne(); Thread.Sleep(m_rand.Next(200)); m_shared = i; if (i == 50) break; ++i; m_eventProducer.Set(); } } private void ConsumerThreadProc(object o) { for (; ; ) { m_eventProducer.WaitOne(); Thread.Sleep(m_rand.Next(200)); listBox1.Items.Add(m_shared); if (m_shared == 50) break; m_eventConsumer.Set(); } } } } Semaphore Nesneleri: Semaphore nesneleri tipik olarak bir vkritik koda en fazla n tane threadin girmesini salamak iin kullanlmaktadr. Semaphore nesneleri sayaldr. Eer Semaphore sayac 0 dan bykse nesne ak durumda 0 a eitse kapal durumdad r. Semaphore ilemleri Semaphore snfyla temsil edilmitir. Tipik olarak balang fonksiyonu yledir. public Semaphore(int initialCount, int maximumCount) Fonksiyonun birinci parametresi semaphore sayacnn balang deeri, 2. parametresi maksimum deeridir. Semaphore sayac maksimum deerden daha fazla artmamaktadr. Semaphore nesnesi ile kritik kod yle olu turulur. m_sema.WaitOne(); //... .... Kritik Kod

m.sema.Release();

199

Wait fonksiyonlar kullanld nda eer semaphore sayac 0 dan bykse gei yaplr ve wait fonksiyonlar sayac otomatik olarak 1 drr. Realese fonksiyonu semaphore sayacn bir arttrmaktad r. Bylece yukarda kritik kod en fazla n kiinin girebilecei bir kodu belirtmektedir. retici Tketici Problemini Kuyruklu Versiyonu: retici tketici probleminin tekli versiyonunda bir retici bir tketici vardr ve ortada paylalan alan tek elemanlktr. Bu tr sistemler retici ve tketici bakm ndan ok fazla beklemeye yol amaktad r. Halbuki ortadaki paylalan n elemanl olsa toplam bekleme zaman daha az olur. Ancak kuyruk tam dolu oldu unda Ya da tam bo olduunda bekleme gerekleir. retici tketici probleminin bu tr n li zm iin tipik olarak iki semaphore kullanlr. Balangta tketici semaphor u n de retici semaphore u sfrdad r. retici thread tketici semaphore nu kullanarak tketici threadde retici semaphore nu kullarak bekleme yapar.

Semaphore m_semaProducer = new Semaphore(0, 10); Semaphore m_semaConcumer = new Semaphore(10, 10); retici for(;;) { m_semaconsumer.WaitOne(); //kuyru a ekle m_semaproducer.Release(); }

Tketici for(;;) { m_semaproducer.WaitOne(); //kuyruktan al m_semaConsumer.Release(); }

phesiz burada kullanlan kuyruk sistemininde ayrca korunmas gerekir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.Collections; namespace Producer_Consumer { public partial class Form1 : Form { private Thread m_producer; private Thread m_consumer; private Semaphore m_semaProducer; private Semaphore m_semaConsumer; 200

private Random m_rand; private Queue m_queue; public Form1() { InitializeComponent(); m_rand = new Random(); m_queue = new Queue(); m_semaConsumer = new Semaphore(10, 10); m_semaProducer = new Semaphore(0, 10); m_producer = new Thread(new ParameterizedThreadStart(ProducerThreadProc)); m_producer.Start(null); m_producer.IsBackground = true; m_consumer = new Thread(new ParameterizedThreadStart(ConsumerThreadProc)); m_consumer.Start(null); m_consumer.IsBackground = true; } private void ProducerThreadProc(object o) { int i = 0; for (; ; ) { m_semaConsumer.WaitOne(); Thread.Sleep(m_rand.Next(200)); lock (m_queue) { m_queue.Enqueue(i); } if (i == 50) break; ++i; m_semaProducer.Release(); } } private void ConsumerThreadProc(object o) { int val; for (; ; ) { m_semaProducer.WaitOne(); Thread.Sleep(m_rand.Next(200)); lock (m_queue) 201

{ val = (int)m_queue.Dequeue(); } if (val == 50) break; listBox1.Items.Add(val); m_semaConsumer.Release(); } } } } Mutex Nesnelerinin Kullanm: Neredeyse tm iletim Sisteminde varolan senkronizasyon nesnesidir. Mutex nesnesinin sahiplii bir thread tarafndan alnr ve sahiplii ancak alm olan thread verebilir. Mutex nesnesi mutex snfyla temsil edilmitir. Mutex nesnesi yarat lrken mutaex snfnn balanglar yoluyla nesnenin balangtaki durumu yani sahipliinin alnp alnmayaca belirlenebilir. public Mutex (bool initiallyOwner) Fonksiyonun parametresi mutex nesnesinin balangtaki sahipliinin alnp alnmayacana ilikindir. Nesnenin sahiplii ReleaseMutex fonksiyonuyla braklr. public void ReleaseMutex() Wait fonksiyonlar eer mutex in sahipliini eer baka bir thread almsa beklemeye yol aar deilse nesne ak durumdad r ve sahiplik alnr. Mutex nesnesi ile kritik kod yle oluturulur. m_mutex.WaitOne(); ... Kritik Kod

m_mutex.ReleaseMutex(); phesiz Mutex snf da WaitHandle snfndan tretildii iin Dispose fonksiyonuna sahiptir ve kullanmdan sonra Dispose fonksiyonunun arlmas uygun olur. Ayn thread windows sistemlerinde mutex nesnesinin sahipliini yeniden alabilir. Fakat ald kadar ReleaseMutex uygulamaldr. rnein biz mutex nesnesi ile retici tketici problemini zemeyiz. nk baka bir threadin sahipliini alm olduu mutex nesnesini b rakamayz. Kernel Senkronizasyon Nesnelerinin Prosesler Aras Kullanm: Event, Mutex, Semaphore nesneleri istenilirse isimli bir biimde prosesler arasnda da kullanlabilir. EventWaitHandle, Semaphore ve Mutex Snflarnn ayrca String parametreli balang fonksiyonlar da vardr. ki ayr proses ortak bir isim zerinden anlarsa ikisi de ayn isimli ayn trden nesneyi yarattnda aslnda bunlar ayn nesnedir. Prosesler aras haberleme mmkn olur.

202

rnein bir proses EventWaitHandle trnden nesneyiaadaki gibi yaratm olsun: m_event = new EventWaitHandle(false, EventResetMode.AutoReset, CSD1993); imdi baka bir programnda Event nesnesini yukardaki gibi ayn ismi vererek yarattn dnelim Bu durumda bu proses yeni bir Event nesnesi yaratmayacaktr. simler ayn oldu u iin yaratlm olan aacaktr. Dier bir nokta ayn ismi vererek aan dier prosesin farkl bir modda nesneyi amak istemesi durumunda nesne alacak fakat programcnn belirttii modda deil ilk prosesin modunda alm olacaktr. Asenkron Fonksiyonlar: Normal fonksiyon arlar senkrondur. Asenkron fonksiyon arma denilince thread yaratlarak fonksiyon arm anlalmald r. Fonksiyon arma ilemi devam ettii halde fonksiyondan geri dnlr. Asenkron arlar aslnda tm delegelere zgdr. Process1/program.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace Process1 { class Program { private static EventWaitHandle m_event; static void Main(string[] args) { m_event = new EventWaitHandle(false, EventResetMode.AutoReset, "CSD1993"); Console.WriteLine("Waiting process1"); m_event.WaitOne(); Console.WriteLine("ok..."); //... } } } Process2/program.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace Process2 { class Program { private static EventWaitHandle m_event; static void Main(string[] args) { 203

m_event = new EventWaitHandle(false, EventResetMode.AutoReset, "CSD1993"); Console.WriteLine("Press any key to release other process"); Console.ReadLine(); m_event.Set(); //... } } } Biz bir delege referansyla fonksiyon arma operatr kullanarak fonksiyonu ardm zda aslnda C# derleyicisi bu ilemi Delegate snfnn Invoke fonksiyonuyal yapmaktadr. rnein: Proc p = new Proc(Foo) p.Invoke(); Biz armay aadaki gibi de yapabiliriz. p(); Delege yoluyla arma ilemi Invoke fonksiyonuyla deilde BeginInvoke fonksiyonuyla yap lrsa arma asenkron olur. Yani arma srasnda bir thread yaratlr ve fonksiyon o thread tarafndan arlr. BeginInvoke fonksiyonunun ilk n tane parametresi delege bildirimindeki parametrik yapyla tamamen aynd r. Son iki parametresi srasyla AsynCallback snf trnden ve object trnden parametrelerdir. AsynCallback parametresi null geilebilir. AsynCallback bir delegedir. Bu delegede verilen fonksiyon ilem bittiinde arlacak fonksiyondur. Null geilirse ilem bitince herhangi bir fonksiyonun arlmayaca sonucu karlr. BeginInvoke fonksiyonunun son object parametresi programc tarafndan ileride ele alnaca gibi elde edilebilecek bir deerdir. Bu parametre de null geilebilir. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; using System.Threading; namespace ConsoleApp { class Program { public static void Main(string[] str) { Proc p = new Proc(Foo); p.Invoke(10); Console.WriteLine("....."); 204

Console.ReadLine(); }

public static void Foo(int n) { for (int i = 0; i < n; ++i) { Console.WriteLine("Foo: {0}", i); Thread.Sleep(1000); } } } delegate void Proc(int a); } O halde biz bir fonksiyonun baka bir thread tarafndan altrlmasn istiyorsak hi thread yaratma zahmetine girmeden fonksiyonu delegeye yerletirip BeginInvoke fonksiyonunu arabiliriz. Fonksiyonlar asenkron ard ktan sonra bazen biraz paralel ilerleyip sonra ofonksiyonun bitmesini bekleyebiliriz. te bu ilem EndInvoke fonksiyonuyla yaplmaktad r. BeginInvoke bize IAsyncResult trnden bir arayz referans verir. EndInvoke fonksiyonu da BeginInvoke fonksiyonu tarafndan verilen bu arayz referansn istemektedir. Proc p =new Proc(Foo); IAsyncResult iresult; iresult = p.BeginInvoke(10, null, null) //... p.EndInvoke(iresult);

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; using System.Threading; namespace ConsoleApp { class Program { public static void Main(string[] str) { Proc p = new Proc(Foo); p.BeginInvoke(10, null, null);

205

Console.WriteLine("....."); Console.ReadLine(); }

public static void Foo(int n) { for (int i = 0; i < n; ++i) { Console.WriteLine("Foo: {0}", i); Thread.Sleep(1000); } } } delegate void Proc(int a); } EndInvoke fonksiyonu ayn zamanda arlan asenkron fonksiyonun geri dn deeri ile geri dnmektedir. Yani ilgili fonksiyonun bitmesi beklenirken ayn zamanda onun gerei dn deeri de elde edilmektedir. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; using System.Threading; namespace ConsoleApp { class Program { public static void Main(string[] str) { Proc p = new Proc(Foo); IAsyncResult iresult; iresult = p.BeginInvoke(10, null, null); //.... int val = p.EndInvoke(iresult); Console.WriteLine("Result: {0}", val); } public static int Foo(int n) { for (int i = 0; i < n; ++i) { 206

Console.WriteLine("Foo: {0}", i); Thread.Sleep(1000); } return 100; } } delegate int Proc(int a); } BeginInvoke fonksyonunun AsynCallback delege parametresi ilem bitince aprlacak fonksiyonu belirtir. Bu delegenin parametrik yaps yledir. public delegate void AsynCallback(IAsyncResult ar) Fonksiyona geirilecek vAsyncResult parametresi bize arlm olan fonksiyon hakknda bilgi vermektedir. Bu arayzn object trnden AsynState property si BeginInvoke fonksiyonuna geilecek son parametreyi belirtir. Bylece biz farkl Asenkron fonksiyonlar iin ayn biti fonksiyonlarn verebiliriz. Bu parametre belki de yeni bir ilemin balat lmas iin bize yardmc olabilir. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; using System.Threading; namespace ConsoleApp { class Program { public static void Main(string[] str) { Proc p = new Proc(Foo); IAsyncResult iresult; iresult = p.BeginInvoke(10, new AsyncCallback(CompletionProc), 500); Console.ReadLine();

} private static void CompletionProc(IAsyncResult ia) { int val = (int) ia.AsyncState; Console.WriteLine("Param: {0}", val); } public static int Foo(int n) { for (int i = 0; i < n; ++i) 207

{ Console.WriteLine("Foo: {0}", i); Thread.Sleep(1000); } return 100; } } delegate int Proc(int a); } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; using System.Threading; namespace ConsoleApp { class Program { private static Proc m_proc; public static void Main(string[] str) { m_proc = new Proc(Foo); IAsyncResult iresult; iresult = m_proc.BeginInvoke(3, new AsyncCallback(CompletionProc), null); Console.ReadLine(); } private static void CompletionProc(IAsyncResult ia) { //... Console.WriteLine("Proc Completed"); m_proc.BeginInvoke(3, new AsyncCallback(CompletionProc), null); } public static int Foo(int n) { for (int i = 0; i < n; ++i) { Console.WriteLine("Foo: {0}", i); Thread.Sleep(1000); } return 100; 208

} } delegate int Proc(int a); } Threadlere zg Alanlar(Thread Local Storage): Bazen bir deikenin threade zgbir kopyas kullanlmak istenebilir yani paylalan bir nesnenin her thread iin farkl bir kopyas olsun istenebilir. Bu konuya windows sistemlerinde Thread Local Storage denilmektedir. Threade zg alanlar olu turmak iin Thread snfnn AllocateDataSlot , AllocateNamedDataSlot , FreeNamedDataSlot fonksiyonlar kullanlr. AllocateDataSlot fonksiyonu parametresi yledir. public static LocalDataStoreSlot AllocateDataSlot() Fonksiyon bize LocalDataStoreSlot isimli bir snf trnden nesne verir. AllocateNamedDataSlot fonksiyonu da aadaki gibidir. public static LocalDataStoreSlot AllocateNamedDataSlot(string name) Daha sonra elde edilen bu nesne Thread snfnn SetData ve GetData fonksiyonlaryla kullanlan public static void SetData(LocalDataStoreSlot slot, Object data) public static object GetData(LocalDataStoreSlot slot) Nihayet threade zg oluturulan bu alan FreeNamedSlot fonksiyonuyla yok edilir. public static void FreeNamedDataSlot(string name) using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; using System.Threading; namespace ConsoleApp { class Program { private static Thread m_thread1; private static Thread m_thread2; private static LocalDataStoreSlot m_slot;

public static void Main(string[] str) { m_thread1 = new Thread(new ParameterizedThreadStart(ThreadProc)); m_thread2 = new Thread(new ParameterizedThreadStart(ThreadProc)); //... m_slot = Thread.AllocateDataSlot(); m_thread1.Start(100); m_thread2.Start(200);

m_thread1.Join(); m_thread2.Join(); 209

} public static void ThreadProc(object o) { Thread.SetData(m_slot, o); Foo(); //... }

private static void Foo() { int val = (int)Thread.GetData(m_slot); Console.WriteLine(val); } } } .Net te daha sonralar TLS konusu daha basitletirilmitir. yleki Snfn Statik veri eleman ThreadStaticAttribute snfyla zniteliklendirilrse bu TLS tahsisatlar otomatik yaplacaktr. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.IO; using System.Threading; namespace ConsoleApp { class Program { private static Thread m_thread1; private static Thread m_thread2; [ThreadStatic] private static int m_val; public static void Main(string[] str) { m_thread1 = new Thread(new ParameterizedThreadStart(ThreadProc)); m_thread2 = new Thread(new ParameterizedThreadStart(ThreadProc)); //... m_thread1.Start(100); m_thread2.Start(200);

m_thread1.Join(); 210

m_thread2.Join(); } public static void ThreadProc(object o) { m_val = (int)o; Foo(); //... }

private static void Foo() { Console.WriteLine(m_val); } } } ok lemcili Sistemler in nlemler: ok ilemcili ya da ok ekirdekli sistemlerde ok seyrek olarak karlalsada nemli bir problem vardr. Birden fazla threadin paylalan ortak bir deikene erimesi durumunda threadler den biri yazma yapyorsa eer threadlerfarkl ilemcilere atanmsa ve ilem tesadfen ayn anda gereklemise bozuk deer olu abilmektedir. ok ilemcili sistemlerde bu bozulma ok seyrek olsada bir olaslk olarak her zaman sz konusudur. Bunu dikkate almayan programlar bcekli kabul edilmektedir. rnein threadlerden biri m_val deikenine deer yazarken dieri de bunu okuyor olsun. Bu iki thread tesadfen paralel alan iki farkl ilemciye ya da ekirdee atanm olabilir ve bu okuma yazma ilemleri tesadfen ayn anda gereklemi olabilir. te bu durumda bozulma olu abilir. Bu tr durumlarda bu kadar seyrek olu ma olasl olan bir durum iin monitor snf yla ya da Lock deyimiyle senkronizasyon uygulamaya almak kt bir tekniktir. Intel ilemcilerinde bir Makine komutunu bu anlamda atomik yapan zel komutlar vardr. C# da Volatile belirleyicisi CLR sistemine ilgili deikenin threadler arasnda paylaldn ve ok ilemci iin tehdit olutu unu belirtmektedir. Bu durumda ok ilemcili sistemler iin threadler arasnda paylalacak deikenlerin kesinlikle volatile bildirilmesi gerekir. private volatile int m_val; Thread Gvenli Fonksiyonlar: Ayn anda birden fazla thread tarafndan altrld halde soruna yol amayan fonksiyonlara Thread gvenli fonksiyonlar diyoruz. Genel olarak snfn veri elemanlarn kullanan fonksiyonlar( yani yerel deikenlerden baka deikenleride kullanan fonksiyonlar) thread gvenli deildir. Bir fonksiyonun thread gvenli olup olmadn nceden bilmek nemlidir. .net snf sisteminde genel olarak snflarn static fonksiyonlar thread gvenlidir. Fakat static olmayan fonksiyonlar thread gvenli deildir. Bir fonksiyonu thread gvenli yapabilmek iin o fonksiyonun kulland snfn veri elemanlarn ThreasStatic znitelii ile zniteliklendirerek o veri elemann dier threadlerden ayrmak gerekir. Thread Gvenli Collection Nesneleri: .net snf sisteminde dier snflarda oldu u gibi snflarn yalnzca static fonksiyonlar thread gvenlidir. Collection snflar genel olarak threadler aras 211

kullanm yo un snflard r. phesiz btn bir fonksiyonu d ardan lock ilemi ile kilitlemek yerine ieriden gerekli kk blmleri kilitlemek daha etkin kullanma yol aar. Bu nedenle performans dikkate alndnda Collection snflarn daha verimli bir biimde thread gvenli yaplmas nemlidir. (Yani biz thread gvenli olmayan Collection snflarn fonksiyonlarn d ardan kritik kod iine alp kullanabiliriz. Fakat bu fonksiyonlarn kendi iinde kritik kod oluturmas phesiz daha verimlidir.) Her Collection snfn Synchronized isimli bir static fonksiyonu vardr. Bu fonksiyon parametre olarak ilgili collection trnden bir nesne alr ve bize ayn collection trnden fakat thread gvenli olan yeni bir nesne verir. rnein: ArrayList m_a; //... m_a = ArrayList.Synchronized(new ArrayList()); Artk burada geri verilen nesnesyi thread gvenli olarak kullanabiliriz. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.Collections; namespace Producer_Consumer { public partial class Form1 : Form { private Thread m_producer; private Thread m_consumer; private Semaphore m_semaProducer; private Semaphore m_semaConsumer; private Random m_rand; private Queue m_queue; public Form1() { InitializeComponent(); m_rand = new Random(); m_queue = Queue.Synchronized(new Queue()); m_queue = new Queue(); m_semaConsumer = new Semaphore(10, 10); m_semaProducer = new Semaphore(0, 10); m_producer = new Thread(new ParameterizedThreadStart(ProducerThreadProc)); 212

m_producer.Start(null); m_producer.IsBackground = true; m_consumer = new Thread(new ParameterizedThreadStart(ConsumerThreadProc)); m_consumer.Start(null); m_consumer.IsBackground = true; } private void ProducerThreadProc(object o) { int i = 0; for (; ; ) { m_semaConsumer.WaitOne(); Thread.Sleep(m_rand.Next(200)); m_queue.Enqueue(i); if (i == 50) break; ++i; m_semaProducer.Release(); } } private void ConsumerThreadProc(object o) { int val; for (; ; ) { m_semaProducer.WaitOne(); Thread.Sleep(m_rand.Next(200)); val = (int)m_queue.Dequeue(); if (val == 50) break; listBox1.Items.Add(val); m_semaConsumer.Release(); } } } } Resource Use(Kaynak Kullanm): Pek ok programda onlarca kk jpg, bmp gibi grnt dosyalar waw gibi ses dosyalar kullanlmaktad r. Bu dosyalarn programn alma zaman srasnda yklenerek ilerlik kazanmas gvenli bir yaklam deildir. Bu kk dosyalardan biri bile silinse program muhtemelen almayacaktr. te bu tr durumlarda onlarca kk dosyann kurulum srasnda baka bir makinaya ekilmesi yerine bu dosyalarn exe dosya iine gmlmesi ok daha etkin bir yntemdir. te Kaynak(Resource) konusu bununla ilgilidir. 213

Herhangi bir dosya bir kaynak biiminde Assembly iine gmlebilir. Bunun iin csc.exe programnda komut satrnda /resource seenei kullanlmald r. /resource seeneiningenel biim aadaki gibidir. /resource:<dosya ismi> csc.exe derleyicisi belirtilen dosyay bir kaynak olarak assembly dosyasna gmmektedir. Bu tr kaynaklara ayn zamanda gml kaynaklar embedded resources ya da manifest resources denilmektedir. Assembly dosyas iine gmdmz kaynaklar program iinden ekilerek kullanlabilir. Bunun iin u admlar izlenmelidir: 1. ncelikle kaynan iinde bulunduu Assembly nin Assembly nesnesini elde etmek gerekir. Bu ilem Assembly snfnn GetXXXAssembly isimli static fonksiyonlar ile yaplabilir. rnein Assembly snfnn GetExacutingAssembly fonksiyonu bize almakta olan kodun iinde bulunduu Assemblynin Assembly nesnesini vermektedir. 2. Assembly snfnn GetManifestResourceStream fonksiyonlar kullanlarak kaynak bilgileri elde edilebilir. Bu fonksiyonlar bize bir stream nesnesi vermektedir. Bizbu stream nesnesinden okuma yaptmzda aslnda assembly iine gmlm kaynaktan okuma yapm oluruz Assembly a = Assembly.GetExecutingAssembly(); try { Stream s = a.GetMaifestResourceStream(message.txt); StreamReader sr = new StreamReader(s); Console.WriteLine(sr.ReadToEnd()); } catch (Exception e) { Console.WriteLine(e.Message); } Visual Studio IDE si kullanlarak bir kayna manifest kaynak olarak Assembly ye gmmek iin ilgili dosya projeye eklenir sonra fareyle sa tua baslp propertys mensne gelinir Bulid Action EmbeddedResourse biiminde seilir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace ResourceSample { public partial class Form1 : Form { private Image m_image; public Form1() { InitializeComponent();

214

try { m_image = new Bitmap(@"E:\DotNetAppBasic\ResourceSample\forest.jpg"); } catch (Exception e) { MessageBox.Show(e.Message); } } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawImage(m_image, this.ClientRectangle); } } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Reflection; namespace ResourceSample { public partial class Form1 : Form { private Image m_image; public Form1() { InitializeComponent(); try { Assembly a = Assembly.GetExecutingAssembly(); m_image = new Bitmap(a.GetManifestResourceStream("ResourceSample.Forest.jpg")); } catch (Exception e) { Console.WriteLine(e.Message); } } 215

private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawImage(m_image, this.ClientRectangle); } } } XML Temelli Kaynaklar: Kaynak kullanmnn temellerini yukarda akladk. Ancak Microsoft Visual Studio 2005 ile birlikte zellikle IDE zerinde kaynak ilemlerini daha kolay yapabilmek iin XML tabanl kaynak kullanm n tasarlamtr. XML tabanl kaynak kullanm nn anahtar noktalar unlard r. rili ufakl tm kaynaklar farkl dosyalar biiminde deil bir XML dosyas biiminde text tabanl olarak ifade edilir. Olu turulan bu kaynak XML kaynak dosyas resgen.exe denilen zel bir programla derlenir ve bir .resource dosyas elde edilir. x.resx(xml) resgen.exe x.resource

Elde edilen bu .resource dosyas Assembly dosyasna yukarda akland gibi gmlr. Buradaki .xml dosya format ve .resource dosya format microsoft tarafndan aklanmtr. Fakat programcnn bunlar bilmesi gerekmektedir. .net ktphanesinde ResourceManager isimli snf kullanlarak bu Assembly ye gmlm olan .Resource kaynaklar elde edilebilir. Visual Studio 2005 IDE si ile birlikte kaynak kullanm iyice basitletirilmitir. Yukarda aklad mz xml tabanl kaynak projeye eklenmi olan .resx uzantl dosyad r. Visual Studio IDE si eer istenirse Assembly iine gmlm olan .resource dosyasnn iinden ilgili kayna alan property lere sahip bir kod dosyasn bizim iin de oluturmaktadr. Bu dosya IDE de x.resx dosyas iin x.Designer.cs dosyasd r. phesiz programc x.Designer.cs dosyasnn iindeki kodlar yerine kayna ResourceManager snfn kullanarak dorudan alabilir. Bu durumda kaynak ilemlerini IDE kullanarak pratik bir biimde gerekletirmek iin projeye resx dosyas eklenir(Zaten proje ald nda projede byle bir dosya vardr) resx dosyasna grsel editrle kayna eklenir. Proje build yapldnda bu .resx dosyas IDE tarafndan resgen.exe kullanlarak .resource formatna dntrlp Assembly ye eklenir. Bizim yapacam z tek ey o kaynak iin retilmi property yi kullanmaktr. x.Designer.cs iindeki snf projenin isim alan.properties diye isimlendirilen bir isim alanna yerletirilmi Resources isimli bir snftr. Kayna alan propertyler statik propertylerdir. O halde rnein projemizin isim alan CSD ise Message isimli bir kayna elde eden property nin nitelikli ismi CSD.Properties.Resources.Message biimindedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; 216

using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Reflection; namespace ResourceSample { public partial class Form1 : Form { private Image m_image; public Form1() { InitializeComponent(); this.Text = ResourceSample.Properties.Resources.Message; try { Assembly a = Assembly.GetExecutingAssembly(); m_image = new Bitmap(a.GetManifestResourceStream("ResourceSample.Forest.jpg")); } catch (Exception e) { Console.WriteLine(e.Message); } } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawImage(m_image, this.ClientRectangle); } } } .net ortamnda bu IDE nin x.Designer.cs dosyas iinde bize property ile sundu u alma tarzna typed resource da denilmektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Reflection; namespace ResourceSample 217

{ public partial class Form1 : Form { private Image m_image; public Form1() { InitializeComponent(); m_image = ResourceSample.Properties.Resources.Forest; } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.DrawImage(m_image, this.ClientRectangle); } } } XML tabanl kaynak kullanm n daha ynetilebilir yapmak iin Visual Studio IDE si uygulama iin toplam 1 tane olan genel bir resources.resx isimli bir kaynak dosyas ile her form iin ayr bir .resx kaynak dosyas olu turmaktadr. Programcnn eer ilgili kaynak belirli bir forma ynelik ise o kayna o formun resx dosyasna koymas tavsiye edilmektedir. Fakat dikkat edilecei gibi uygulama genelindeki resources.resx dosyas iin ii kolaylatran Resources.Designer.cs dosyas retildii halde formlar iin byle bir .cs dosyas retilmemektedir. Yani Form a ilikin resx iindeki kaynaklar ResourceManager snf kullanlarak elde edilmelidir. Ancak programc isterse form a iliki resx dosyasnn zereine gelip properties mensnden Custom Tool ResxFileCodeGenerator girerse bu resx dosyas iinde x.Designer.cs dosyas retilir. Elimizde varolan bir dosyay XML tabanl kaynaa IDE yoluyla ekleyebiliriz.Bunun iin Solution Explorer da .resx uzant l dosyaya ift tklanr ve burada Edd Resource/Add Existinf File yap lr. .resx uzantl XML tabanl kaynak dosyasna eklenen dosyalar eer resim dosyas ise kaynak editr bunun iin image trnden property yazar. Eer biz kayna uygulamann kaynak dosyasna yani resources.resxe yerletirmisek kaynak yukardada belirtildii gibi properties isim alanndaki Resources snfnn statik propertyleri yoluyla ekilir. Yok eer Formun kaynak dosyasna eklemisek zaten kayna elde eden property formun iine yazlmaktadr. Ayrca IDE de istenirse kaynaa eklenmi olan dosyann Assembly dosyasna gmlmemeside salanabilir. Bunun iin ilgili kaynan zerine gelinip Properties mensnden Copy to output file seeneinde copy always seilir. IDE baz kontrollerin image propertyleri sz konusu olduunda zaten XML tabanl .resx dosyalarna otomatik bavurmaktad r. Zaten import seenei hem kaynaa ekleme hem de kullanma ilemlerini bir arada yapmaktadr. Anahtar Notlar: Microsoft eski windows srmlerinde oyun kartlarna ilikin oyunlarda kulland kartlar Cards.dll isimli bir dosyada toplamtr. stersek bu dll iinde ki bu oyun kartlarn .bmp 218

olarak save edebiliriz. Programa likin Ayarlar(Application Settings): Pek ok uygulama sonlandrldktan sonra saklanmas gereken pek aok ayar bilgileri kullanmaktadr. Kullanc eitli bileenlerin renklerini deitirebilir Ya da bir open diaalog penceresi sonlandrld yerden yeniden almak istenebilir. Bu tr ayar bilgilerinin saklanmas iin iki yntem kullanlr. 1. Windows un hem kendi ayarlarnn hemde programcnn ayarlarnn sakland registry dosyasn kullanmak. 2. Tamamen bu amala oluturulmu bir data dosyas kullanmak. .net 2005 ile birlikte uygulamaya ilikin ayar bilglerinin yine xml tabanl dosyalarda saklanmas salanmaktadr. Sihirbazla proje oluturulduunda Ide otomatik olarak Settings.setting isimli bir xml dosyas ile Settings.Designer.cs isimli bir property dosyas oluturmaktadr. Uygulamaya ilikin ayarlar IDE yoluyla Menu kullanlarak oluturulabilir. Projeye birden fazla settings eklenebilir. Proje built yapld nda tm bu settings dosyalar birletirilir ve .exe.config dosyas olu turulur. Bu dosyada kurulum srasnda hedef bilgisayara yklenmelidir. .exe.config uzantl bu dosya bir xml data dosyasdr. Fakat bizim oluturacam z sradan bir data dosyasndan fark bunun IDE destekli bir biimde pratik kullanlabilmesidir. Uygulamaya ilikin ibr ayar oluturabilmek iin Solution Explorer da setting dosyas zerine ift tklanr. nmze kan girdiimiz tm mende her ayar eleman iin Settings.Designer.cs dosyasnda bir property oluturulmaktadr. IDE Settings.Designer.cs dosyas ierisinde default isminde ayarlar temsil eden bir snf geri dndren Settings isimli snfn bir property sini oluturur. O halde rnein message isminde bir ayar eleman oluturmu olalm. Bunun program iindeki kullanm yle olacaktr. string msg = Properties.Settings.Default.Message; Burada properties kaynak konusunda da grdmz isim alandr. Settings IDE tarafndan oluturulmu bir snftr. Default bu snfn static bir property sidir ve bize Settings snf trnden bir nesne vermektedir. Message ise bizim ayar eleman iin oluturulan bir propertydir. Ayrca ayar elemanlar Scope bakmndan User ve Application olmak zere ikiye ayrlm tr. Bir ayar scope bakmndan user durumundaysa kullancya zgdr. Yani her kullanc login olduunda kendine zg ayarlar kullanr. Fakat ayar scope bakm ndan Application ise kullancdan bamsz olarak yani her kullanc iin ayn olacak biimde etki gsterir. Ayrca settings snfnn (Bu snf ApplicationSettingsBase snfndan tretilmitir.) baz faydal fonksiyonlar vardr. Reload Fonksiyonu ayar propertylerini .exe.config dosyasndan ykler. Reset fonksiyonu propertylere default deerlerini ykler. (Yani IDE ekranndaki elle girilen deerler) ve nihayet Save fonksiyonu da property iindeki deerleri .exe.config dosyasna geri ykler. Bunlarn d nda programc ayarlara deer girilirken ya da ayarlar save edilirken eitli kontrollerin yap lmasn isteyebilir. Bunun iin Settings snfnn (ApplicationSettingsBase snfnn) eitli event elemanlar kullanlr. Application ayarlar normal olarak read only dir. Fakat user ayarlar read/write biimindedir. Dolaysyla her user iin program alrken ayr bir ayar dosyas vardr ve bu ayar dosyas 219

\users\kullanc ad\Local Settings\ierisindedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace SampleSettings { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.Left = Properties.Settings.Default.FormX; this.Top = Properties.Settings.Default.FormY; } private void Form1_Click(object sender, EventArgs e) {

} private void Form1_FormClosing(object sender, FormClosingEventArgs e) { Properties.Settings.Default.FormX = this.Left; Properties.Settings.Default.FormY = this.Top; Properties.Settings.Default.Save(); }

} } Anahtar Notlar: Users ayarlarn property yoluyla deitirdiimizde otomatik bir biimde bu ayarlar kalc hale gelmemektedir. Ayarlar kalc hale getirebilmek iin Save fonksiyonunu arlmas gerekir. Bu fonksiyonun arlmas iin uygun bir yer FormClosing mesajdr. Form Editr Kullanarak Otomatik Ayar Oluturma: .net in kontrollerine ilikin ayarlar form editr kullanarak veri balama(data binding) zellii de kullanlarak kolay bir biimde kalc hale getirilebilmektedir. Bunu salamak iin Form editrde kontrol zerine gelinir. Properties mensne geilir ve orada Application Setting ksmna gelinir. Burada hazr bir biimde Location ve test blm vardr fakat farkl blmleri biz oluturabiliriz. 220

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace SampleSettings { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Click(object sender, EventArgs e) {

} private void Form1_FormClosing(object sender, FormClosingEventArgs e) { Properties.Settings.Default.Save(); } private void button1_Click(object sender, EventArgs e) { ColorDialog cd = new ColorDialog(); if (cd.ShowDialog() == DialogResult.OK) { this.BackColor = cd.Color; } }

} } Burada new seenei ile biz bir property iin yeni bir kalc ayar balants yapabiliriz. Bu balant y grsel olarak yaptktan sonra IDE arka planda dier btn ayarlamalar yapmaktadr. Fakat yine save ilemi programc tarafndan yap lmaldr. using System; using System.Collections.Generic; 221

using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace SampleSettings { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Click(object sender, EventArgs e) {

} private void Form1_FormClosing(object sender, FormClosingEventArgs e) { Properties.Settings.Default.Save(); } private void button1_Click(object sender, EventArgs e) { ColorDialog cd = new ColorDialog(); if (cd.ShowDialog() == DialogResult.OK) { this.BackColor = cd.Color; } this.label1.Text = "Max Score: 1234"; }

} } znitelikler(Attributes): znitelikler snf gibi yap gibi, veri eleman, property gibi, fonksiyon gibi pek ok programlama elemanna ilitirilebilir. litirme ilemi keli parantezler iinde ilgili elemann ncesinde gerekletirilir. rne in: [My Atrribute] class Sample { 222

//... } lgili elemana ilitirdiimiz z nitelik snfsal bir biimde metadata olarak Assembly dosyasna yerletirilir. K eli parantezler iinde ilitirdiimiz zniteliklerin znitelik snflarna ilikin olmas gerekir. System isim alanndaki Attribute isimli snftan tretilen snflara znitelik snflar denilir. rnein: class MyAttribute : Attribute { //... } [MyAttribute] class Sample { //... } Attribute snf Abstract bir snftr. Dolaysyla bu snftan tretme yapmazsak nesne yaratamayz. Bir elemana bir znitelik ilitirildiinde derleyici znitelik snf trnden bir nesne yaratr. Bu nesnenin bilgilerini metadata olarak Assembly dosyasna yerletirir. K eli parantezler iinde aslnda bir balang fonksiyonu arma ifadesi yer alr. znitelik nesnesi bu balang fonksiyonuyla yaratlr. rnein: [MyAttribute(This is a test)] class Sample { //... } Burada MyAttribute snfnn string parametreli balang fonksiyonu arlarak znitelik taratlacak. Nesnenin datalar da metadata olarak Assmebly dosyasna gmlecektir. znitelik snf isminden sonra hi fonksiyon parantesi almassa nesne iin default balang fonksiyonu arlr. Yani: [MyAttribute] ile [MyAttribute()] ayn anlamdad r. phesiz bir programlama elemanna birden fazla znitelik nesnesi atanabilir. Sintaks olarak bu nesneler aralarna virgl konularak ayn keli parantez ierisinde Ya da ayr ayr keli parantezler ierisinde belirtilebilir. rnein: [MyAttribute, YourAttribute] class Sample { //... } ya da ayn eyi yle de yapabiliriz. [MyAttribute] [YourAttribute] class Sample { 223

//... }ayn anlamdad r. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AttributeSample { class Program { static void Main(string[] args) { } }

[ MyAttribute ( "This is a test")] [YourAttribute(100)]class Sample { [YourAttribute(100)] private int m_a; } class MyAttribute : Attribute { private string m_msg; public MyAttribute(string msg) { m_msg = msg; } public string Msg { get { return m_msg; } set { m_msg = value; } } } class YourAttribute : Attribute { private int m_no; public YourAttribute(int no) { m_no = no; 224

} public int No { get { return m_no; } set { m_no = value; } } } } Bir bildirime ilitirilen znitelik nesnesi programn alma zaman srasnda programc tarafndan ya da CLR tarafndan elde edilebilir. Bunun iin srasyla u ilemler yaplr. 1. Bu aamada znitelik nesnesinin ilitirildii programlama elemannn iinde bulunduu Assembly ye ilikin Assembly nesnesi elde edilir. Bu ilem Assembly snfnn GetAssembly fonksiyonuyla, GetExecutingAssembly fonksiyonuyla ya da GetCallingAssembly fonksiyonuyla gerekletirilebilir. 2. znitelik bilgileri elde edilecek trn type nesnesi elde edilir. Type nesnesi GetType fonksiyonuyla ya da Typeof operatr ile elde edilebilir. 3. Type snfnn GetCustomAttributes fonksiyonlar bize tr e ilitirilmi btn znitelik nesnelerini bize vermektedir. public abstract Object[] GetCustomAttributes(bool inherit) fonksiyonun parametresi true girilirse trn taban snflarna ilikin znitelik nesneleri de elde edilir. Fonksiyonun geri dn deeri aslnda metadata olara Assembly e ilitirilmi olan znitelik nesnelerini vermektedir. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AttributeSample { class Program { static void Main(string[] args) { Type t = typeof(Sample); foreach (object o in t.GetCustomAttributes(false)) { MyAttribute ma = o as MyAttribute; if (ma != null) { Console.WriteLine(ma.Msg); } }

} 225

[MyAttribute("This is a test")] [YourAttribute(100)] class Sample { //... } class MyAttribute : Attribute { private string m_msg; public MyAttribute(string msg) { m_msg = msg; } public string Msg { get { return m_msg; } set { m_msg = value; } } } class YourAttribute : Attribute { private int m_no; public YourAttribute(int no) { m_no = no; } public int No { get { return m_no; } set { m_no = value; } } } } rnein Sample snfna ilikin bu snfa ilitirilmi olan MyAttribute trnden znitelik nesnelerini yle elde edebiliriz. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AttributeSample { 226

class Program { static void Main(string[] args) { Type t = typeof(Sample); foreach (object o in t.GetCustomAttributes(false)) { MyAttribute ma = o as MyAttribute; if (ma != null) { Console.WriteLine(ma.Msg); } YourAttribute ya = o as YourAttribute; if (ya != null) { Console.WriteLine(ya.No); } }

} }

[MyAttribute("This is a test")] [YourAttribute(100)] class Sample { //... } class MyAttribute : Attribute { private string m_msg; public MyAttribute(string msg) { m_msg = msg; } public string Msg { get { return m_msg; } set { m_msg = value; } } } class YourAttribute : Attribute 227

{ private int m_no; public YourAttribute(int no) { m_no = no; } public int No { get { return m_no; } set { m_no = value; } } } } Grld gibi program alrken biz nesneye ilitirilmi olan znitelik nesnelerini elde edebilmekteyiz. Type snfnn aadaki gibi bir GetCustomAttribute fonksiyonu da vardr. public abstract Object[] GetCustomAttribute(Type attributeType, bool inherit) Bu fonksiyonun birinci parametresi znitelik snfna ilikin Type nesnesidir. Yani biz bu fonksiyonla rnein bir snfa ilitirilmi yalnzca MyAtrribute trnden nesneleri elde edebiliriz. rnein: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AttributeSample { class Program { static void Main(string[] args) { Type t = typeof(Sample); foreach (MyAttribute ma in t.GetCustomAttributes(typeof(MyAttribute), false)) { Console.WriteLine(ma.Msg); }

} }

[MyAttribute("This is a test")] [YourAttribute(100)] class Sample { //... } 228

class MyAttribute : Attribute { private string m_msg; public MyAttribute(string msg) { m_msg = msg; } public string Msg { get { return m_msg; } set { m_msg = value; } } } class YourAttribute : Attribute { private int m_no; public YourAttribute(int no) { m_no = no; } public int No { get { return m_no; } set { m_no = value; } } } } Dier programlama elemanlarna ilitirilmi olan znitelik nesnelerinin nasl elde edilecei Reflection konusu ierisinde ele alnacaktr. znitelik snflarna ilikin iki tr parametre bilgisi vardr. 1. Konumsal(positional) parametreler 2. simli(named) parametreler znitelik snfnn balang fonksiyonlarnda bulunan parametrelere konumsal parametreler denir ve bu parametreler eer o balang fonksiyonu kullanl yorsa kesinlikle bulundurulmak zorundadr. znitelik snflarnn public veri elemanlar ve propertyleri isimli parametrelerdir. Bunlar konumsal parametrelerden sonra isim = deer(values) biiminde belirtilirler. rnein: class MyAttribute : Attribute { private string m_msg; private int m_no; public MyAttribute(string msg) 229

{ //... } public int no { get{ return m_no} set { m_no = value;} } //... } Burada string parametresi konumsal no parametresi ise isimseldir. simli parametreler hi belirtilmeyebilir. Fakat belirtilecekse konumsal parametrelerden sonra isim = value biiminde belirtilmelidir. rnein: [MyAttribute (This is a test, No = 123)] class Sample { //... } simli parametreler birden fazla bulunabilir. Bunlarn hangi srada belirtildiinin bir nemi yoktur. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AttributeSample { class Program { static void Main(string[] args) { Type t = typeof(Sample); foreach (MyAttribute ma in t.GetCustomAttributes(typeof(MyAttribute), false)) { Console.WriteLine("{0} {1}", ma.Msg, ma.No); }

} }

[MyAttribute("This is a test", No = 123)] class Sample { //... } class MyAttribute : Attribute 230

{ private string m_msg; public string Msg { get { return m_msg; } set { m_msg = value; } } private int m_no; public MyAttribute(string msg) { m_msg = msg; } public int No { get { return m_no; } set { m_no = value; } }

//... }

} znitelik snflarnn isimlerinin Attribute son ekiyle oluturulmas zorunlu deildir fakat gelenekseldir. rnein MyAtrribute gibi. C# standartlarna gre bir znitelik snf eer XXXAttribute biiminde isimlendirilmise biz onu XXX biiminde kullanabiliriz. rnein SerializableAttribute znitelik snfn biz yle kullanabiliriz: [Seriliazable] phesiz bu kullanm yalnzca [] iinde kullanlabilir. Fakat XXXAttribute yerine znitelik snflar yalnzca XXX biiminde de isimlendirilebilir. Bu durumda snf ismi doal olarak XXX biiminde kullanlr. Hem XXX biiminde hem de XXXAttribute isminde iki znitelik snf bir arada bulunabilir. Bu snflarn birarada bulunmas deil keli parantez iinde XXXAttribute n XXX biiminde kullanlmas soruna yol aar. Fakat [] iinde XXXAttribute eklinde kullanm soruna yol amaz. .Net snf ktphanesinde ok sayda znitelik snfda bulunmaktadr. Programcnn ktphane iindeki programlama elemanlarn incelerken bu elemanlara ilitirilmi znitelik snflarna dikkat etmesi tavsiye edilir. nk bu znitelik nesneleri igii programlama eleman hakknda ipular vermektedir. znitelik Bilgileri Neden Kullanlr?: znitelik bilgileri bir programlama eleman hakknda ek birtakm bilgiler vermektedir. znitelik nesneleri derleyici tarafndan CLR tarafndan, programcnn kendisi tarafndan kullanlyor olabilir. Bir elemana znitelik ilitirmenin bir anlam vard r. rnein bir Enum trne FlagsAttribute isimli znitelik ilitirilirse bu Enum trnn elemanlarnn | operatr ile kombine edilebilecei anlam kar. Programc enum trne bunun ilitirildiini grdnde hemen bu bilgiyi edinmi olur. stelik bu bilgi IDE gibi programlar tarafndan da 231

faydal amalarla kullanlabilir. C# derleyicisi de baz zniteliklere daha derleme aamasnda zel nem vermektedir. rnein biz bir snf ya da yap ya Serliazable zniteliini ilitirirsek daha derleme aamasnda derleyici snfn serihalegetirilebilme zelliini kontrol eder. Bir tre ya da programlama elemanna ilitirdiimiz znitelik onun belirli bir zellie uygunluunu da belirtiyor olabilir. Bylece bu zellie uygunluk programn alma zaman srasnda denetlenebilmektedir. Bir program bir tre bir zniteliin ilitirilmi oldu unu grdnde ona zel bir ilem uygulayabilir. znitelik Snflarna Uygulanan znitelik Snflar: znitelik snflarna uygulanan en nemli znitelik snf AttributeUsageAttribute snfd r. Bu znitelik snfnn balang fonksiyonu yani konumsal parametresi AttributeTarget isimli bir Enum trndendir. Bu parametre ilgili zniteliin hangi program elemanlarna uygulanabileceini belirtmektedir. rnein: [AttributeUsage(AttributeTargets.Class)] calss MyAttribute : Attribute { //.... } Burada MyAttribute isimli znitelik sadece snflara uygulanr. AttributeUsage Attribute snfnn AllowMultiple isimli bool trden isimli parametresi ilgili zniteliin birden fazla kez ayn elemana uygulanp uygulanmayacan belirtir. Normal olarak ayn znitelik ayn elemana birden fazla kez uygulanamaz. [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] calss MyAttribute : Attribute { //.... } Burada artk biz MyAttribute isimli znitelii ayn elemana birden fazla kez uygulayabiliriz. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace AttributeSample { [My] [My] class Program { static void Main(string[] args) { } }

232

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] class MyAttribute : Attribute { //... } } Yanstma (Reflection) simli: Bir .net programnda kullandm z snf, yap gibi tm trlere ilikin bilgiler, tm fonksiyonlara ilikin bilgiler, tm veri elemanlarna ve dier programlama elemanlarna ilikin bilgiler derleme srasnda derleyici tarafndan Assembly dosyasnn (PE Format) metadata blmne yazlmaktadr. Ayn zamanda .net snf sistemi iinde bu bilgilerin elde edilmesini alayan snflarda vard r. te bir Assembly iindeki Metadata lar alarak zerinde ilem yapmamaya yanstma ilemleri denilmektedir. Bu snflar System.Reflection isim alan iindedir. Yanstma ilemlerinin ilk adm ilgili Assemblye ilikin bilgilerin elde edilmesidir. Bir Assembly dosyasnn btn daha nce belirtildii gibi Assembly snfyla temsil edilmektedir. lgili Assembly iin Assembly nesnesinin elde edilmesi Assembly snfnnGetAssembly, GetCallingAssembly, GetExacutingAssembly, GetEntryAssembly fonksiyonlaryla elde edilir. lgili Assemly nin bilgileri elde edildikten sonra sra bu Assembly iindeki trlerin bilgilerin elde edilmesine3 gelmitir. Bunlara; Snf, enum, delege, yap , fonksiyon, Arayz, tr (Type) denilmektedir. Sistem her bir tr iin bir type nesnesi oluturmaktad r. te Assembly snfnn aadaki GetTypes fonksiyonu o Assembly iindeki tm trleri bir Type dizisi olarak vermektedir. public virtual Type [] GetTypes() using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace ReflectionSample { class Program { int a; static void Main(string[] args) { Assembly a = Assembly.GetExecutingAssembly(); foreach (Type type in a.GetTypes()) Console.WriteLine(type.Name); } } struct X { //... } 233

interface Y { } class Z { } } Asswmbly iindeki tm trlere ilikin Type nesnelerini elde ettikten sonra artk sra bu trlerin iindeki elemanlar elde etmeye gelmitir. (DeAssembler program Reflector program bedava) Type snfnn IsXXX isimli propertyleri ilgili trn XXX tr olup olmadn belirlemekte kullanlr. rnein IsClass ilgili trn bir snf olup olmad n IsValueType bir yap olup olmad n anlamakta kullanlr. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace ReflectionSample { class Program { static void Main(string[] args) { Assembly a = Assembly.GetExecutingAssembly(); foreach (Type type in a.GetTypes()) { Console.Write(type.Name + ":"); if (type.IsClass) Console.Write("Class"); else if (type.IsEnum) Console.Write("Enum"); else if (type.IsInterface) Console.Write("Interface"); else if (type.IsValueType) Console.Write("Struct"); Console.WriteLine(); } } } struct X { //... } 234

interface Y { } class Z { } } Type snfnn bir grup GetYYY fonksiyonu vardr. Buradaki YYY tr ierisindeki hangi elemanlara ilikin bilgilerin alnacan belirtir. rnein GetConstructors tm balang fonksiyonlarn, GetField tm veri elemanlarn, GetEvent tm Event elemanlarn GetMethod tm fonksiyonlar almak iin kullanlr. Bir tr iindeki tm programlama elemanlar ZZZInfo isimli snflarla temsil edilmitir. Burada ZZZ trn iindeki ilgili eleman belirtmektedir. rnein MethodInfo gibi PropertyInfo gibi. Bu snflarn hepsi MemberInfo isimli snftan tretilmitir. MemberInfo

PropertyInf o

MethodInfo

ConstructoryInf o

ZZZInfo

rnein bir snfn tm fonksiyonlarna ilikin bilgileri yle elde edebiliriz. Assembly a = Assembly.GetExacutingAssembly(); Type t = a.GetType(ReflectionSample.Program); foreach (MethodInfo mi int t.GetMethods()) Console.WriteLine(mi.Name) using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace ReflectionSample { class Program { static void Main(string[] args) { Assembly a = Assembly.GetExecutingAssembly(); Type t = a.GetType("ReflectionSample.Program"); 235

foreach (MethodInfo mi in t.GetMethods()) Console.WriteLine(mi.Name); } } struct X { //... }

interface Y { } class Z { } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace ReflectionSample { class Program { public static void Main(string[] args) { Assembly a = Assembly.GetExecutingAssembly(); Type t = a.GetType("ReflectionSample.Program"); MethodInfo mi = t.GetMethod("Foo"); foreach (ParameterInfo pi in mi.GetParameters()) Console.WriteLine("{0} {1}", pi.ParameterType.Name, pi.Name);

} public void Foo(int a, long b) { } } struct X 236

{ //... }

interface Y { } class Z { } } Artk Assmebly snfndan balayarak programa ilikin tm detaylar tek tek elde edilebilir. Zaten DisCharp gibi Reflector gibi Salamandergibi DeCompilerler .net in bu yanstma snflarn kullanarak yalmlardr.

MDI(Multiple Document Interface) Uygulamalar: Eskiden MDI uygulamalar ok yo un olarak kullanlyordu. Gerektende Microsoft un Excel, Word gibi programlar MDI biiminde desgn edilmiti. Fakat daha sonra MDI uygulamalarnn poplaritesi azalmt. Microsoft un kendisi de daha sonralar MDI uygulamlar yerine bir program birden fazla kez altrma yntemini uygulamaya balamt r. Microsoft son zamanlarda MDI uygulamalar yerine kendi tipik programlarn her bir dkuman penceresinin anapencere olduu Multiform olarak tasarlamaktadr. Yani rnein Microsoft un word programnda her file/new yaptm zda yeni bir word altrlmaz fakat yeni bir word formu oluturulur. Bu kullanm MDI uygulamalar ndaki faydaya benzer bir fayda oluturmaktad r. Fakat burada sz edilen MDI uygulamalar byle deildir. Fakat yine de poplaritesi dmesine karn IDE ler gibi tipik programlar yine de MDI uygulamalarn kullanmaktadr. Tipik bir MDI uygulamasnda API terminolojisi ile konuulursa 3 tr pencere vardr. Programn ana penceresine Frame penceresi(Frame window) denir. Frame penceresinin alma alann kaplayan gri renkte bir pencere alan daha oluturulmutur ve buna da Client penceresi denir. Nihayet kullancnn etkiletii asl ilevsel pencerelere ise document penceresi (document windows) denilmektedir. .Net altnda programcnn Client penceresi ile dorudan bir etkileimi yoktur. Fakat arka planda Client penceresi Frame penceresi ile documnet pencereleri arasnda arayz oluturma grevindedir. Tipik bir MDI uygulamasnda document pencerelerini idare etmek iin bir men ubuunda Window popup bulunmaktadr. Tabi bunun bulunmas zorunlu deildir. .Nette hem Frame penceresi hem de document pencererleri yine form snfndan tretilmi snflarla temsil edilmektedir. MDI uygulamas iin iki eyin yaplmas yeterlidir. 1. Programn ana penceresini temsil eden(Yani Frame penceresi olacak olan) form snfnn bool trden IsMDI property si true yap lmaldr. Bu property true yapldnda arka planda otomatik olarak ana pnecere bir frame penceresi yaplr ve gri renkteki Client penceresi yaratlr. 2. Document pencereleri de form snfndan tretilmi snflarla temsil edilir. Bir document penceresi yaratlaca zaman tek yaplacak bu form snf trnden bir nesne yaratmak ve 237

Form snfnn MDIParent simli property elemanna frame penceresine ilikin form referansn atamaktr. Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace MdiSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void newToolStripMenuItem_Click(object sender, EventArgs e) { Form2 f = new Form2(); f.MdiParent = this; f.Visible = true; } } } Form2.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace MdiSample { public partial class Form2 : Form { public Form2() { InitializeComponent(); } } } Form snfnn MdiChildren isimli property eleman bize bir form dizisi olarak yaratlm olan tm document pencerelerini verir. Biz eer btn docment pencereleri zerinde ilem yapmak istersek 238

bu formlar dolaabiliriz. Anahtar Notlar: Visual Studio add new iteim seenei ile MdiParent seilirse Window mensne de sahip olan basit bir iskelet MDI program yazmaktadr. Bunun iin bo bir windows form uygulamas yaratlarak Ana form silinip bunun yerine yeni bir MDIParent form projeye eklenebilir. Burada Form editrn oluturdu u kodlarda document penceresi olarak dorudan form snf kullanlm tr. phesiz programcnn bunun yerine kendi formunu kullanmas anlaml olur. MDIParent1.cs Wizard n kendi yazd using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace MdiWizard { public partial class MDIParent1 : Form { private int childFormNumber = 0; public MDIParent1() { InitializeComponent(); } private void ShowNewForm(object sender, EventArgs e) { Form childForm = new Form(); childForm.MdiParent = this; childForm.Text = "Window " + childFormNumber++; childForm.Show(); } private void OpenFile(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal); openFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"; if (openFileDialog.ShowDialog(this) == DialogResult.OK) { string FileName = openFileDialog.FileName; } } private void SaveAsToolStripMenuItem_Click(object sender, EventArgs e) { SaveFileDialog saveFileDialog = new SaveFileDialog(); 239

saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal); saveFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"; if (saveFileDialog.ShowDialog(this) == DialogResult.OK) { string FileName = saveFileDialog.FileName; } } private void ExitToolsStripMenuItem_Click(object sender, EventArgs e) { this.Close(); } private void CutToolStripMenuItem_Click(object sender, EventArgs e) { } private void CopyToolStripMenuItem_Click(object sender, EventArgs e) { } private void PasteToolStripMenuItem_Click(object sender, EventArgs e) { } private void ToolBarToolStripMenuItem_Click(object sender, EventArgs e) { toolStrip.Visible = toolBarToolStripMenuItem.Checked; } private void StatusBarToolStripMenuItem_Click(object sender, EventArgs e) { statusStrip.Visible = statusBarToolStripMenuItem.Checked; } private void CascadeToolStripMenuItem_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.Cascade); } private void TileVerticalToolStripMenuItem_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.TileVertical); } private void TileHorizontalToolStripMenuItem_Click(object sender, EventArgs e) { LayoutMdi(MdiLayout.TileHorizontal); } private void ArrangeIconsToolStripMenuItem_Click(object sender, EventArgs e) 240

{ LayoutMdi(MdiLayout.ArrangeIcons); } private void CloseAllToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Form childForm in MdiChildren) { childForm.Close(); } } } } Form snfnn LayoutMdi isimli fonksiyonu document pencerelerini dzenlemek iin kullanlr. Bu fonksiyon MdiLayout isimli bir enum parametresi almaktadr. Bu Enum trnn Cascade, TileHorizantal, TileVertical, ArrangeIcon isimli elemanlar vardr. Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace MdiSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void newToolStripMenuItem_Click(object sender, EventArgs e) { Form2 f = new Form2(); f.MdiParent = this; f.Show(); } private void cascadeToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.Cascade); } private void tileHorizontalToolStripMenuItem_Click(object sender, EventArgs e) { 241

this.LayoutMdi(MdiLayout.TileHorizontal); } private void tileVerticalToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.TileVertical); } private void arrangeIconsToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.ArrangeIcons); }

} } Form2.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace MdiSample { public partial class Form2 : Form { public Form2() { InitializeComponent(); } } } MDI uygulamalarnn o unda bir dkuman ald nda ayn zamanda bu dkuman ismi window mensnn altnda da grntlenir. Bu klasik bir uygulamadr. Manuel olarak yap labilir fakat .net bunu kolaylatrc basit bir yntem sunmaktadr. MenuStrip snfnn MDIWindowListItem isimli property eleman ToolStripMenuItem snf trndendir. Bu eleman bir popup girilirse yukarda aklad mz dkuman penceresi listelemesi otomatik yaplr. Bu otomatize etme ileminde menu separatr de otomatik yerletirilmektedir. Fakat maalesef tm dkuman pencereleri kapatld nda bu separatr hala kalmaktad r. Bu ilemi biz popup mennn DropDownOpening ve DropDownClosed Eventlerinde manuel bir biimde salayabiliriz. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; 242

using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class MDINotepadForm : Form { private int m_count; public MDINotepadForm() { InitializeComponent(); m_count = 1; } private void newToolStripMenuItem_Click(object sender, EventArgs e) { DocumentForm df = new DocumentForm(); df.MdiParent = this; df.Text = "Document " + m_count.ToString(); ++m_count;

df.Show(); } private void tileHorizontalToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.TileHorizontal); } private void tileVerticalToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.TileVertical); } private void cascadeToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.Cascade); } private void arrangeIconsToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.ArrangeIcons); } private void windowToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { if (MdiChildren.Length == 0) 243

windowToolStripMenuItem.DropDownItems[windowToolStripMenuItem.DropDownItems.Count 1].Visible = false; } } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace CSD { public partial class MDINotepadForm : Form { private int m_count; public MDINotepadForm() { InitializeComponent(); m_count = 1; } private void newToolStripMenuItem_Click(object sender, EventArgs e) { DocumentForm df = new DocumentForm(); df.MdiParent = this; df.Text = "Document " + m_count.ToString(); ++m_count;

df.Show(); } private void tileHorizontalToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.TileHorizontal); } private void tileVerticalToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.TileVertical); }

244

private void cascadeToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.Cascade); } private void arrangeIconsToolStripMenuItem_Click(object sender, EventArgs e) { this.LayoutMdi(MdiLayout.ArrangeIcons); } private void windowToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { if (MdiChildren.Length == 0) windowToolStripMenuItem.DropDownItems[windowToolStripMenuItem.DropDownItems.Count 1].Visible = false; } public void saveToolStripMenuItem_Click_1(object sender, EventArgs e) { DocumentForm df = (DocumentForm)this.ActiveMdiChild; if (df.DocPath == null) {

SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = "Text Files(*.txt)|*.txt|All Files(*.*)|*.*"; if (sfd.ShowDialog() == DialogResult.OK) { df.SaveAs(sfd.FileName); MDINotepadForm_MdiChildActivate(null, null); df.Text = Path.GetFileName(sfd.FileName); } } else { df.Save(); MDINotepadForm_MdiChildActivate(null, null); } } public void MDINotepadForm_MdiChildActivate(object sender, EventArgs e) { DocumentForm df = (DocumentForm)this.ActiveMdiChild; if (df != null) { saveToolStripButton.Enabled = df.Modified; 245

saveToolStripMenuItem.Enabled = df.Modified; } } private void openToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Text Files(*.txt)|*.txt|All Files(*.*)|*.*"; if (ofd.ShowDialog() == DialogResult.OK) { DocumentForm df = new DocumentForm(); df.MdiParent = this; df.Show(); df.Open(ofd.FileName); MDINotepadForm_MdiChildActivate(null, null); df.Text = Path.GetFileName(ofd.FileName); } } } } MDI Uygulamalar ve Menu Birletirme lemleri: MDI uygulamalarnn ounda Frame penceresinin anamens hi dkuman ak deilken ya da en azndan bir dkuman akken farkllk gstermektedir. rnein bir MDI editr uygulamasnda hibir dkuman ak deilken ana mendeki edit popup nn bulunmas anlamszdr. Bazen dkuman pencereleri aktifken baka popup larada elemanlar eklenmektedir. Bu ilemler manuel olarak yaplabilir fakat .net ktphanesi bu ilemleri otomatize edecek bir mekanizma sunmaktadr. Yukarda anlatlan ilemleri otomatik yapmak iin ana men ye ek olarak bir de dkuman pencerelerine men yerletirilir. Menu birletirme ilemleri iin hem ana mennn hemde dkuman penceresenin mensnn MenuStrip snfna ilikin bool trden AllowMerge property eleman true yap lmald r. Bundan sonra birletirme ileminin nasl yap laca belirlenir. ToolStripMenuItem snfnn MergeAction isimli property eleman MergeAction isimli Enum trndendir. Burada ilgili popup n ya da men elemannn anamenye nasl eklenecei belirtilmektedir. Append sona ekleme anlam na gelir. Insert belirli bir indexe ekleme anlamna gelir. Bunun iin MergeIndex property sine baklmaktad r. Replace anamendeki ile yer deitirme anlamna gelir. Remove uyu an elemann silinecei anlamna gelir MatchOnly seeneinde bir ilem yap lmaz. Durum ubuu Kontrol: Pek ok uygulamada ana pencerenin altnda programn o andaki durumu hakknda bilgi veren Durum ubuu Kontrol(StatesBar) bulunur. FrameWork 2.0 ile birlikte durum ubuu kontrol de bir erit kontrol olarak ele alnmaktad r. ToolStrip ToolBar

MenuStrip

StatusStrip

StatusBar

Durum ubu u kontrolleri Blmlerden oluur. Bu blmlere eleman yerletirilebilir. 246

Durum ubu u kontrol tipik olarak yle kullanlr: 1. StatusStrip snf trnden bir nesne yaratlr. Control Default aa yuvalanmtr. 2. Tpk menulerde yaptmz gibi durum ubuu elemanlarn statusStrip snfnn ItemsCollection elemanna ekleyebiliriz. Grld gibi durum ubu u tamamen ana menuye benzemektedir. Anamenuye PopUp menuler eklenirken Durum ubuuna tipik olarak StatusLabel,progressBar, DropDownButton ve SplitButton nesneleri eklenebilir. phesiz durum ubuundaki en tipik eleman StatusLabel elemandr. Programc tipik olarak bu blme bir yaz yerletirir.StatusLabel ToolStripStatusLabel snf ile temsil edilmitir. Bu snf ToolStripStatusLabel snfndan tretilmitir. O da ToolStripItem Snfndan tretilmitir.

ToolStripItem

ToolStripLabel

ToolStripStatusLabe l Snfn Text propertysi burada grntlenecek yazy belirtir. Durum ubu u elemanlar iin en nemli zellik blmn yerleimine ilikindir. ToolStripStatusLabel snfnn Size eleman ile genilik ayarlanabilir. blm Default durumda AutoSize biimindedir. Eer genilik istenildii gibi ayarlanacaksa nce AutoSize propertysi False yap lmald r. nk Default olarak bu true durumdadr. Bu durumda blm otomatik olarak oraya yerletirilen yaznn genilii kadar genilie sahip olabilir. Genellikle Durumubuunun son eleman geri kalan tm blgeyi kaplamaktadr. Bunu salamak iin ToolStripStatus snfnn bool trden Spring propertysi true yap lmaldr. Blmlerin default olarak snr izgileri yoktur. Fakat toolStripStatusLabel snfnn BorderStyle propertysi ile snr izgileri istenildii gibi ayarlanabilir. Fakat bu property snr izgilerinin kmasna yol amaz. ncelikle snfn borderSides Propertysi ile snr izgilerinin izilmesini eklemek gerekir. BorderStyle BorderSides ile kenar izgilere izin verilmise etkili olur. Pek ok programda borderSides ile blmn drt tarafna snr izgileri yerletirilmekte borderStyle Sunken yaplmaktad r. ListView Kontrol: ListView kontrol stunlardan ve satrlardan olu maktad r. Aslnda bu kontroln ikonik kullanm da mevcuttur. Fakat burada klasik details kullanm ele alnmaktad r. Bu klasik kullanm iin Listwiev trnden nesne yaratldktan sonra ncelikle kontroln view proertysi details biime alnmald r. nk bu property default durumda largealcon biimindedir. ncelikle kontrole stunlar eklenmelidir. Herbir stun ColumnHeader snfyla temsil edilmektedir. Programc ColumnHeader nesnesini yaratp Listview snfnn Columns Propertysiyle belirtilen Collectiona ekler. Columns isimli property eleman ColumnHeaderCollection isimli bir snf trndendir. Bu snfn Collectiona ekleme yapan ColumnHeader parametreli ve String Parametreli Add fonksiyonlar vardr. String parametreli Add fonksiyonlar ColumnHeader nesnesini kendi ierisinde yaratp ekleme yapmaktadr. Bu durumda Kontrole bir stun eklemenin iki yolu olur. 247

Birincisi column Header nesnesini yaratarak eklemektir.


public partial class Form1 : Form { private ListView m_lv; public Form1() { InitializeComponent();

private ListView m_lv; //... m_lv = new ListView(); m_lv.Dock = DockStyle.Fill; m_lv.View = View.Details;

ColumnHeader ch = new ColumnHeader(); ch.Text = "Ad Soyad"; m_lv.Columns.Add(ch);

this.Controls.Add(m_lv); } }

kinci yol ise u ekilde olur: this.Controls.Add(Add Soyad); ColumnHeader snfnn Width property eleman Stunun geniliini belirlemekte kullanlr.
private ListView m_lv;

public Form1() { InitializeComponent();

m_lv = new ListView(); m_lv.Dock = DockStyle.Fill; m_lv.View = View.Details; m_lv.Columns.Add("File Name");

248

m_lv.Columns[0].Width = 100;

m_lv.Columns.Add("Size"); m_lv.Columns[1].Width = 100;

m_lv.Columns.Add("Date"); m_lv.Columns[2].Width = 100;

this.Controls.Add(m_lv); }

Column snfnn TextAllign propertysi ile stun balk yazsnn hizalanmas salanabilir. Stunlar eklendikten sonra artk sra satrlarn eklenmesine gelmitir. Satrlar Listview item nesneleri ile belirtilmitir. Listview kontrolnde aslnda bir anahtar stun vardr. Dier stunlar o anahtar stundaki bilgilerin detaylarn iermektedir. ListviewItem nesneleri ListviewSubItem nesnelerini tutmaktadr. ListViewItem FileName --------ListViewSubIte m Size --------ListViewSubIte m Date ---------

Grld gibi Listview kontrol ListviewItem nesnelerini tutan Collection gibidir. ListviewItem ise ListviewSubItem nesnelerini tutar. ListViewItem da ListviewSubItem da stunlarla temsil edilir. Listview snfnn Items isimli property eleman ListviewItem isimli Collection snf trndendir. Bu collection snf ListviewItem nesnelerini tutmaktadr. O halde zetle zetle Listview snfnn iki nemli Collection eleman vardr. Columns stunlar,items satrlar tutmakta kullanlr. ListviewItem snfnn SubItems isimli property eleman ise ListViewSubItems nesnelerini tutan bir collection trndendir. O halde bir satra eklemek iin u uzun yntem kullanlarbilir: 1. ListviewItem nesnesi yaratlr. 2. ListviewSubItem nesneleri yarat lr. 249

3. ListviewSubItem nesneleri ListviewItem snfnn SubItems propertysi yoluyla ListviewItem nesnesine eklenir. 4. ListviewItem nesnesi ise Listview snfnn Items propertysi yoluyla Listview nesnesine eklenir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace ListViewSample { public partial class Form1 : Form { private ListView m_lv; public Form1() { InitializeComponent(); m_lv = new ListView(); m_lv.Dock = DockStyle.Fill; m_lv.View = View.Details; m_lv.Columns.Add("File Name"); m_lv.Columns[0].Width = 100; m_lv.Columns.Add("Size"); m_lv.Columns[1].Width = 100;

m_lv.Columns.Add("Date"); m_lv.Columns[2].Width = 100;

ListViewItem lvi = new ListViewItem("A.DAT"); ListViewItem.ListViewSubItem lvsi1 = new ListViewItem.ListViewSubItem(); lvsi1.Text = "1234323"; ListViewItem.ListViewSubItem lvsi2 = new ListViewItem.ListViewSubItem(); lvsi2.Text = "10/12/2008"; lvi.SubItems.AddRange(new ListViewItem.ListViewSubItem[] { lvsi1, lvsi2 }); m_lv.Items.Add(lvi); this.Controls.Add(m_lv); } } } 250

Wizard ile yazlan kod: namespace ListViewWizard { partial class Form1 { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem(new string[] { "A.DAT", "1234354", "10/12/2008"}, -1); this.listView1 = new System.Windows.Forms.ListView(); this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); this.columnHeader3 = new System.Windows.Forms.ColumnHeader(); this.SuspendLayout(); // // listView1 // this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.columnHeader1, this.columnHeader2, this.columnHeader3}); this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] { 251

listViewItem1}); this.listView1.Location = new System.Drawing.Point(0, 0); this.listView1.Name = "listView1"; this.listView1.Size = new System.Drawing.Size(625, 264); this.listView1.TabIndex = 0; this.listView1.UseCompatibleStateImageBehavior = false; this.listView1.View = System.Windows.Forms.View.Details; // // columnHeader1 // this.columnHeader1.Text = "File Name"; this.columnHeader1.Width = 100; // // columnHeader2 // this.columnHeader2.Text = "Size"; this.columnHeader2.Width = 100; // // columnHeader3 // this.columnHeader3.Text = "Date"; this.columnHeader3.Width = 100; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(625, 264); this.Controls.Add(this.listView1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion private System.Windows.Forms.ListView listView1; private System.Windows.Forms.ColumnHeader columnHeader1; private System.Windows.Forms.ColumnHeader columnHeader2; private System.Windows.Forms.ColumnHeader columnHeader3; } }

ListView kontrolne satr eklemenin kolay bir yolu da vardr. Anmsanaca gibi ListView snfnn satrlar tutan Items property si ListView.ListViewItemCollection snf trndendir. Bizdaha nce bu snfn ListViewItem parametreli ya da string parametreli Add fonksiyonlarn kullanmtk. te ListViewItem snfnn keli panatez parametreli bir balang fonksiyonu da vard r. Programc bu 252

balang fonksiyonuna 0. stundan balayarak tm stunlara ilikin satr yazlarn verir. Fonksiyon bu yazlardan hareketle ListViewSubItem nesnelerini oluturarak eklemeleri yapar. rnein Bir dizin iindeki tm dosya bilgilerini bir ListView kontrolne yle aktarabiliriz. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ListViewSample { public partial class Form1 : Form { private ListView m_lv; public Form1() { InitializeComponent(); m_lv = new ListView(); m_lv.Dock = DockStyle.Fill; m_lv.View = View.Details;

m_lv.Columns.Add("File Name", 200); m_lv.Columns.Add("Size", 200); m_lv.Columns.Add("Date", 200); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file); m_lv.Items.Add(new ListViewItem( new string [] {fi.Name, fi.Length.ToString(), fi.CreationTime.ToString()})); } this.Controls.Add(m_lv); } } } ListView snfnn bool trden FullRowSelect property eleman satrn btnyle seilmesini salar. Propertinin default deeri false dur. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; 253

using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ListViewSample { public partial class Form1 : Form { private ListView m_lv; public Form1() { InitializeComponent(); m_lv = new ListView(); m_lv.Dock = DockStyle.Fill; m_lv.View = View.Details; m_lv.FullRowSelect = true;

m_lv.Columns.Add("File Name", 200); m_lv.Columns.Add("Size", 200); m_lv.Columns.Add("Date", 200); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file); m_lv.Items.Add(new ListViewItem( new string [] {fi.Name, fi.Length.ToString(), fi.CreationTime.ToString()})); } this.Controls.Add(m_lv); } } } ListWiew snfnn bool trden MultiSelect property si oklu seime olanak salamaktadr. Bu property nin de default durumu true dur. Listview snfnn SelectedItems isimli property eleman, seilmi elemanlar ListViewItem nesneleri tutan collection biiminde verir. Yine ListView snfnn SelectedIndices isimli property eleman bize seilmi olan elemanlarn indeks numaralarn int trden bir collection da toplayarak verir.
using System; using System.Collections.Generic;

using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; 254

using System.Text; using System.Windows.Forms; using System.IO; namespace ListViewSample { public partial class Form1 : Form { private ListView m_lv; public Form1() { InitializeComponent(); m_lv = new ListView(); m_lv.Bounds = new Rectangle(0, 0, 500, 400); m_lv.View = View.Details; m_lv.FullRowSelect = true;

m_lv.Columns.Add("File Name", 200); m_lv.Columns.Add("Size", 200); m_lv.Columns.Add("Date", 200); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file); m_lv.Items.Add(new ListViewItem( new string [] {fi.Name, fi.Length.ToString(), fi.CreationTime.ToString()})); } this.Controls.Add(m_lv); } private void button1_Click(object sender, EventArgs e) { string s = ""; foreach (ListViewItem lvi in m_lv.SelectedItems) { s += lvi.Text + "\n"; } MessageBox.Show(s); } } } ListView snfnn bool trden CheckBoxes isimli property eleman her satrda bir de seenek kutusu kartlmasn salar. Default biim false biimindedir. Bu biimde elemanlarn Checked yap lmas ile seilmesi ayn anlamda deildir. stersek biz ayrca CheckedItems ve CheckedIndecis propertyleri ile Checked yaplm elemanlarn listesini alabiliriz. 255

ListView snfnn bool trden GridLines isimli property eleman kontrolde zgara izgilerinin kmasn salar. Bu property nin de default durumu false biimindedir. Programc isterse bir satrn tamamnn zemin rengini ve yaz rengini deitirebilir. Bunun iin ListViewItem snfnn BackColor ve ForeColor property elemanlar kullanlmaktad r. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ListViewSample { public partial class Form1 : Form { private ListView m_lv; public Form1() { InitializeComponent(); m_lv = new ListView(); m_lv.Bounds = new Rectangle(0, 0, 500, 400); m_lv.View = View.Details; m_lv.FullRowSelect = true; m_lv.CheckBoxes = true; m_lv.GridLines = true;

m_lv.Columns.Add("File Name", 200); m_lv.Columns.Add("Size", 200); m_lv.Columns.Add("Date", 200); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file);

ListViewItem lvi = new ListViewItem(new string [] {fi.Name, fi.Length.ToString(), fi.CreationTime.ToString()}); m_lv.Items.Add(lvi); if (Path.GetExtension(fi.Name).ToLower() == ".exe") lvi.ForeColor = Color.Red;

256

} this.Controls.Add(m_lv); } private void button1_Click(object sender, EventArgs e) { string s = ""; foreach (int index in m_lv.SelectedIndices) { s += index.ToString()+ "\n"; } MessageBox.Show(s); } } } ListView snfnn eitli faydal Event Elemanlar vard r. ListView snfnn ColumnClick isimli event eleman bir stun balna tkland nda tetiklenir. Oluan mesajda biz tklanm olunan stunun numarasnda elde edebiliriz. Control n ItemActivate isimli Event eleman bir eleman seildiinde tetiklenir. Fakat active etme ileminin tek tklamaylam yoksa ift tklamaylam yap laca snfn Activation isimli property eleman yla belirlenmektedir. Ayrca tpk ListBox kontrolnde olduu gibi bu kontrolnde Changed isimli event eleman vard r. Bu event seili eleman deitiinde tetiklenmektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ListViewSample { public partial class Form1 : Form { private ListView m_lv; public Form1() { InitializeComponent(); m_lv = new ListView(); m_lv.Bounds = new Rectangle(0, 0, 500, 400); m_lv.View = View.Details; m_lv.FullRowSelect = true; m_lv.GridLines = true; m_lv.SelectedIndexChanged += new EventHandler(m_lv_SelectedIndexChanged);

257

m_lv.Columns.Add("File Name", 200); m_lv.Columns.Add("Size", 200); m_lv.Columns.Add("Date", 200); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file);

ListViewItem lvi = new ListViewItem(new string [] {fi.Name, fi.Length.ToString(), fi.CreationTime.ToString()}); m_lv.Items.Add(lvi); if (Path.GetExtension(fi.Name).ToLower() == ".exe") lvi.ForeColor = Color.Red;

} this.Controls.Add(m_lv); } void m_lv_SelectedIndexChanged(object sender, EventArgs e) { string s = ""; foreach (int index in m_lv.SelectedIndices) { s += index.ToString() + "\n"; } MessageBox.Show(s); } private void button1_Click(object sender, EventArgs e) { string s = ""; foreach (int index in m_lv.SelectedIndices) { s += index.ToString()+ "\n"; } MessageBox.Show(s); } } } Stun balklarna tkland nda ilgili stuna gre sraya dizme ok uygulanan bir yntemdir. Fakat bu ilem otomatik yaplmamaktadr. Bu ilemi gerekletirmek iin u ilemler uygulanmaldr. 1. Sraya dizme ilemi ListView snfnn sort fonksiyonuyla yap lmaktadr. Fakat programcnn daha nce baz hazrlklar yapmas gerekebilir. Programc bu sort fonksiyonunu phesiz ColumnClick eventi olutuunda aracaktr. 2. Programcnn Icomparer arayzn destekleyen bir snf oluturmas gerekir. Sonra bu sunuf trnden bir nesne yaratarak ListView snfnn ListViewItemSorter property sine atama 258

yapmas gerekir. ICompare arayznn Compare isimli tek bir fonksiyonu vardr. int Compare(Object x, Object y) Sort fonksiyonu aslnda sraya dizme srasnda karlatrma yaparken iki ListView nesnesini bu fonksiyona parametre yapmaktadr. Yani programc Icompare arayz destekleyen bu snfta bu fonksiyonu yazarken Fonksiyonun iki parametresinde ListViewItem nesnelerinin olduunu bilmelidir. Bu fonksiyon yle bir biimde yazlmaldrki Birinci yaz ikinci yazdan bykse pozitif herhangi bir deere kkse negatif herhangi bir deere ve eitse sfr deerine geri dnsn. 3. Programcnn ilgili stuna gre sraya dizme ilemi yapabilmesi iin Compare fonksiyonunu o stuna gre yazmas gerekir. O halde tipik olarak Icomparer arayzn destekleyen snfa stun numaras veri eleman olarak geirilebilir. Compare fonksiyonu da bu veri elemanna bakarak alabilir. 4. ListView snfnn Sorting isimli property eleman bykten k emi, yoksa kkten byemi sraya dizileceini belirtir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Collections; namespace ListViewSample { public partial class Form1 : Form { private ListView m_lv; public Form1() { InitializeComponent(); m_lv = new ListView(); m_lv.Bounds = new Rectangle(0, 0, 600, 400); m_lv.View = View.Details; m_lv.FullRowSelect = true; m_lv.GridLines = true; m_lv.ColumnClick += new ColumnClickEventHandler(m_lv_ColumnClick);

m_lv.Columns.Add("File Name", 200); m_lv.Columns.Add("Size", 200); m_lv.Columns.Add("Date", 200); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file);

ListViewItem lvi = new ListViewItem(new string[] {fi.Name, fi.Length.ToString(), 259

fi.CreationTime.ToString()}); m_lv.Items.Add(lvi); if (Path.GetExtension(fi.Name).ToLower() == ".exe") lvi.ForeColor = Color.Red;

} this.Controls.Add(m_lv); } void m_lv_ColumnClick(object sender, ColumnClickEventArgs e) { m_lv.ListViewItemSorter = new MyComparer(e.Column); m_lv.Sort(); } private void button1_Click(object sender, EventArgs e) { string s = ""; foreach (int index in m_lv.SelectedIndices) { s += index.ToString()+ "\n"; } MessageBox.Show(s); } } class MyComparer : IComparer { private int m_cno; private static int ms_oldcno; private static bool ms_sortOrder = true; public MyComparer(int cno) { if (cno != ms_oldcno) { ms_sortOrder = false; } else ms_sortOrder = !ms_sortOrder; m_cno = cno; ms_oldcno = cno; } public int Compare(object x, object y) { ListViewItem lvi1; ListViewItem lvi2; 260

if (ms_sortOrder) { lvi1 = (ListViewItem)y; lvi2 = (ListViewItem)x; } else { lvi1 = (ListViewItem)x; lvi2 = (ListViewItem)y; } switch (m_cno) { case 0: return string.Compare(lvi1.SubItems[m_cno].Text, lvi2.SubItems[m_cno].Text); case 1: return int.Parse(lvi1.SubItems[m_cno].Text) - int.Parse(lvi2.SubItems[m_cno].Text); case 2: DateTime dt1 = DateTime.Parse(lvi1.SubItems[m_cno].Text); DateTime dt2 = DateTime.Parse(lvi2.SubItems[m_cno].Text); return DateTime.Compare(dt1, dt2); } return 0; } } } Anahtar Notlar: Tpk int , long gibi temel yaplarn olduu gibi DateTime yapsnn da parse fonksiyonu vard r. Bu fonksiyon bizden tarih ve zaman bilgisini yaz olarak alr ve onu DateTime yap sna dn trr. Ayrca iki DateTime yapsn karlatrarak pozitiflik ve negatiflik durumuna gre int deere geri dnen DateTime yapsnn static Compare fonksiyonu da vardr. DateTime yap snn Parse fonksiyonunun yaz y hangi formatta alacana ilikin detayl bilgi MSDN dkumanlarndan izlenebilir. .Nette Veri Taban lemleri: Bilgileri belirli bir dzene gre tutan ve zerinde baz ilemlerin yap lmasna olanak salayan bir ya da birden fazla dosyaya veri taban denilmektedir. Veri taban ilemleri temel olarak yntemle gerekletirilebilir. 1. lemler do rudan aa seviyeli dosya snflar ve fonksiyonlar kullanlarak gerekletirilebilir. rnein biz birka yz rencinin bilgilerini tutacaksak ve karmakta bir sorgulama yapmayacaksak bu manuel yntemi uygulayabiliriz. 2. Programc zel yazlm veri taban ktphanelerini kullanabilir. zellikle 90 l yllara kadarki dnem iinde bu tr zmler kullanlyordu. Yani szkonusu olan ktphanede kayt ekleyen, kayt silen, arama yapmay salayan fonksiyonlar vard. rnein: Ctrieve, DbVista, Btrieve ve DB ktphaneleri yo un olarak kullanlm tr. Veri tanab ktphaneleri Veri Taban Ynetim Sistemlerine gre(VTYS) ok daha hzl zm sunmaktad r. Fakat bu ktphaneler esnek deildir ve data formatna skca balanr. Bu tr ktphaneler VTYS nin sundu u pek ok kolayl sunmamaktad r. 3. Programc tm veri taban ilemlerini ismine VTYS(Database Managment System) denilen bir yazlma b rakarak hereyi o yazlma yaptrabilir. Gnmzde arlkl olarak kullanlan 261

yntem budur. .Nette de temel olarak bu yntemin kullanlmasna ynelik zm sunulmutur. Veri Taban Ynetim Sistemleri(VTYS): Veri taban ynetim sistemleri veri taban ilemlerini yksek seviyeli bir biimde gerekletirmek iin kullanlan zel yazlmlardr. Bu tr yazlmlar tipik olarak ilemlerin dosya ksm n kendi zerlerine alp kullancnn aa seviye dosya formatndan bamsz bir biimde veri tabanna erimesini mmkn hale getirmektedir. Kendi ilerinde pek ok arac iermektedir. Pek ok VTYS inde ynetim ilemi komut satrnda ya da grsel olarak gerekletirilebilir. Verilerin gsterimine ilikin eitli aralar bulunabilir ve adeta programc herhangi bir programlama diline gereksinim duymadan veri taban ilemlerini gerekletirebilir. Bu tr yazlmlar veri btnl n korumak iin zel mekanizmalara sahiptir ve gvenilir bir ortam sunmaktadr. VTYS lerinin o u yine ya hep ya hi biiminde transaction(Bir gurup ilemi ya hep ya hi biiminde yapmak) ilemlerini salamaktadr. VTYS leri tipik olarak Client ve Server alan sistemlerdir. Veri tanab ynetim sisteminden hizmet alan programlar client programlardr. VTYS leri kendisi server sistemlerdir. Client Server ile balant salar ve ondan baz ilemleri yapmasn ister. Server bu ilemleri Client iin yapar sonular client a gnderir. phesiz veri tanab ynetim sistemleri ayn anda yakn ya da uzak pek ok client a hizmet verebilmektedir. VTYS lerinden en ok kullanlanlar Oracle firmasndan oracle Microsoft firmasndan SQL Server IBM in DB2 su Sybase, Progres, Informix Bedava olanlardan en ok tercih edileni MySQL dir. SQL kullancnn VTYS i yaptrmak iin kulland standart bir sorgulama dilidir. rnein kullanc veri tabanna bir kayt eklemek istediinde bunu VTYS mine bir SQL komutu olarak iletir. VTYS bu komutu yorumlayarak kullancnn isteini yerine getirir. SQL asl ii yapan dil deildir. Gerek veri taban ilemleri C de ve C++ yap lan kodlar la yap lmaktadr. SQL yalnzca istek bildirmekte kullanlan bir dildir. VTYS lerinin gerek veri taban ilemlerini yapan blmlerine motor ksm denir. Bugn VTYS lerinin hemen hepsi standart SQL komutlarn desteklemektedir. SQL bu nedenle standart bir arayz olarak kullanlmaktadr. VTYSlerini Programlama Yoluyla Kullanlmas: Daha nceden de belirtildii gibi VTYS leri kendi iinde pek ok arac ieren byk yazlmlardr. Bunlarn Etkin kullanlmas ve ynetimi iin zel eitimlere gereksinim duyulmaktadr. Bir VTYS konusunda uzmanlam kiiye Veritaban Yneticisi(Database Administrator) denilmektedir. Fakat veri taban ynetim sistemlerinin tipik dier bir kullanm da baka bir programlama dilinden ya da ortamdan onlara i yaptrmak amald r. rnein bir C Ya da C# programcs VTYS ine balant kurup kayt ekleme, kayt silme, sorgulama gibi ilemleri ona yaptrabilir. Kursumuzda bu VTYS leri .netten bu amala kullanlacaktr. Bylesi bir kullanm iin temel bir SQL bilgisi yeterlidir. VTYS yneticisi seviyesinde bir bilgiye gereksinim yoktur. .Netin Veri Taban Snflar ve ADO.Net(Active Data Object): Microsoft .net ortam iinde VTYS iyle balant kurmakta kullanlan ona SQL de komut gndermekte kullanlan, sonular almakta kullanlan bir grup snf bulundurmaktadr. VTYS iyle kurulan iliki ADO teknolojine dayand iin bu snflara ADO.Net snflar denilmektedir. Veritaban ilemlerine ynelik snflarn ismi System.Data isim alannda ya da bu isim alannn iindeki isim alanlar iindedir. Microsoft farkl VTYS lerini benzer bir mantk iinde kullanmay hedefleyen bir tasarm yelemitir. Yani VTYS deise de bizim konuya yaklamm z kulland mz snflar ve 262

fonksiyonlar birbirine ok benzemektedir. Bylece daha kolay bir renme salamaktad r. likisel Veritaban Kavram: Veritabanlarnn yksek seviyeli bir biimde eleanlnmasna ynelik eitli veri taban modelleri newrilmitir. Bunlardan en ok tercih edilen ve kullanlan likisel(Relational) veritaban modelidir. likisel veritabannda bir veritaban tablolar biimindedir. Bir tablo stunlardan ve satrlardan oluur. Stunlara alan(field) satrlara kayt(record) denilmektedir. Tablolarn ve stunlarn birer ismi vardr. Stunlarda bulunan bilgilerin trleri vardr. Bir vertaban pek ok tablodan oluabilir. phesiz veritabanndaki tablo ilikisi kullanc algsna yneliktir. Bu durum diskteki fiziksel model hakknda bir fikir veremez. VTYS bu tablolarn oluturulmas ve ynetiminden sorumludur. Veritaban ilemlerinin anahtar noktalarndan biri sorgulama(query) ilemidir. Sorgulama belirli koullar salayan kaytlar zerinde ilem yapmaktr. rnein Eskiehirde doup ya 21 den byk olanlarn listesinin alnmas Temel SQL Komutlar: SQL komutlar eitli alt kategorilerde incelenebilir. ADO.Net programcs iin temelSQL bilgisi yetrerlidir. SQL komutlarnn genel biimi kark olmasna karn burada temel kullanmlar zerinde durulacaktr. Komutlardan bazlar kayt geri dndrmez, bazlar kayt geri dndrr. rnein Select komutu bize bir takm kaytlar geri dndrmektedir. Fakat rnein Delete komutu yalnzca i yapmaktadr. SELECT Komutu: Select komutu belirli koulu salayan kaytlarn elde edilmesi iin kullanlmaktadr. Select komutuyla belirli bir tablodan ya da tablolardan belirli stunlara ilikin belirli koullar salayan kaytlar elde edilebilir. Bir SQL komutu eitli cmleciklerin bir araya gelmesinden olu turulur. Bu cmleciklerin en ok kullanlan WHERE cmleciidir. Anahtar Notlar: SQL standarlara gre byk kk harf duyarll olan bir dil deildir. Fakat SQL szcklerinin byk harflerle yazlmas geleneksel ve iyi bir tekniktir. SELECT anahtar szcn tablodaki hangi srunlarn elde edileceine ilikin bir liste izler. Yani biz ko ulu salayan kaytlarn yalnzca belirli stunlarn elde edebiliriz. Burada yld z * tm stunlar anlam na gelmektedir. Sonra from anahtar szc ve hangi tablolar zerinde ilem yap lacana ilikin tablo listesi gelir. Nihayet koul iin bir WHERE cmlecii getirilebilir. O halde SELECT komutunun tipik biimi yledir: SELECT <stun listesi> FROM <Tablo Listesi> WHERE<Koul> Buradaki kullanm genel biim deil tipik biimdir. rnein: SELECT PersonName, PersonNo FROM Person Burada ko ul belirtilmedii iin Person tablosundaki tm kaytlar isim ve numaralar elde edilmitir. rnein: SELECT * FROM Person WHERE PersonName='Kaan Aslan' Burada Person tablosundaki ismi Kaan Aslan olan tm kaytlar yani satrlar elde edilmektedir. Koul ksm mantksal operatrlerle detayland rlabilir. rnein: SELECT * FROM Person WHERE Age>20 AND BirthPlace = 'Eskiehir' LIKE operatr Joker karekterlerin kullanlmasna olanak salamaktadr. rnein: SELECT * FROM Person WHERE Age>20 AND BirthPlace = 'Eskiehir' AND NAME LIKE'A%' Burada ismi A ile balayan ya 20 den byk olanlarn listesi elde edilmektedir. SELECT komutuna baka cmleciklerde eklenebilir. rnein ORDER BY<Stun Listesi> cmlecii elde edilen kaytlarn hangi stunlara gre sral olacan belirlemektedir. lk belirtilen stun ayn ise dier stunlar etkili olur. rnein: SELECT * FROM Person WHERE PersonName LIKE 'A%' ORDER BY PersonNo Burada ismi A ile balayanlarn listesi valnmaktadr fakat bu liste numara srasna gre dizilmitir. 263

INSERT INTO Komutu: Bu komut veritabanna kayt eklemek iin kullanlr. Tipik biimi yledir. INSERT INTO <Tablo smi>(<Stun Listesi>) VALUES (<Deer Listesi>) rnein: INSERT INTO Person (PersonName, PersonNo) VALUES ('Kaan Aslan, 120) Tablo isminden sonra parantez almazsa tm stunlar anlalr. Stun isimlerinin tablodaki sraya gre olmas gerekmez. Fakat deerlerin srasyla stunlara karlk gelmesi gerekmektedir. DELETE Komutu: Delete komutu tipik olarak belirli koullar salayan kaytlarn silinmesi amacyla kullanlmaktad r. Komutlarn tipik biimi yledir. DELETE FROM <Table Listesi> WHERE <Koul> rnein: DELETE FROM Person WHERE Name='Kaan Aslan' AND BirthPlace = 'Eskiehir' UPDATE Komutu: UPDATE komutu ko ulu salayan kaytlardaki baz stunlarn deitirilmesi iin kullanlr. rnein tm Kaan Aslan isimlerini Kaan Arslan yapmak iin Update komutunu kullanabiliriz. UPDATE komutunun tipik biimi yledir. UPDATE <Toblo Listesi> SET<Stun = De er Listesi> WHERE <Koul> rnein: UPDATE Person SET PersonName= 'Kaan Aslan' WHERE PersonName = 'Kaan Arslan' phesiz UPDATE ile birden fazla stun zerinde deiiklik yaplabilir. rnein: UPDATE Person SET PersonName= 'Kaan Aslan' , BirthPlace='Eskiehir' WHERE PersonName = 'Kaan Arslan' CREATE DATABASE Komutu: Sfrdan yeni bir Veritaban yaratmak iin kullanlr. Tipik biimi yledir. CREATE DATABASE <sim> rnein: CREATE DATABASE Personel_Takip CREATE TABLE Komutu: Bir veritaban tablosu olu turmak iin kullanlr. Bu komut veritabanna yeni bir tablo yaratmak iin kullanlr. Tablo yaratlrken tabloya bir isim verilir. Sonra tablodaki tm stun isimleri ve bunlarn trleri belirtilir. SQL de standart baz trler vard r. Fakat Veritaban Ynetim Sistemine bal olarak baka ek trlerde sz konusu olabilir. Tipik trler unlardr. INT : Tam say Tr DEC : Gerel Say turu CHAR : n tane karakter tr VARCHAR : deiken karakter DATE : Tarih DATETIME : Tarih Zaman CREATE TABLE komutunun tipik kullanm yledir. CREATE TABLE <Tablo smi> (<sim ve tr listesi>) rnein: CREATE TABLE Person(PersonName VARCHAR(32), PersonNo INT) USE Komutu: USE komutu zaten yaratlm olan bir veritabann kullanmak iin kullanlr. Genel biimi yledir: USE <Veritaban smi> rnein: USE Personel_Takip Anahtar Notlar: Normal olarak SQL komutlar ; ile sonlandrlr. .Nette de komut satrnda da ayn satr zerine birden fazla komut verilebilir. Fakat ileride grlecei gibi .Nette tek bir komutu ; ile sonlandrmak zorunda deiliz. ADO.net Balantl ve Balantsz Snflar: Ado.net balantsz snflar veritaban tablolarn bellekte temsil etmek iin kullanlan snflard r. Bu snflar kullanabilmek iin VTYS ile balant kurmu olmamz gerekmez. Halbuki balantl snflar VTYS ile i yaptrmak iin kullanlan snflardr. Veritaban Tedariki Snflar: Ado.net snf sisteminde Veritaban ne biimde olursa olsun 264

ilemler benzer biimde yaplmaktadr. Veritaban ynetimsistemleri iin farkl tedariki snflar vardr. Bu tedariki snflar ortak aratzlweri destekledikleri iin benzer kullanmlara sahiptir. Microsoft sqlserver iim sqlXXX biiminde isimlendirilmi tedariki snflar, Access jet motoru iin, Excel jetmotoru iin Mysql iin genel amal OLEDBXXX tedariki snflarn, ODBC balant s iin ODBCXXX tedariki snflarn Oracle ilemleri iin OracleXXX tedariki snflarn bulundurmaktad r. rnein biz Access veritaban ile OLEDB tedariki snflarn kullanarak ilemlerini yapabiliriz. Balant iin OLEDBCollection snflarn kullanrz. Fakat VTYS SQL Server olsayd SQLConnection snfn kullanacaktk. Bu durumda rnein biz rneklerimizi OledbXXX isi, ODBCxxx biiminde dier tedariki versiyonlar da vard r ve kullanmlar birbirine benzer. Oledb ve odbc yntemleri genel yntemlerdir. Pek ok VTYS zerinde bu tedariki snflar yoluyla ilem yap labilir. rnein biz odbc tedariki snflar ile Oracle ilemleri yapabiliriz. nk odbc genel bir yntemdir. Fakat oracle tedariki snflar bu veritaban iin zel dzenlenmi vve daha hzl sonu verir. Benzer biimde SqlServer veritaban iinde sqlXXX tedariki snflarn kullanmak yerinde olur. Access ve MySQL VTYS ler iin Oledb tedariki snflar kullanlabilir. VTYSleri ile Balantnn Kurulmas: VTYS client server biimide alan sistemlerdir. Dolaysyla onlara i yaptrabilmek iin nce bir balantnn salanmas gerekir. Bunun iin tedarikiYYY olmak zere YYYConnection snflar kullanlr. Yani SqlServer iin SqlConnection, Oledb iin OledbConnection Odbc iin OdbcConnection, Oracle iin OracleConnection snflar kullanlmaldr. Connection snflar DbConnection isimli bir Abstract snftan tretilmitir. Bu abstrac snfta IDbConnection arayzn desteklemektedir. IDbConnection

DbConnection

OledbConnection

SqlConnection

OdbcConnection

OracleConnectio n

Grld gibi tedariki snflarn ortak fonksiyonlar DbConnection snfnda toplanmt r. Buradaki en genel ilemler IDbConnection arayzyle temsil edilmektedir. VTYS ne balanrken Client programn balantnn nitelii hakknda Server a eitli bilgiler iletmesi gerekmektedir. Ado.nette bu bilgiler string trnden ConnectionString denilen property ile temsil edilmitir. ConnectionString property si IdbConnection arayznn bir propertysidir. Dolaysyla tm tedariki snflarda bu propertynin bulunmas zorunludur. Balant yazsnn format VTYS inden VTYS ine farkllk gsternektedir. Yaz genel olarak ; ile ayrlm blmlerden oluur. Bu ; arasndaki blmler x=y biimde ifadelerden olumaktad r. Fakat kesin format kark olabilmektedir ve bunun iin dkumanlara bavurulmald r. rnein Access jetmoturuna balanmak iin tipik olarak aadaki gibi bir balant yazs oluturulur. Provider=Microsoft.Jet.OLEDB.4.0; Data Source = c:\bin\test.mdb Grld gibi Oledb tedarikisinde balant yazs iinde bir provider blm olmak zorundad r. 265

nk Oledb genel bir tedarikidir. Ve Oledb snflaryla Access, Oracle, Sql gibi VTYS leri ile ilem yap labilir. Data Source Access veritaban iin ilgili mdb dosyasnn yol ifadesini ierir. YYYConnection snflarnn default balang fonksiyonlar ve String parametreli balang fonksiyonlar vardr. Default balang fonksiyonlar ile nesne yaratlrsa balant yazs daha sonra ConnectionString property si ile girilmelidir. Ya da programc balant yazsn Oledb connection snfnn balang fonksiyonunda da belirtebilir. Balant yazs programn iinde string olarak verilebilecei gibi bir kaynak biiminde Application Setting iinde Ya da Registery de saklanabilir. Programc balant yazsn set ettikten sonra gerek anlamda balanty YYYConnection snflarnn Open fonksiyonuyla kurar. Openfonksiyonu IDbConnection arayznden gelmektedir. Balantnn mmkn oldu u kadar ksa sre iinde kapatlmas iyi bir tekniktir. Gerektiinde yeniden Open ilemi yaplabilir. Open ile balantnn kurulmas srasnda pek ok nedenden dolay baarszlk sz konusu olabilir. Programcnn Open fonksiyonunu try catch bloklar iinde armas uygun olur. Balanty kapatmak iin Close fonksiyonu kullanlr. Bu fonksiyonda IDbConnection arayznden gelmektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace DataBaseSample { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; "+ @"Data Source=E:\DotNetApp-1317\DataBaseSample\Person.mdb"; } private void button1_Click(object sender, EventArgs e) { try { m_dbConnection.Open(); } catch (Exception ex) 266

{ MessageBox.Show(ex.Message); } } } } YYYConnection snflarnn State isimli property elemanlar IdbConnection arayznden gelmektedir. Bu property balant durumunu belirten bir Enum trndendir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace DataBaseSample { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; "+ @"Data Source=E:\DotNetApp-1317\DataBaseSample\Person.mdb"; } private void button1_Click(object sender, EventArgs e) { MessageBox.Show(m_dbConnection.State.ToString()); try { m_dbConnection.Open(); //... MessageBox.Show(m_dbConnection.State.ToString());

m_dbConnection.Close(); } catch (Exception ex) 267

{ MessageBox.Show(ex.Message); } } } } YYYConnection snflarnn ConnectionTimeout isinli property elemanlar IDbConnection arayznden gelmektedir. OleDB iin zamanam default 15 sn'dir. Yani 15 sn'yeye kadar balant salanamazsa Exception oluur. YYYConnection snflarnn dier elemanlar MSDN dkumanlarndan izlenebilir. VTYS'ine SQL Komutlarnn Uygulanmas: Daha nceden de belirtildii gibi VTYS i SQL Arayzyle ynetilmektedir. .net programcs tipik olarak yaptrmak istedii ilemleri SQL komutlarna dntrr ve bunlar Ado.net snflaryla VTYS ine gnderir. SQL komutlarndan bazlar rnein tipik olarak Select komutu bize kaytlar geri dndrr. Bu komutlar uyguland nda VTYS nin verdii kaytlar bizim bir yerde saklamam z gerekir. Kaytlarn elde edilerek saklanmas iin zel balantsz snflar kullanlmaktadr. Bu konuya daha sonra deinilecektir. O halde imdilik biz Insert, Update, Delete gibi kayt geri dndrmeyen komutlar uygulayacaz. Bir Sql komutu YYYCommandsnf trnden bir nesne ile temsil edilmektedir. YYYCommand snflar DbCommand isimli bir Abstract snftan tretilmitir. Bu snfta IDbCommand arayzn desteklemektedir.

IDbCommand

DbCommand

OleDbCommand

SqlCommand

OdbcCommand

OracleCommand

Programc rnein Oledb snf trnden bir nesne yaratr ve Sql komutunu bu nesneye yerletirir. YYYCommand snflarnn String trnden CommandText isimli property elemanlar IdbCommand arayznden gelmektedir ve Sql komutunu temsil etmektedir. Aslnda YYYCommand snflarnn String parametreli balang fonksiyonlar da vardr. Sql komutunu CommandText propertysine yerletirmek yerine bu balang fonksiyonuna parametre olarak vermekte ayn anlamdadr. CommandText olu turulduktan sonra artk sra Sql komutlarnn uygulanmasna gelmitir. YYYCommand nesneleri Connection nesnesini de kullanmaktad r. Bu nedenle programcnn YYYcommand snflarnn Connection propertylerine balant nesnelerini de vermesi gerekir. rnein: OleDbCommand dbCommand = new OleDbCommand; 268

dbCommand.Connection = m_dbConnection; dbCommand.CommandText = INSERT INTO Info(PersonName, PersonNo) VALUES ('Bob Marley', 632); YYYCommand snflarnn aslnda Connection deerini de parametre olarak alan balang fonksiyonu da vardr. Yani yukardaki kod ylede yazlabilirdi. OleDbCommand dbCommand = new OleDbCommand(INSERT INTO Info(PersonName, PersonNo) VALUES ('Bob Marley', 632), m_dbConnection); Nihayet SQL komutu YYYCommand snflarnn ExacuteNonQuery fonksiyonuyla altrlr.(Fonksiyonun yanl isimlendirildiini Microsoft kabul etmektedir.) Fonksiyon Int geri dn deerine sahiptir ve ilemden etkilenen kayt saysn geri dndrmektedir. Komutun iletilmesi srasnda Excepiton oluabilir. ExacuteNonQuery fonksiyonu uygulanmadan nce balant Open fonksiyonuyla almald r. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace DataBaseSample { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; "+ @"Data Source=E:\DotNetApp-1317\DataBaseSample\Person.mdb"; } private void button1_Click(object sender, EventArgs e) { MessageBox.Show(m_dbConnection.State.ToString()); try { m_dbConnection.Open(); OleDbCommand dbCommand = new OleDbCommand("INSERT INTO Info(PersonName, PersonNo) VALUES('Bob Marley', 632)", m_dbConnection);

269

dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace DataBaseSample { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; "+ @"Data Source=E:\DotNetAppBasic\DataBaseSample\Person.mdb"; } private void button1_Click(object sender, EventArgs e) { try { m_dbConnection.Open(); OleDbCommand dbCommand = new OleDbCommand( "DELETE FROM Info WHERE PersonNo > 750", m_dbConnection); int result = dbCommand.ExecuteNonQuery(); MessageBox.Show(result.ToString()); m_dbConnection.Close(); 270

} catch (Exception ex) { MessageBox.Show(ex.Message); } } } } SQL Komutlarnda Parametre Kullanm: phesiz veritaban uygulamalarnda insert into, update, slect gibi SQL komutlar program iinde static bir biimde oluturulmaz kullancnn girdii bilgiler kullanlarak oluturulur. Bu durumda sorgulama ekranlarndan alnan bilgiden SQL cmlelerinin oluturulmas gerekir. Ancak bu yazlarn olu turulmas ok kolay deildir. Anahtar Notlar: Bir form ilk kez alrken form snfna Load isimli mesaj gnderilir. Baz programclar form ald nda yaplacak ilk ilemleri bu Load eventinde gerekletirmektedir. Load Eventi olutuunda pencere yaratlmtr. Fakat henz grnr durumda deildir. rnek: Windows forms kullanarak programatik komut satr oluturupprograma kendisi kayt eklemek ve silmek AddRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class AddRecordForm : Form { public AddRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); 271

textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } } DataBaseMainForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace CSD { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); } private void addRecordToolStripMenuItem_Click(object sender, EventArgs e) 272

{ AddRecordForm arf = new AddRecordForm(); if (arf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES('" + arf.PersonName + "'," + arf.PersonNo.ToString() + ")"; try { m_dbConnection.Open(); dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); }

} } private void Form1_Load(object sender, EventArgs e) { m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; " + @"Data Source=E:\DotNetAppBasic\DataBaseRecordProc\Person.mdb"; } private void deleteRecordToolStripMenuItem_Click(object sender, EventArgs e) { DeleteRecordForm drf = new DeleteRecordForm(); if (drf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "DELETE FROM Info WHERE PersonName = '" + drf.PersonName + "' AND PersonNo = " + drf.PersonNo.ToString(); try { m_dbConnection.Open(); 273

int result = dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); if (result == 0) { MessageBox.Show("Cannot find record"); return; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } } DataBaseDeleteForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class DeleteRecordForm : Form { public DeleteRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; 274

} private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } } SQL komutlarnda parametre kullanmak iin nce komut yazs parametreyi belirten bir yer tutucuyla olu turulur. Bu yer tutucu Oledb tedariki snflarnda ? karakteri SQL Server ve ORACLE tedariki snflarnda Add parametre ismi eklindedir. rnein Oledb iin parametrik bir INSERT INTO komutu yle yazlr. INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?) Sql Server ve Oracle tedarikilerinde yertutucu yalnzca bir soru iareti karekteri deildir bir isim de iermektedir. rnein:INSERT INTO Info(PersonName, PersonNo) VALUES(@Name, @No) Yertutucular yerine yerletirilecek olan yazlar YYYParameter isimli snf nesneleri ile temsil edilir. Programc herbir yer tutucu iin bir YYYParameter nesnesi yaratr ve bu nesneleri YYYCommand snfnn parameter isimli collection elemanna ekler. Parameter isimli collection eleman YYYParameterCollection isimli bir snf trndendir. OleDb tedariki snflarnda yertutucu yalnzca bir ssoru iaretiyle belirlendii iin bu collectiona belirleme sras nemlidir. Halbuki Sql Server ve Oracle tedariki snflarnda yertutucularla elendirmeler sraya gre deil isme gre yap lr. YYYParameter snfnn ParameterName isimli property eleman yertutucu parametrenin ismini, Value isimli property eleman yertutucu elemann deerini belirtir. Value propertysi object trnden olduu iin bizim bu value propertysi iindeki deerin trn de ayrca belirtmemiz gerekir. Bunun iin YYYParameter snfnn DbType isimli property eleman kullanlr. Aslnda YYYParameter snfnn eitli balang fonksiyonlar bu deerleri parametre olarak almaktadr. OleDb tedarikisinde ParamterName kullanlmamaktadr bo geilebilir. rnein OleDb iin bir parametre ilemi Aadaki ekilde yap labilir AddForm.cs using System; using System.Collections.Generic; 275

using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class AddRecordForm : Form { public AddRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } 276

} MainForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace CSD { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); } private void addRecordToolStripMenuItem_Click(object sender, EventArgs e) { AddRecordForm arf = new AddRecordForm(); if (arf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?)"; OleDbParameter param1 = new OleDbParameter(null, arf.PersonName); OleDbParameter param2 = new OleDbParameter(null, arf.PersonNo.ToString()); dbCommand.Parameters.AddRange(new OleDbParameter[] { param1, param2 });

try { m_dbConnection.Open(); dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); }

277

catch (Exception ex) { MessageBox.Show(ex.Message); }

} } private void Form1_Load(object sender, EventArgs e) { m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; " + @"Data Source=E:\DotNetAppBasic\DataBaseRecordProc\Person.mdb"; } private void deleteRecordToolStripMenuItem_Click(object sender, EventArgs e) { DeleteRecordForm drf = new DeleteRecordForm(); if (drf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "DELETE FROM Info WHERE PersonName = '" + drf.PersonName + "' AND PersonNo = " + drf.PersonNo.ToString(); try { m_dbConnection.Open(); int result = dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); if (result == 0) { MessageBox.Show("Cannot find record"); return; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } } DeleteForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; 278

using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class DeleteRecordForm : Form { public DeleteRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } }

279

YYYParameterCollection snfnn eitli Add fonksiyonlar kendi iinde YYYParameter nesnelerini olu turup zaten eklemektedir. Bu durumda yukardaki parametre oluturma ilemi ylede yaplabilirdi. AddRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class AddRecordForm : Form { public AddRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { 280

get { return int.Parse(textBox2.Text); } } } } MainRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace CSD { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); } private void addRecordToolStripMenuItem_Click(object sender, EventArgs e) { AddRecordForm arf = new AddRecordForm(); if (arf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?)"; dbCommand.Parameters.Add(null, arf.PersonName); dbCommand.Parameters.Add(null, arf.PersonNo.ToString()); try { m_dbConnection.Open(); dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); 281

} catch (Exception ex) { MessageBox.Show(ex.Message); }

} } private void Form1_Load(object sender, EventArgs e) { m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; " + @"Data Source=E:\DotNetAppBasic\DataBaseRecordProc\Person.mdb"; } private void deleteRecordToolStripMenuItem_Click(object sender, EventArgs e) { DeleteRecordForm drf = new DeleteRecordForm(); if (drf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "DELETE FROM Info WHERE PersonName = '" + drf.PersonName + "' AND PersonNo = " + drf.PersonNo.ToString(); try { m_dbConnection.Open(); int result = dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); if (result == 0) { MessageBox.Show("Cannot find record"); return; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } } DeleteRecordForm.cs 282

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class DeleteRecordForm : Form { public DeleteRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } 283

} } Yukardaki uygulama Sql Server da yap lsayd isimli bir arama sz konusu olacakt. Bu durumda ekleme ileminin sras nemli deildir. SqlCommand dbCommand = new SqlCommand(); dbCommand.Connection = m_Conection;
dbCommand.CommandText = INSERT INTO Info(PersonName, PersonNo) VALUES(@Name, @No);

dbCommand.Parameter.Add(Add(No, arf.PersonNo.ToString()); dbCommand.Parameter.Add(Add(ame, arf.PersonName); ADO.NETin Balantsz Snflar: Balantsz snflar veri taban balant ilemlerinden bamsz veri saklama ilemleridir. DataTable Snf: Datatable snf veri taban tablosunun bellekte temsil eden temel bir snftr. SELECT komutuyla vtys den elde edilen bilgiler bit datatable ierisinde geici olarak saklanr. Ayrca ADO.NET sisteminde bir datatable nesnesi ile gerek veri tabanna bir aktarmda salanr. Yani biz bir datatable zerindeki bilgilerde deiikli yap p bunu veri tabanna yanstabiliriz. DataGridWiev isimli kontrol temel olarak bir veri taban tablosunu grntlemek iin kullanmaktadr. Bu kontrol olduka detayldr ve daha sonra ele alnacakt r. Fakat en basit kullanm kontroln DataSource isimli elemanna bir DataGridWiev atanmasd r. Bu durumda dataGridWiev kontrol bu veri taban tablosunu grntler. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO;

namespace DataTableSample { public partial class Form1 : Form { private DataGridView m_dgv; public Form1() { InitializeComponent(); m_dgv = new DataGridView(); m_dgv.Dock = DockStyle.Fill; DataTable dt = new DataTable("File"); 284

dt.Columns.Add("PersonName", typeof(string)); dt.Columns.Add("PersonNo", typeof(long)); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file); dt.Rows.Add(fi.Name, fi.Length); } m_dgv.DataSource = dt; this.Controls.Add(m_dgv); } } } Bir DataTable nesnesi DataTable snfnn default balang fonksiyonu ile yada string parametreli balang fonksiyonu ile de yaratlabilir. Tablonun bir ismi vardr. Bu TableName property si ile belirlenir. Balang fonksiyonun daki string bu ismi belirtmektedir. Tablo yaratld ktan sonra tabloya sutunlar eklenmelidir. Daha sonra da satrlar eklenir. Aslnda bu ekleme ilemi ListWiev kontrolndeki manta ok benzemektedir. DataTale snfnn stnlar DataColumn isimli snfla temsil edilmektedir. O halde programc her sutun iin bir DataColumn nesnesi olu turup ColumnsCollection elemanna ekler. DataTable nesnesinin bir sutunu iin en nemli iki bilgi sutun ismi ve trdr. sim string ile tr ise Type snf ile belirtilir. DataColumn snfn balang fonksiyonlar lar ise bu iki zellik hemen set edilebilir. Yada snfnn ColumnName ve DataType property leri kullanlr. rnein; DataTable dt = new DataTable ( Person ); DataColumn dt1=new DataColumn(PersonName, typeof(string)); DataColumn dt2=new DataColumn(PersonNo, typeof(int)); dt.Column.AddRange(new DataColumn[] {dt1,dt2}); Aslnda DataColumn nesnelerini ayr ayr yaratp eklemektense tpk ListView kontrolnde oluu gibi daha pratik bir yoluda vardr. DataTable snfnn Columns isimli property eleman DataColumnsCollection siimli bir Collection snf trndendrir. public DataColumnCollection columns ( get; ) Bu Collection snfn string ve type parametreli Add fonksiyonlar zaten kendi ierisinde DataColumn nesnesini kendisi yaratp eklemektedir. O halde yukardaki ekleme ilemi daha basit olarak yle yap labilir. DataTable dt = new DataTable(Person); dt.Columns.Add(PersonName, typeof(string)); dt.Columns.Add(PersonNo, typeof(int)); DataColumn snfnn baka nemli elemanlarda vardr. rnein MaxLenght isimli property eleman kolondaki maximum karakter saysn snrlandrmada kullanlabilir. Ordinal isimli 285

property eleman sutunun sura numarasn elde etmekte kullanlabilir. Column Mapping isimli property eleman ileride ele alnacaktr. Bir veri tabann tablosunun satrlar DataRow snf ile temsil edilmektedir. Yani her bir satr aslnda bir DataRow nesnesidir. Aslnda bir DataRow nesnesi new operatr ile sfrdan yaratlmaz. nk DataRow nesnesinin ierii sutun zelliine gre configure edilmi olmasd r. Bu nedenle yeni bir DataRow nesnesi DataTable snfnn new Row fn ile yaratlr. rnein ; DataRow dr = dt.new Row(); Bu biimde bir DataRow nesnesi yaratld nda programc bunun iini doldurup DataTable nesnesine eklemelidir. new Row fonksiyonu yanlzca bize o stn yapsna ilikin bir DataRow nesnesi olu turmaktadr. DataTable snfnn Rows isimli collection eleman DataRow collection isimli bir collection snf trndendir. Bu collection DataRow nesnelerini tutmaktadr. rnein; DataRow dr = dt.NewRow(); //. dt.Rows.Add(dr); imdi DataRow nesnesinin iinin doldurulmasna sra gelmitir. Bunu salamann en pratik yolu indeksleyicileri kullanmaktr. Temel olarak tr indeksleyici vardr. DatColumm parametreli, string parametreli ve int parametreli. String parametreli indeksleyici kolon ismini almaktadr. int parametreli indeksleyici kolon indeks numarasn alr. Ve DataColumn parametreli indeksleyici DataColumn nesnesini alarak ilgili satrn DataRow dr = dt.NewRow(); dr[PersonName] = Kaan Aslan; dr[PersonNo] = 123; dt.Rows.Add(dr); Anahtar Notlar: DataGridView kontol zerinde ekleme, silme ve gncelleme yapldnda ileride ele alnaca gibi bu ilgili satrlara yanstlmaktad r. Yani DataGridView sadece gsterme amal deil ayn zamanda gnceleme amalda kullanlmaktadr. Satr ekleme ilemi DataRowCollection snfnn ParamsObject[] Add fonksiyonuylada yap lmaktad r. DataRow snf aslnda bir satrn birka versiyonunu bir arada tutmaktadr. Snfn RowState isimli property eleman DataRowState isimli enum trndendir. Bu enum trnn anlamlar ve DataRow nesnesinin iinde bulunduu durum unlardan biri olabilir.

286

Detached : Eer DataRow nesnesi bu durumdaysa tabloya balanmam durumdadr . rnein NewRow ile yarat lm tr fakat henz tabloya eklenmemitir. Yada tablodan kartlm durumdad r. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO;

namespace DataTableSample { public partial class Form1 : Form { private DataGridView m_dgv; public Form1() { InitializeComponent(); m_dgv = new DataGridView(); m_dgv.Dock = DockStyle.Fill; DataTable dt = new DataTable("File"); dt.Columns.Add("PersonName", typeof(string)); dt.Columns.Add("PersonNo", typeof(long)); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file); dt.Rows.Add(fi.Name, fi.Length); } DataRow dr = dt.NewRow(); MessageBox.Show(dr.RowState.ToString()); m_dgv.DataSource = dt; this.Controls.Add(m_dgv); } } } Added : DataRow nesnesi yaratlm ve tabloya eklenmitir. Fakat AcceptChanges fonksiyonu henz arlmamtr. 287

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO;

namespace DataTableSample { public partial class Form1 : Form { private DataGridView m_dgv; public Form1() { InitializeComponent(); m_dgv = new DataGridView(); m_dgv.Dock = DockStyle.Fill; DataTable dt = new DataTable("File"); dt.Columns.Add("PersonName", typeof(string)); dt.Columns.Add("PersonNo", typeof(long)); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file); dt.Rows.Add(fi.Name, fi.Length); } DataRow dr = dt.NewRow(); dt.Rows.Add(dr); MessageBox.Show(dr.RowState.ToString()); m_dgv.DataSource = dt; this.Controls.Add(m_dgv); } } } Unchanged : DatatRow nesnesi tabloya eklenmi durumdadr. Ve AcceptChanges nesnesi 288

arlmtr ancak nesne zerinde henz bir deiiklik yaplmam tr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO;

namespace DataTableSample { public partial class Form1 : Form { private DataGridView m_dgv; public Form1() { InitializeComponent(); m_dgv = new DataGridView(); m_dgv.Dock = DockStyle.Fill; DataTable dt = new DataTable("File"); dt.Columns.Add("FileName", typeof(string)); dt.Columns.Add("FileSize", typeof(long)); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file); dt.Rows.Add(fi.Name, fi.Length); } DataRow dr = dt.NewRow(); dt.Rows.Add(dr); dr["FileName"] = "X.DAT"; dr["FileSize"] = 5353535; dt.AcceptChanges(); MessageBox.Show(dr.RowState.ToString()); m_dgv.DataSource = dt; 289

this.Controls.Add(m_dgv); } } } Modified : En son AcceptChanges fonksiyonu arldktan sonra nesne zerinde deiiklik yap lm tr. Fakat henz yeniden AcceptChanges fonks,yonu arlmam tr. Deleted : Satr delete fonksiyonu ile silinmitir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO;

namespace DataTableSample { public partial class Form1 : Form { private DataGridView m_dgv; public Form1() { InitializeComponent(); m_dgv = new DataGridView(); m_dgv.Dock = DockStyle.Fill; DataTable dt = new DataTable("File"); dt.Columns.Add("FileName", typeof(string)); dt.Columns.Add("FileSize", typeof(long)); foreach (string file in Directory.GetFiles(@"c:\windows")) { FileInfo fi = new FileInfo(file); dt.Rows.Add(fi.Name, fi.Length); } DataRow dr = dt.NewRow(); // Detached dt.Rows.Add(dr); // Added 290

dr["FileName"] = "X.DAT"; dr["FileSize"] = 5353535; // Added dt.AcceptChanges(); // Unchanged dr["FileName"] = "Y.DAT"; // Modified dt.AcceptChanges(); // Unchanged dr.Delete(); MessageBox.Show(dr.RowState.ToString()); m_dgv.DataSource = dt; this.Controls.Add(m_dgv); } } } imdi bir DataRow nesnesine ilemler uygulayarak onun durumunun nasl deitiini deerlendirelim. 1 DataRow nesnesini NewRow ile yaratalm u anda Detached durumdadr. 2 DataRow nesnesini DataTable ye ekleyelim. Nesne imdi Added durumdad r. 3 Henz eklediimiz DataRow zerinde deiiklik yapalm. AcceptChanges nesnesi arlmad iin nesne henz Added durumundadr. 4 imdi DataTable snfnn AcceptChanges fonksiyonu aralm. Artk DataRow nesnesi UnChanged duruma gelmitir. 5 imdi DataRow zerinde herhangi bir deiiklik yapalm. Artk nesne Modified durumdad r. 6 imdi yeniden DataTable snfnn AcceptChanges fn aralm. Nesne yeniden Unchanged duruma gemitir. 7 imdi DataRow nesnesini DataRow snfnn Delete fn ile silelim. Nesne Deleted durumdad r. Ayn zamanda tablodan kartlm tr. Biz eer ilgili satr DataRow snfnn ilgili fn ile deilde Rows Collection unun Remove fonksiyonu ile silmeye alsayd k bu durumda nesnenin tabloyla hibir ilikisi kalmayacakt bu durumda nesne deleted deil detached duruma gelecekti. Grld gibi DataRow snfnn Delete fonksiyonu silme yapmtr fakat tablo ilikisini henz kesmemitir. rnein ;

291

DataRow dr = dt.NewRow(); // Detached dt.Rows.Add(dr); // Added dr["FileName"] = "X.DAT"; dr["FileSize"] = 5353535; // Added dt.AcceptChanges(); // Unchanged dr["FileName"] = "Y.DAT"; // Modified dt.AcceptChanges(); // Unchanged dr.Delete(); //Deleted dt.Rows.Remove(dr); //Detached MessageBox.Show(dr.RowState.ToString()); m_dgv.DataSource = dt; DataRow Nesnesinin Deiik Versiyonlar: Anmsanaca gibi DataRow nesneleri DataTable nesnesinin Rows Colleciton yoluyla tabloya eklenmektedir. Ayrca biz DataRow snfnn eitli indeksleyicileriyle ilgili sutun elemanlarna ulamtk. te DataRow snfnn ayrca tm tek parametreli indeksleyicelerinin yan sra iki parametreli indeksleyicileride vardr. Bu indeksleyiclerin parametreli yine DataRow string yada int trndendir. Fakat ikinci parametreleri DataRowVorsion isimli bir enum trndendir. Aslnda bir DataRow nesnesinin duruma gre drt farkl versiyonu tutulmaktadr. Bu versiyonlar unlard r : Current : Bu versiyon DataRow nesnesinin son durumunu veren versiyondur. Zaten tek parametreli indexleyiciler bu versiyonu vermektedir. Orginal : Orginal versiyondan ama bir nceki durumunu tutmaktadr. rnein biz Unchanged durumdaki nesneyi deitirip Modified duruma sokmu olalm. Current versiyon bize deimi olan durumu verir. Halbuki Orginal versiyon deiimden nceki deeri bize verecektir. Her ne zaman AcceptChanges uygulansa Orginal versiyon tamamen Current versiyonla ayn yap lmaktadr. Yani nesne UnChanged durumdaysa zaten Orginal versiyonla Current version ayn durumdadr. Ayrca nesnenin orginal versiyonu newRow ile nesne yaratlp yaratlmaz oluturulmaz tabloya ekleme yap ld nda da oluturulmaz AcceptChanges fn arld ktan sonra olu turulur. DataRow nesnesi Delete fn ile silindiinde onun Current versiyonu yok olur fakat Orginal versiyonu kalr. DataSet Snf: Anmsanaca gibi DataTable snf bir veritaban tablosunu bellekte temsil etmektedir. DataSet 292

snf ise bir grup DataTable nesnesini tutmak iin dnlmtr. Yani DaSet DataTable lardan olumaktadr. Bir DataSet nesnesi snfn default balang fonksiyonuyla yaratlabilir. DataSet nesnelerinin de birer ismi vard r. sim DataSetName property si ile temsil edilmektedir. public string DataSetName { get; set;} DataSet snfnn Tables isimli Collection eleman DataTableCollection isimli Collection trndendir ve DataTable nesnelerini tutmaktadr. Select Komutuyla Veritabanndan Bilgilerin Elde Edilmesi: Bilindii gibi Slect SQL komutu kayt geri dndren bir komuttur. Geri dndrlen kaytlar bir DataTable ya da bir DataSet iindeki DataTable ierisine yerletirilir. Sorgulama sonucunda elde edilen kaytlarn DataTable ya da DataSet iine yerletirilmesi YYYDataAdapter snflaryla gerekletirilmektedir. YYYDataAdapter nesneleri bir YYYCommand nesnesi alr. YYYDataAdapter nesnesi yle kullanlmaktad r. 1. YYYDataAdapter nesnesi snfn herhangi bir balang fonksiyonuyla yaratlabilir. 2. Programcnn YYYDataAdapter nesnesine en azndan bir Select SQL komutu vermesi gerekir. Bunu yapmann tipik yolu Select komutu iin bir tane YYYCommand nesnesi oluturmak ve bu Command nesnesini YYYDataAdapter snfnn SelectCommand propertysine yerletirmektir. Zaten snfn YYYCommand parametreli bir balang fonksiyonuda vard r. Dier bir seenek Select SQL komutunun komut yazsn YYYDataAdapter snfnn balang fonksiyonunda belirtmek olabilir. Bu durumda balang fonksiyonu YYYCommand nesnesini olu turup yine snfn SelectCommand propertysini yerletirir. O halde YYYCommand snflar YYYConnection nesnesini YYYDataAdapter snflarda YYYCommand nesnelerini istemektedir. 3. SQL Select komutunun uygulanarak bunun bir DataTable ya da DataSet nesnesini iine sonular yerletirebilmesi iin YYYDataAdapter snflarnn Fill fonksiyonlar kullanlr. rnein bir Fill fonksiyonunun parametresi yledir. public int Fill(DataTable dataTable)dier bir Fill fonksiyonuda yledir. public override int Fill(DataSet dataSet) Bu biimde elde edilen tablolarn isimleri srasyla Table, Table1, Table2, ... biimindedir. Fakat programc isterse istenilen isimli bir DataTable da yaratabilir. Bunun iin aadaki Fill fonksiyonu kullanlr. public int Fill(DataSet dataSet, string srcTable)

AddRecord.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class AddRecordForm : Form { public AddRecordForm() { InitializeComponent(); 293

} private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } } MainRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace CSD { 294

public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); } private void addRecordToolStripMenuItem_Click(object sender, EventArgs e) { AddRecordForm arf = new AddRecordForm(); if (arf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?)"; dbCommand.Parameters.Add("Name", arf.PersonName); dbCommand.Parameters.Add("No", arf.PersonNo.ToString()); try { m_dbConnection.Open(); dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); }

} } private void Form1_Load(object sender, EventArgs e) { m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; " + @"Data Source=E:\DotNetAppBasic\DataBaseRecordProc\Person.mdb"; } private void deleteRecordToolStripMenuItem_Click(object sender, EventArgs e) 295

{ DeleteRecordForm drf = new DeleteRecordForm(); if (drf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "DELETE FROM Info WHERE PersonName = '" + drf.PersonName + "' AND PersonNo = " + drf.PersonNo.ToString(); try { m_dbConnection.Open(); int result = dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); if (result == 0) { MessageBox.Show("Cannot find record"); return; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } private void findToolStripMenuItem_Click(object sender, EventArgs e) { FindRecordForm frf = new FindRecordForm(m_dbConnection); if (frf.ShowDialog() == DialogResult.OK) {

} } } } DeleteRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { 296

public partial class DeleteRecordForm : Form { public DeleteRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } } FindRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; 297

using System.Windows.Forms; using System.Data.OleDb; namespace CSD { public partial class FindRecordForm : Form { private OleDbConnection m_connection; public FindRecordForm() { InitializeComponent(); } public FindRecordForm(OleDbConnection dbConnection) : this() { m_connection = dbConnection; } private void button1_Click(object sender, EventArgs e) { try { OleDbCommand dbCommand = new OleDbCommand("SELECT PersonName, PersonNo FROM Info WHERE " + textBox1.Text, m_connection); OleDbDataAdapter da = new OleDbDataAdapter(dbCommand); DataSet ds = new DataSet(); da.Fill(ds); dataGridView1.DataSource = ds.Tables["Table"]; } catch (Exception ex) { MessageBox.Show(ex.Message); }

} private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.OK; } } } Fill fonksiyonlarnn geri dn deerleri DataSet ve DataTable iine yerletirilen satr saysn belirtir. Fill fonksiyonlar otomatik olarak kendi ilerinde balanty aarak SelectCommand 298

propertysinde belirtilen SQL komutunu uygular. Sonucuda ilgili DataSet ya da DataTable iine yerletirir. rnein bir Fill ilemi yle yaplabilir. OleDbCommand dbCommand = new OleDbCommand(SELECT PersonName, PersonNo FROM Info WHERE PersonNo>300 OleDbAdapter da = new OleDbAdapter(dbCommand); DataSet ds = new DataSet(); da.Fill(ds); dataGridView1.DataSource = ds.Tables[Table]; rneimizde tablo ismi verilmedii iin Fill fonksiyonu default olarak Table isimli bir tabloya yerletirme yapmt r. Ama istenirse aadaki gibi bizim istediimiz bir tablo ismiyle yarletirme yap lr. DataSet ds = new DataSet(); da.Fill(ds, info) Fill fonksiyonu bir DataTable da verilebilirdi. Bu durumda yerletirme do rudan o DataTable nesnesine yap lacakt. OleDbCommand dbCommand = new OleDbCommand(SELECT PersonName, PersonNo FROM Info WHERE PersonNo>300 OleDbAdapter da = new OleDbAdapter(dbCommand); DataTable dt = new DataTable(); da.Fill(dt); dataGridView1.DataSource = dt; DataSet ya da DataTable iindeki bilgilerin Veritabanna Yanstlmas: Veritabanna sorgulama yap p sonular bir DataSet ya da DataTable a yerletirdikten sonra bu nesneler zerinde ilemler yaparsak bu ilemden otomatik olarak veritaban etkilenmez. te bu nesneler zerindeki satrlarda deiiklik yaptmzda bu deiikliklerin veritabanna yanstlmas iin baz eylerin bilinmesi gerekmektedir. ncelikle yaplan deiikliklerin yanstlmas YYYDataAdapter snflarnn Update fonksiyonlaryla gerekletirilmektedir. Bu snflarn pek ok Update fonksiyonu vardr. Fakat en tipik olan DataSet parametreli ve DataTable parametreli Update fonksiyonlard r. Ancak Update fonksiyonlarn kullanmadan nce baz hazrlklarn da yap lmas gerekmektedir. Ado.Net iinde ilemleri kolaylatran pek ok yardmc snf dnlm tr. Fakat programcnn daha aa seviyeli mekanizmalar bilmesinde fayda vardr. Update fonksiyonunu armadan nce programcnn baz command nesnelerini hazrlamas gerekir. Aslnda YYYDataAdapter snflarnn yalnzca SelectCommand isimli bir Command property si yoktur. Ayn zamanda UpdateCommand, InsertCommand, DeleteCommand propertyleri de vardr. Gerektende SelectCommand propertysi en nemli property olduu iin balang fonksiyonunda da belirtilmitir. O halde YYYDataAdapter snflarnn bu command nesneleri programc tarafndan oluturulmu olmald r. Fill fonksiyonlar SelectCommand propertysi ile belirtilen command nesnesini uygular. Eer biz yalnzca Fill ilemi uygulayacaksak YYYDataAdapter snfnn yalnzca SelectCommand propertysinin set edilmi olmas yeterlidir. Fakat eer biz Update ilemi uygulayacaksak InsertCommand, UpdateCommand, DeleteCommand nesnelerinin de oluturulmu olmas gerekmektedir. nk Update fonksiyonlar ileride aklanaca gibi gerektiinde bu Command nesnelerini kullanmaktadr. Yani grld gibi Fill fonksiyonlar yalnzca SelectCommand nesnesini kullanrken Update fonksiyonlar InsertCommand, DeleteCommand ve UpdateCommand nesnelerini de kullanmaktadr. YYYDataAdapter snflarnn Fill fonksiyonlar kabaca nce balanty aar. Sonra SelectCommand nesnesi ile SQL komutunu uygular. Elde edilen satrlarda DataTable ya da DataSet nesnesine 299

yerletirir ve tabi balanty kapatr. Peki Update fonksiyonlar ne yapmaktadr? te Update fonksiyonlar DataTable iindeki tm satrlar ya da DataSet iindeki DataTable nesnelerinin tm satrlarn tek tek inceler bu satrlarn RowState propertylerine bakar. Eer RowState propertysi Deleted ise o satr iin DeleteCommand isimli Command nesnesini, RowState Edit ise Insertcommand command nesnesini ve RowState Changed ise UpdateCommand nesnesini ExacuteNonQuery ile uygular. rnein Update fonksiyonu bir satrn Edit olduunu grdnde o satr gerekten veritabanna eklemek iin InsertCommand ile belirtilen komutu uygular. Update fonksiyonu benzer biimde bir satrn Deleted olduunu grdnde o satr gerekten silmek iin DeleteCommand nesnesi ile belirtilen SQL komutunu uygular. Update fonksiyonlar yalnzca belirtilen command nesnelerini uygular. Bu command nesnelerinin oluturularak ilgili propertylere set edilmi olmas gerekir. Bu da programcnn bu ilemleri yerine getirecek SQL komutlarn hazrlam olmasn gerektirir. Ado.net iinde ilgili command nesnelerini otomatik oluturmak iinde mekanizmalar vardr. Programc mekanizmalar kullanabilir. Fakat bu nesnelerin manuel oluturulmas esneklik salamaktadr. Command Nesnelerinin Otomatik Oluturulmas: Command nesnelerinin otomatik oluturulmas olduka kolayd r. Tek yaplacak ey bir YYYCommandBuildir nesnesi olu turmak ve bu nesneyi YYYDataAdapter nesnesi ile ilikilendirmektir. YYYCommandBuildir snfnn YYYDataAdapter isimli balang fonksiyonu bunun iin kullanlabilir. Ya da nesne snfn default balang fonksiyonuyla olu turulup YYYDataAdapter nesnesi snfn DataAdapter property sine girilebilir. Grld gibi YYYCommandBuilder snf yalnzca YYYDataAdapter nesnesini kullanmaktadr. rnein otomatik komut retmesi yle yap labilir. AddRecordsForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class AddRecordForm : Form { public AddRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); 300

} catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } } DataBaseMainForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace CSD { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); 301

} private void addRecordToolStripMenuItem_Click(object sender, EventArgs e) { AddRecordForm arf = new AddRecordForm(); if (arf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?)"; dbCommand.Parameters.Add("Name", arf.PersonName); dbCommand.Parameters.Add("No", arf.PersonNo.ToString()); try { m_dbConnection.Open(); dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); }

} } private void Form1_Load(object sender, EventArgs e) { m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; " + @"Data Source=D:\Ders\IlerCSharp\DataBaseRecordProc8\Person.mdb"; } private void deleteRecordToolStripMenuItem_Click(object sender, EventArgs e) { DeleteRecordForm drf = new DeleteRecordForm(); if (drf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; 302

dbCommand.CommandText = "DELETE FROM Info WHERE PersonName = '" + drf.PersonName + "' AND PersonNo = " + drf.PersonNo.ToString(); try { m_dbConnection.Open(); int result = dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); if (result == 0) { MessageBox.Show("Cannot find record"); return; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } private void findToolStripMenuItem_Click(object sender, EventArgs e) { FindRecordForm frf = new FindRecordForm(m_dbConnection); if (frf.ShowDialog() == DialogResult.OK) {

} } } } DeleteRecordsForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class DeleteRecordForm : Form { public DeleteRecordForm() { InitializeComponent(); }

303

private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } } FindRecordsForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.OleDb; namespace CSD { public partial class FindRecordForm : Form { 304

private OleDbConnection m_connection; private DataTable m_dt; public FindRecordForm() { InitializeComponent(); } public FindRecordForm(OleDbConnection dbConnection) : this() { m_connection = dbConnection; } private void button1_Click(object sender, EventArgs e) { try { OleDbCommand dbCommand = new OleDbCommand( "SELECT * FROM Info WHERE " + textBox1.Text, m_connection); OleDbDataAdapter da = new OleDbDataAdapter(dbCommand); m_dt = new DataTable(); da.Fill(m_dt); dataGridView1.DataSource = m_dt; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.OK; } private void button3_Click(object sender, EventArgs e) { try { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.CommandText = "SELECT * FROM Info WHERE " + textBox1.Text; dbCommand.Connection = m_connection; OleDbDataAdapter da = new OleDbDataAdapter(dbCommand); OleDbCommandBuilder cb = new OleDbCommandBuilder(da); //... da.Update(m_dt); 305

} catch (Exception ex) { MessageBox.Show(ex.Message); } } } } YYYCommandBuilder nesnesinin snfn veri eleman biimnde bildirilmesi gerekmez. nk bu nesne yaratld nda kendi referansn Event mekanizmas iin YYYDataAdapter nesnesine yazd iin p toplayc nesneyi toplamaz. Anahtar Notlar: Pekok diyalog penceresinde Enter tuuna basldnda tipik baz ilemler yap lr. Yani Enter tuu basld ndao u kez programc mevcut bir dmeye baslm etkisi istemektedir. Bu durum manuel olarak salanabilir. rnein KeyDown mesajlar ilenebilir. Ancak bu temayla ok sk karlald iin basit bir yntem de sunulmutur. Form snfnn AcceptButton isimli property eleman bu amala kullanlr. Benzer biimde Esc tuu iin CancelButton propertysi de vardr. Command Nesnelerinin Manuel Oluturulmas: Command nesnelerinin manuel retilmesi mmkndr. Burada command nesneleri ayr ayr ele alnacaktr. Insert Command Nesnesinin Manuel retilmesi: Programc InsertCommand nesnesini oluturuken komut yazsn parametrik bir biimde(rnein OleDb tedarikisi szkonusu ise ? ile )oluturur. Tabi Update fonksiyonu ilgili satrn durumunu Edit grdnde bu komutu uygulamadan nce komut parametrelerini yerletirmelidir. Komut parametrelerinin nasl yerletirilecei yani sat rn hangi elemanlar olarak yerletirileceini programc belirler. Programc InsertCommand nesnesini yle oluturur. 1. YYYCommand nesnesi yaratarak Insert Into sql komutunu CommandText biiminde girer. 2. InsertInto komutundaki bilgiler parametrik olmaldr. Programc her parametre iin bir YYY parameter nesnesi oluturur. Bunu YYYCommand nesnesinin Parameter isimli Collectionna atar. Programc parametrenin Value deerini set etmez fakat sat rn hangi stununa ve satrn hangi versiyonuna ilikin oldu unu belirtir. Bunun iin SourceColumn ve SourceVersion propertylerini kullanr. 3. YYYDataAdapter snfnn Update fonksiyonu uygulandnda Update fonksiyonu satr Edit grd nde InsertCommand nesnesini kullanarak ExacuteNonQuery yapmak ister. Fakat nce komutun parametrelerini yerletirmelidir. Bunun iin Nesnenin Parameters Collectionn inceler. Her bir YYYParameter nesnesinin value deerini o nesnede belirtildii biimde ilgili satrdan alarak set eder. rnein bir InsertCommand nesnesi reten fonksiyon yle yazlabilir. DataBaseMainForm using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; 306

using System.Data; using System.Data.OleDb; namespace CSD { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); } private void addRecordToolStripMenuItem_Click(object sender, EventArgs e) { AddRecordForm arf = new AddRecordForm(); if (arf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?)"; dbCommand.Parameters.Add("Name", arf.PersonName); dbCommand.Parameters.Add("No", arf.PersonNo.ToString()); try { m_dbConnection.Open(); dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); }

} } private void Form1_Load(object sender, EventArgs e) { m_dbConnection = new OleDbConnection(); 307

m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; " + @"Data Source=E:\DotNetAppBasic\DataBaseRecordProc\Person.mdb"; } private void deleteRecordToolStripMenuItem_Click(object sender, EventArgs e) { DeleteRecordForm drf = new DeleteRecordForm(); if (drf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "DELETE FROM Info WHERE PersonName = '" + drf.PersonName + "' AND PersonNo = " + drf.PersonNo.ToString(); try { m_dbConnection.Open(); int result = dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); if (result == 0) { MessageBox.Show("Cannot find record"); return; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } private void findToolStripMenuItem_Click(object sender, EventArgs e) { FindRecordForm frf = new FindRecordForm(m_dbConnection); if (frf.ShowDialog() == DialogResult.OK) {

} } } } FindRecordForm.cs
using System; using System.Collections.Generic;

using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; 308

using System.Windows.Forms; using System.Data.OleDb; namespace CSD { public partial class FindRecordForm : Form { private OleDbConnection m_connection; private DataTable m_dt; public FindRecordForm() { InitializeComponent(); } public FindRecordForm(OleDbConnection dbConnection) : this() { m_connection = dbConnection; } private void button1_Click(object sender, EventArgs e) { try { OleDbCommand dbCommand = new OleDbCommand( "SELECT * FROM Info WHERE " + textBox1.Text, m_connection); OleDbDataAdapter da = new OleDbDataAdapter(dbCommand); m_dt = new DataTable(); da.Fill(m_dt); dataGridView1.DataSource = m_dt; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.OK; } private void button3_Click(object sender, EventArgs e) { try { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.CommandText = "SELECT * FROM Info WHERE " + 309

textBox1.Text; dbCommand.Connection = m_connection; OleDbDataAdapter da = new OleDbDataAdapter(dbCommand); da.InsertCommand = CreateInsertCommand(); //... da.Update(m_dt); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private OleDbCommand CreateInsertCommand() { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_connection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?)"; OleDbParameter dbParam; dbParam = new OleDbParameter(null, OleDbType.VarChar, 0, "PersonName"); dbParam.SourceVersion = DataRowVersion.Current; dbCommand.Parameters.Add(dbParam); dbParam = new OleDbParameter(null, OleDbType.Integer, 0, "PersonNo"); dbParam.SourceVersion = DataRowVersion.Current; dbCommand.Parameters.Add(dbParam); return dbCommand; }

} } AddRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace CSD { public partial class AddRecordForm : Form { 310

public AddRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } } DeleteRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;

311

namespace CSD { public partial class DeleteRecordForm : Form { public DeleteRecordForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { int val = int.Parse(textBox2.Text); } catch (Exception ex) { MessageBox.Show(ex.Message); textBox2.Focus(); textBox2.SelectAll(); return; } this.DialogResult = DialogResult.OK; } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.Cancel; } public string PersonName { get { return textBox1.Text; } } public int PersonNo { get { return int.Parse(textBox2.Text); } } } } DeleteCommand Nesnesinin Oluturulmas: DeleteCommand Nesnesi de InsertCommand nesnesi gibi oluturulur. Programcnn sql komutundaki WHERE ko uluna tm stunlar parametre olarak kullnamas tavsiye edilir. Satr Deleted durumuna geldiinde satrn Orginal versiyonu durmaktadr. DeleteCommand nesnesi reten fonksiyon yle yazlabilir.

312

UpdateCommand Nesnesinin Oluturulmas: UpdateCommand nesnesinin oluturulmasnda daha fazla parametreye gereksinim duyulur. nk satrn hem Orginal versiyonu hem de Current versiyonu kullanlr. UpdateCommand nesnesi reten bir fonksiyon yle yazlabilir. FindRecordForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.OleDb; namespace CSD { public partial class FindRecordForm : Form { private OleDbConnection m_connection; private DataTable m_dt; public FindRecordForm() { InitializeComponent(); } public FindRecordForm(OleDbConnection dbConnection) : this() { m_connection = dbConnection; } private void button1_Click(object sender, EventArgs e) { try { OleDbCommand dbCommand = new OleDbCommand( "SELECT * FROM Info WHERE " + textBox1.Text, m_connection); OleDbDataAdapter da = new OleDbDataAdapter(dbCommand); m_dt = new DataTable(); da.Fill(m_dt); dataGridView1.DataSource = m_dt; } catch (Exception ex) { MessageBox.Show(ex.Message); } } 313

private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.OK; } private void button3_Click(object sender, EventArgs e) { try { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.CommandText = "SELECT * FROM Info WHERE " + textBox1.Text; dbCommand.Connection = m_connection; OleDbDataAdapter da = new OleDbDataAdapter(dbCommand); da.InsertCommand = CreateInsertCommand(); da.DeleteCommand = CreateDeleteCommand(); da.UpdateCommand = CreateUpdateCommand();

//... da.Update(m_dt); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private OleDbCommand CreateInsertCommand() { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_connection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?)"; OleDbParameter dbParam; dbParam = new OleDbParameter(null, OleDbType.VarChar, 0, "PersonName"); dbParam.SourceVersion = DataRowVersion.Current; dbCommand.Parameters.Add(dbParam); dbParam = new OleDbParameter(null, OleDbType.Integer, 0, "PersonNo"); dbParam.SourceVersion = DataRowVersion.Current; dbCommand.Parameters.Add(dbParam); return dbCommand; } private OleDbCommand CreateDeleteCommand() { OleDbCommand dbCommand = new OleDbCommand(); 314

dbCommand.Connection = m_connection; dbCommand.CommandText = "DELETE FROM Info WHERE PersonName = ? AND PersonNo = ?"; OleDbParameter dbParam; dbParam = new OleDbParameter(null, OleDbType.VarChar, 0, "PersonName"); dbParam.SourceVersion = DataRowVersion.Original; dbCommand.Parameters.Add(dbParam); dbParam = new OleDbParameter(null, OleDbType.Integer, 0, "PersonNo"); dbParam.SourceVersion = DataRowVersion.Original; dbCommand.Parameters.Add(dbParam); return dbCommand; } private OleDbCommand CreateUpdateCommand() { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_connection; dbCommand.CommandText = "UPDATE Info SET PersonName = ?, PersonNo = ? WHERE PersonName = ? AND PersonNo = ?"; OleDbParameter dbParam; dbParam = new OleDbParameter(null, OleDbType.VarChar, 0, "PersonName"); dbParam.SourceVersion = DataRowVersion.Current; dbCommand.Parameters.Add(dbParam); dbParam = new OleDbParameter(null, OleDbType.Integer, 0, "PersonNo"); dbParam.SourceVersion = DataRowVersion.Current; dbCommand.Parameters.Add(dbParam); dbParam = new OleDbParameter(null, OleDbType.VarChar, 0, "PersonName"); dbParam.SourceVersion = DataRowVersion.Original; dbCommand.Parameters.Add(dbParam); dbParam = new OleDbParameter(null, OleDbType.Integer, 0, "PersonNo"); dbParam.SourceVersion = DataRowVersion.Original; dbCommand.Parameters.Add(dbParam); return dbCommand; }

} } DataBaseMainForm.cs using System; using System.Collections.Generic; 315

using System.ComponentModel; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data; using System.Data.OleDb; namespace CSD { public partial class Form1 : Form { private OleDbConnection m_dbConnection; public Form1() { InitializeComponent(); } private void addRecordToolStripMenuItem_Click(object sender, EventArgs e) { AddRecordForm arf = new AddRecordForm(); if (arf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "INSERT INTO Info(PersonName, PersonNo) VALUES(?, ?)"; dbCommand.Parameters.Add("Name", arf.PersonName); dbCommand.Parameters.Add("No", arf.PersonNo.ToString()); try { m_dbConnection.Open(); dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); }

} 316

} private void Form1_Load(object sender, EventArgs e) { m_dbConnection = new OleDbConnection(); m_dbConnection.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; " + @"Data Source=E:\DotNetAppBasic\DataBaseRecordProc\Person.mdb"; } private void deleteRecordToolStripMenuItem_Click(object sender, EventArgs e) { DeleteRecordForm drf = new DeleteRecordForm(); if (drf.ShowDialog() == DialogResult.OK) { OleDbCommand dbCommand = new OleDbCommand(); dbCommand.Connection = m_dbConnection; dbCommand.CommandText = "DELETE FROM Info WHERE PersonName = '" + drf.PersonName + "' AND PersonNo = " + drf.PersonNo.ToString(); try { m_dbConnection.Open(); int result = dbCommand.ExecuteNonQuery(); m_dbConnection.Close(); if (result == 0) { MessageBox.Show("Cannot find record"); return; } } catch (Exception ex) { MessageBox.Show(ex.Message); } } } private void findToolStripMenuItem_Click(object sender, EventArgs e) { FindRecordForm frf = new FindRecordForm(m_dbConnection); if (frf.ShowDialog() == DialogResult.OK) {

} } } } Bu durumda Update ilemide yle uygulanr. OleDbCommand dbCommand = new OleDbCommand( 317

"SELECT * FROM Info WHERE " + textBox1.Text, m_connection); OleDbDataAdapter da = new OleDbDataAdapter(dbCommand); m_dt = new DataTable(); da.Fill(m_dt); dataGridView1.DataSource = m_dt; izim lemlerinde Koordinat Dntrmesi: izim ilemlerinde default koordinat sistemindeki birim pixel cinsindendir. Orjin noktas alma alannn solst k esidir ve x ekseni saa do ru y ekseni aaya doru akmaktadr. Bu koordinat sistemi baz uygulamalarda zorluklara yol amaktad r. izim fonksiyonlarna girdiimiz deerler, koordinat deerleri iki dntrmeye sokulduktan sonra gerek piksel deerlerine dntrlmektedir. Global Dn trme (world transformation) SayfaDntrme gerek ekran koordinat (Page transformation)

x, y

Grld gibi izim fonksiyonlarna girdiimiz x, y deerleri nce global dntrmeye sokulmakta sonra bu dn trlm deerler sayfa dntrlmesine sokulmaktadr. Global dntrme zerinde etkili olan fonksiyonlar TranslateTransform, RotateTransform ve ScaleTransform fonksiyonlardr. Sayfa dntrmesi zerinde PageUnit ve PageScale propertyleri etkili olmaktadr. Graphics snfnn ScaleTransform fonksiyonunun parametrik yaps yledir. public void ScaleTransform(float sx, float sy) Fonksiyonun parametreleri izim fonksiyonlarna girdiimiz deerlerin hangi deerlerle arplacan belirtir. rnein eksenlerin ynlerini deitirmek istersek -1 deerini verebiliriz. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace TransformSample { public partial class Form1 : Form { private float m_scaleX, m_scaleY; public Form1() { InitializeComponent();

318

m_scaleX = 1; m_scaleY = 1; }

private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.TranslateTransform(100, 100); g.ScaleTransform(m_scaleX, m_scaleY);

g.DrawRectangle(Pens.Red, 100, 100, 100, 100); } private void toolStripLabel1_Click(object sender, EventArgs e) { m_scaleX += 1; m_scaleY += 1; panel1.Invalidate();

} private void toolStripLabel2_Click(object sender, EventArgs e) { if (m_scaleX > 1) { m_scaleX -= 1; m_scaleY -= 1; } panel1.Invalidate(); } } } TranslateTransform fonksiyonu orjin noktasn kayd rmak iin kullanlmaktadr. public void TranslateTransform(float dx, float dy) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; 319

namespace TransformSample { public partial class Form1 : Form { private float m_scaleX, m_scaleY; public Form1() { InitializeComponent();

m_scaleX = 10; m_scaleY = -10; }

private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.TranslateTransform(panel1.Width / 2, panel1.Height / 2); g.ScaleTransform(m_scaleX, m_scaleY); g.DrawLine(Pens.Red, 0, panel1.Height / 2, 0, -panel1.Height / 2); g.DrawLine(Pens.Red, panel1.Width / 2, 0, -panel1.Width / 2, 0); List<PointF> points = new List<PointF>(); for (double x = -2 * Math.PI; x <= 2 * Math.PI; x += 0.1) { points.Add(new PointF((float) x, (float) Math.Sin(x))); } PointF [] pts = points.ToArray(); g.DrawLines(Pens.Blue, pts);

} private void toolStripLabel1_Click(object sender, EventArgs e) { m_scaleX += 1; m_scaleY -= 1; panel1.Invalidate();

320

} private void toolStripLabel2_Click(object sender, EventArgs e) { if (m_scaleX > 1) { m_scaleX -= 1; m_scaleY += 1; } panel1.Invalidate(); } } class MyPanel : Panel { public MyPanel() { this.ResizeRedraw = true; } } } Kalem gibi izim nesneleri default olarak ScaleTransform ileminden etkilenmektedir. rnein biz ScaleTransform fonksiyonuyla arpansal deerler verdiimizde kalemin kalnlklar da duruma gre artmaktadr. Bu durumda kalemin kalnl manuel olarak ayarlanabilir. Pen snfnn ScaleTransform ve RotateTransform fonksiyonlar kaleme zg transform deerleri alabilir. Bylece rnein programc global dzeyde ScaleTransform uygulad ktan sonra kalem nesnesi iin yeniden transform fonksiyonu uygulayabilir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace TransformSample { public partial class Form1 : Form { private float m_scaleX, m_scaleY; private Pen m_bluePen; private Pen m_redPen; public Form1() { InitializeComponent();

321

m_scaleX = 15; m_scaleY = -20; m_bluePen = new Pen(Brushes.Blue); m_redPen = new Pen(Brushes.Red); }

private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.TranslateTransform(panel1.Width / 2, panel1.Height / 2); g.ScaleTransform(m_scaleX, m_scaleY); m_redPen.ScaleTransform(1 / m_scaleX, 1 / m_scaleY); g.DrawLine(m_redPen, 0, panel1.Height / 2, 0, -panel1.Height / 2); g.DrawLine(m_redPen, panel1.Width / 2, 0, -panel1.Width / 2, 0); List<PointF> points = new List<PointF>(); for (double x = -2 * Math.PI; x <= 2 * Math.PI; x += 0.1) { points.Add(new PointF((float) x, (float) Math.Sin(x))); } PointF [] pts = points.ToArray(); m_bluePen.ScaleTransform(1 / m_scaleX, 1 / m_scaleY); g.DrawLines(m_bluePen, pts);

} private void toolStripLabel1_Click(object sender, EventArgs e) { m_scaleX += 1; m_scaleY -= 1; panel1.Invalidate();

} private void toolStripLabel2_Click(object sender, EventArgs e) { if (m_scaleX > 1) { m_scaleX -= 1; 322

m_scaleY += 1; } panel1.Invalidate(); } } class MyPanel : Panel { public MyPanel() { this.ResizeRedraw = true; } } } Pen snfnn ResetTransform fonksiyonu kalem zerine uygulanan Transform ilemlerini reset eder. RotateTransform fonksiyonu eksen dndrmesi yapar. Fonksiyonun parametresi derece cinsinden a almaktadr. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace TransformSample { public partial class Form1 : Form { private float m_scaleX, m_scaleY; private Pen m_bluePen; private Pen m_redPen; private float m_rotation; public Form1() { InitializeComponent(); m_scaleX = 15; m_scaleY = -20; m_rotation = 0; m_bluePen = new Pen(Brushes.Blue); m_redPen = new Pen(Brushes.Red); }

323

private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.RotateTransform(m_rotation); g.TranslateTransform(panel1.Width / 2, panel1.Height / 2); g.ScaleTransform(m_scaleX, m_scaleY); m_redPen.ScaleTransform(1 / m_scaleX, 1 / m_scaleY); g.DrawLine(m_redPen, 0, panel1.Height / 2, 0, -panel1.Height / 2); g.DrawLine(m_redPen, panel1.Width / 2, 0, -panel1.Width / 2, 0); List<PointF> points = new List<PointF>(); for (double x = -2 * Math.PI; x <= 2 * Math.PI; x += 0.1) { points.Add(new PointF((float) x, (float) Math.Sin(x))); } PointF [] pts = points.ToArray();

m_bluePen.ScaleTransform(1 / m_scaleX, 1 / m_scaleY); g.DrawLines(m_bluePen, pts);

} private void toolStripLabel1_Click(object sender, EventArgs e) { m_scaleX += 1; m_scaleY -= 1; panel1.Invalidate();

} private void toolStripLabel2_Click(object sender, EventArgs e) { if (m_scaleX > 1) { m_scaleX -= 1; m_scaleY += 1; } panel1.Invalidate(); } 324

private void toolStripLabel3_Click(object sender, EventArgs e) { m_rotation += 10; panel1.Invalidate(); } } class MyPanel : Panel { public MyPanel() { this.ResizeRedraw = true; } } } Eik yaz yazd rma ilemleri bu fonksiyon sayesinde yaplabilmektedir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace TransformSample { public partial class Form1 : Form { private float m_scaleX, m_scaleY; private Pen m_bluePen; private Pen m_redPen; private float m_rotation; public Form1() { InitializeComponent(); m_scaleX = 15; m_scaleY = -20; m_rotation = 0; m_bluePen = new Pen(Brushes.Blue); m_redPen = new Pen(Brushes.Red); }

325

private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.RotateTransform(m_rotation); StringFormat sf = new StringFormat(); sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; g.DrawString("This is a test", this.Font, Brushes.Red, panel1.ClientRectangle, sf); //g.TranslateTransform(panel1.Width / 2, panel1.Height / 2); //g.ScaleTransform(m_scaleX, m_scaleY); //m_redPen.ScaleTransform(1 / m_scaleX, 1 / m_scaleY); //g.DrawLine(m_redPen, 0, panel1.Height / 2, 0, -panel1.Height / 2); //g.DrawLine(m_redPen, panel1.Width / 2, 0, -panel1.Width / 2, 0); //List<PointF> points = new List<PointF>(); //for (double x = -2 * Math.PI; x <= 2 * Math.PI; x += 0.1) //{ // points.Add(new PointF((float) x, (float) Math.Sin(x))); //} //PointF [] pts = points.ToArray();

//m_bluePen.ScaleTransform(1 / m_scaleX, 1 / m_scaleY); //g.DrawLines(m_bluePen, pts);

} private void toolStripLabel1_Click(object sender, EventArgs e) { m_scaleX += 1; m_scaleY -= 1; panel1.Invalidate();

} private void toolStripLabel2_Click(object sender, EventArgs e) { if (m_scaleX > 1) 326

{ m_scaleX -= 1; m_scaleY += 1; } panel1.Invalidate(); } private void toolStripLabel3_Click(object sender, EventArgs e) { m_rotation += 10; panel1.Invalidate(); } } class MyPanel : Panel { public MyPanel() { this.ResizeRedraw = true; } } } Ard l yaplan Scale ve Rotate ilemleri kmlatif etki yaratmaktadr. rnein biz iki kez st ste 10 ar derecelik RotateTransform uygulam olalm. Toplam 20 derecelik bir dndrme ilemi yap lm olur. Benzer biimde biz nce 2 arpansal deeriyle sonra 4 arpansal deeriyle ScaleTransform ilemi yapm olalm. Toplamda 8 arpansal deere karlk gelmektedir. Eksen dndrmeleri matriksel biimde transformasyon matriksi verilerekte yaplabilir. (Programing Microsoft Windows with C# MS Press) Global dntrmeden elde edilen deerler sayfa dn trmesine sokulur. Graphics snfnn PageUnit isimli property eleman GraphicsUnit isimli enum trndendir. Bu enum trnn pixel, inch, milimeter gibi elemanlar vardr. Bu property global dn trme sonucunda elde edilen deerin birimini belirlemektedir. rnein biz 0,0 koordinatndan 100, 100 koordinatna bir do ru izmi olalm. ScaleTransform deeri +2, +2 biiminde olsun. Bu durumda global dntrme sonucunda 0, 0 ve 200, 200 deerleri elde edilir. Buradaki 0,0 ve 200, 200 n birimi Sayfa dntrmesi aamasnda PageUnit propertysine baklarak belirlenmektedir. Default PageUnit pixel durumundadr. rnein biz onu milimeter biimine ekersek buradaki 200, 200 deeri 200 mm anlam na gelir. Eer izim ilemleri yazc iin yaplyorsa mm ve inch byklkleri tamamen gereki biimde oluturulur. Yani biz 10mm bir izimi yazcya yapsak cetvelle ltmzde gerekten 10 mm kmaktad r. Peki ekrandaki durum nasl olacaktr.? Ekran byklkleri deitii iin pixel boyutlarn nceden bilmek ok zordur. Bu durumda bu mm ve inch gibi deerler ekran szkonusu olduunda greli deerler olur. Sistemdeki default font un punto bykl etkili olmaktadr. Vista sistemlerinde default font 8 puntodur. 1 punto 1/72 inch dir. 72 punto 1 inch yapmaktadr. Bu durumda biz ekranda PageUnit deerini inch e ekersek ve 1 inch uzunluunda bir doru izmeye alrsak 1 inch de 72 pixel oldu u iin ve sistemdeki default font 8 punto olduu iin 1 inchlik 327

uzunluk 72*8 pixele karlk gelecektir. mm deeride inch deerine gre ayarlanmtr. Grafik snfnn PageScale isimli property eleman bir birimin ka PageUnit deerine ilikin olduunu belirtir. rnein normal dn trme sonrasnda 100 deeri elde edilmi olsun. PageUnit property sinin mm olduunu dnelim. PageScale de 2 olsun. te global dntrme srasnda elde edilen 100 deeri 200mm anlamna gelecektir. public float PageScale{ get; set} PageScale propertysinin tipik kullanm yledir. rnein biz 0-10000 aralnda deerler elde edelim. Fakat bunu 300 lk bir znrlk iinde yorumlamak isteyelim. Bu durumda PageScale deerini 300/10000 yaparz. Bylece 0 ile 10000 arasndaki deeri izimde kullanabiliriz. Bu property nin default deeri 1 biimindedir. ImageList Snf: ImageList snf ayn boyutta resimleri tutan bir collection snft r. .net te pek ok karmak kontrol ImageList snfn kullanmaktadr. ImageList snf trnden bir nesne snfn default balang fonksiyonuyla yaratlabilir. ImageList snfnn Images isimli collection eleman ImageList.ImageCollection isimli collection bir snf trndendir ve resimleri tutar. ImageList snfnn ImageSize isimli property eleman Size trdendir ve resimlerin boyutunu belirtmektedir. Collection a atanan tm resimler otomatik olarak bu boyuta gerektirir. Bu propertynin default deeri 16 *16 d r. Maksimum deeri 256 *256 olabilir. Snfn ColorDepth isimli property eleman ColorDepth isimli enum trndendir ve resimlerin renk znrln belirtmektedir. Default 8 bit renk znrlndedir. Snfn Draw isimli fonksiyonlar do rudan graphics nesnesi alarak resmi izer. Anahtar Notlar: .net iinde Managed exe ve dll ler iindeki kaynaklar tek tek alp save edebilecek bir program yazabiliriz. Fakat Unmanaged exe ve dll lerdeki kaynaklar API fonksiyonlar n armadan elde edebilecek bir mekanizma yoktur. Ancak Unmanaged exe ve dll ler iindeki kaynaklar alp bunu birer dosya biiminde diske saklayan pek ok basit yazlm bedava biimde internette bulunabilmektedir. TreeView Kontrol: Bu kontrol altlk stlk ilikisi iinde olan a a yaplarn grntlemek amacyla kullanlr. TreeView snnfyla temsil edilmektedir. Nesne snfn Default balang fonksiyonuyla yaratlabilir. Control deki her elemana bir dm denir. D mler de TreeNode isimli bir snfla temsil edilmitir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace ImageListSample { public partial class Form1 : Form { ImageList m_il; public Form1() { 328

InitializeComponent(); m_il = new ImageList(); m_il.ImageSize = new Size(64, 64); m_il.ColorDepth = ColorDepth.Depth24Bit; } private void button1_Click(object sender, EventArgs e) { try { foreach (string file in Directory.GetFiles( @":\Users\pc3\Desktop\ResourceExtract\ChessFigures", "*.bmp", SearchOption.TopDirectoryOnly)) { m_il.Images.Add(new Bitmap(file)); } } catch (Exception ex) { MessageBox.Show(ex.Message); } this.Invalidate(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; if (m_il.Images.Count == 0) return;

int x , y;

for (int i = 0; i < 10; ++i) { y = i * m_il.ImageSize.Height; x = 0; for (int k = 0; k < 10; ++k) { x = k * m_il.ImageSize.Width; m_il.Draw(g, new Point(x, y), 100+ i * 10 + k); } } } } } 329

TreeView snfnn Nodes isimli collection eleman kk elemanlar tutmak iin kullanlr. TreeNode snfnn Nodes isimli collection eleman ise TreeNode nesnelerini tutan bir collectiondr. Bu collection eleman dmn alt dmlerini tutmaktadr. Yani TreeView kontrol dmlerden dmlerde alt dmlerden olumaktadr. TreeNode snfnn Parent isimli eleman st dmn TreeNode referansn Text isimli property eleman dmn yazsal ismini tutmaktadr. Dmn tm alt dmleri ChildNode collection eleman ile elde edilebilir. Tpk baz kontrollerde olduu gibi TreeNode snfnn Nodes isimli collection elemannn ilikin olduu TreeNode collection snfnn String parametreli add fonksiyonlar kendi iinde TreeNode nesnesini yaratp eklemeyi yapmaktadr. TreeView snfnn SelectedNode isimli property eleman o anda seili olan TreeNode elemann vermektedir. Eer hibir eleman seili deilse null referans elde edilir. TreeNode snfnn string trnde FullPath isimli property eleman d mn yerini tersbl karekterleriyle bize vermektedir. Yine TreeNode snfnn ImageIndex isimli property eleman o dm iin grntlenecek resmin ImageList iindeki indeks numarasn belirtir. TreeView snfnn ImageList isimli property eleman tm dmler iin resimleri tutan ImageList nesnesi almaktadr. Yani programc tm d mlerin resimlerini bir ImageList e yerletirmeli sonra TreeNode nesnesinin ImageIndex propertysi ile resmi belirlemelidir. Programc tm aac iin banda zyinelemeli olarak oluturabilir. Fakat baz durumlarda tm aacn oluturulmas zaman kayb na yol aabilmektedir. rnein dizin aacnn TreeView kontrolnde gsterilmesi verilebilir. Bu durumda ileride ele alnaca gibi gsterim Exspend mesajlarnda ayr ayr yaplabilir. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace TreeViewSample { public partial class Form1 : Form { private TreeView m_tv; public Form1() { InitializeComponent(); m_tv = new TreeView(); m_tv.Size = new Size(300, 300);

m_tv.Parent = this; } 330

private void button1_Click(object sender, EventArgs e) { foreach (string drive in Directory.GetLogicalDrives()) { TreeNode tn = new TreeNode(drive); m_tv.Nodes.Add(tn); AddNode(tn); } } private void AddNode(TreeNode tn) { string path = tn.FullPath; foreach (string dir in Directory.GetDirectories(tn.FullPath)) { try { TreeNode stn = new TreeNode(Path.GetFileName(dir)); tn.Nodes.Add(stn); AddNode(stn); } catch (Exception ex) { } } } } } TreeView snfnn BeforeExpand isimli event eleman alt dmleri olan dme tkland nda am ilemi yaplmadan nce tetiklenir. Benzer biimde AfterExpand am ilemi yap ldktan sonra tetiklenmektedir. Benzer biimde bir alt aac kapatrken de BeforeCollapse ve AfterCollapse event elemanlar da vardr. rnein biz daha etkin bir biimde dizin aacn TreeView da grntlemek isteyelim bunun iin iin banda her srcdeki kk dizindeki dizinler bulunur ve aaca eklenir. Bu durumda kkteki srclerde + sembol kar. Programc BeforeExpand mesajn ileyerek ilgili dizine ilikin alt dme tklandnda o dizinin iindeki dizinlerin altdizinlerini bularak aaca ekler. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace TreeViewSample 331

{ public partial class Form1 : Form { private TreeView m_tv; public Form1() { InitializeComponent(); m_tv = new TreeView(); m_tv.Size = new Size(300, 300); m_tv.BeforeExpand += new TreeViewCancelEventHandler(m_tv_BeforeExpand);

m_tv.Parent = this; } void m_tv_BeforeExpand(object sender, TreeViewCancelEventArgs e) { foreach (TreeNode tn in e.Node.Nodes) AddNode(tn); } private void button1_Click(object sender, EventArgs e) { foreach (string drive in Directory.GetLogicalDrives()) { try { TreeNode tn = new TreeNode(drive); m_tv.Nodes.Add(tn); AddNode(tn); } catch (Exception ex) { } } } private void AddNode(TreeNode tn) { string path = tn.FullPath; if (tn.Nodes.Count != 0) return; try {

332

foreach (string dir in Directory.GetDirectories(tn.FullPath)) { try { TreeNode stn = new TreeNode(Path.GetFileName(dir)); tn.Nodes.Add(stn); } catch (Exception ex) { } } } catch (Exception ex) { } } } } Genericler: Yazlm mhendisliinde trden bamsz ilemlerin yaplabilmesi hep bir sorun biiminde alglanm ve de eitli zmler retilmeye allmt r. Szgelimi Eyfel ve Ada dilleri Bu dillerde generticler konusu adreslenmeye allmtr. Zira C++ daysa template dediimiz konu bal bu problemin adreslenmesine yneliktir. C# da ise 2.0 versiyonuna kadar dilin sintaksna entegreedilmi bir zm bulunmamaktayd. 2005 de kan 2.0 versiyonunda ise Generic ismiyle bu problem adreslenmeye allm tr. C# 2.0 dan nce bu problem .net snf sisteminin kendi i dinamiklerine braklm ve de bu snf sisteminin mutlak taban snf durumundaki object snfnn tr uyu um zellii ile giderilmeye allm tr. Object snf

Value Type

Tcp Listener

String

....

Int32

Int64

...

Ancak bu tekniin yaratt bir takm anomaliler ve komplikasyonlar sz konusudur. Bu noktadan sonra odanda bu mekanizmann yer ald yap lar inceleyip sotunlar ortaya karacak ve de genericlerle bu sorunlarn zmn greceiz. Klasik stack uygulamas trden bamsz olarak object nesnesi kullanlarak aadaki gibi yaplabilir. using System; using System.Collections.Generic; using System.Linq; using System.Text;

333

namespace MyStack { class MyStack { private object[] arr; private int cursor = 0; public MyStack(int size) { arr = new Object[size]; cursor = 0; } public void Push(object val) { arr[cursor++] = val; } public object Pop() { return arr[--cursor]; } }

class Program { static void Main(string[] args) { MyStack stk = new MyStack(10); stk.Push("aykut"); string s = (string) stk.Pop(); Console.WriteLine(s); } } } Bu rnekte nesne implicit olarak alnan herhangi bir tip neticede object e dnyor. Bu da geri planda ekstra ilemler yapyor. Aadaki gibi deer trne ilikin bir deeri stackte int push edersek burada int tr obje trne dnyor. nt bir deer tr ve stackte yer alr. Ama objeler nesne yani obje trnden olmasndan dolay heapte bir yerde tututluyor bu dn m boxing(kutulama) olarak biliniyor. Bu durumda hem tr dnm hem bellekte yer deiiimi sz konusu tersi durumda(pop) unboxing gerekleiyor. Obje trnden deer trne bir dnm oluyor vebellek adresleri de deiiyor. Heapten Stake bir yer deiimi... Bu durumda CPU iin fazladan ilem yk getiriyor.

334

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyStack { class MyStack { private object[] arr; private int cursor = 0; public MyStack(int size) { arr = new Object[size]; cursor = 0; } public void Push(object val) { arr[cursor++] = val; } public object Pop() { return arr[--cursor]; } } class Submarine {

} class Program { static void Main(string[] args) { MyStack stk = new MyStack(10); int i = 9; stk.Push(i); int s = (int) stk.Pop(); Console.WriteLine(s); } } 335

} Submarine trnden bir nesne yaratp bunu object trne imlicit dntrdmzde bir boxing sz konusu deil ikiside referans trne ilikin fakat unboxsing durumunda aadaki rnekte olduu gibi pop ileminde nesneyi stringe dntrp bir string nesnesine atadm zda pop submarine verdiini bildiim halde bunu string e dntrp bunu bir string nesnesine atadm zda bu ak hata derleme zamannda hata vermiyor fakat runtime da bu exceptiona yol ayor ve program kyor. Bu bir programcnn yapmamas gerekn bir hata. using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyStack { class MyStack { private object[] arr; private int cursor = 0; public MyStack(int size) { arr = new Object[size]; cursor = 0; } public void Push(object val) { arr[cursor++] = val; } public object Pop() { return arr[--cursor]; } } class Submarine : Object { private string name; public string Name { get { return name; } set { name = value; } } private string no; public string No { 336

get { return no; } set { no = value; } } public Submarine(string name, string no) { this.name = name; this.no = no; } } class Program { static void Main(string[] args) { MyStack stk = new MyStack(10); Submarine sub = new Submarine("Burakreis", "S-356"); stk.Push(sub); string s = (string) stk.Pop();

} } } Bu yap nn getirdii problemler ksa olarak yle anlatlabilir. Bu tarzda tasarlanm stack sistemine referans tre ilikin elemanlar push edildiinde ilgili trden obje trne otomatik tr dntrmesi olumakta bu da belirli bir performans kayb olarak hissedilmektedir. kinci olarak Stackte kullanlan elemanlar ayet deer trnde elemanlarsa bu durumda hem tr dntrmesi yaplmal hemde puch ileminde stack ten heap e (boxing) pop ileminde ise heapten stacke(unboxing) veri tanmas yaanmaktad r. Boxing, Unboxing ad yla anlan bu ilemler olumasn istemediimiz trden ilemlerdir. nc olarak yukardaki rnek te submarin trnden bir eleman stacke push edildiinde pop ile alnd nda yanl bir tre dntrlerek alnrsa yaanacak olan hata derleme zamannda deil ok daha sonra ve de sinsice alma zamannda bir exception biiminde ortaya kacaktr. Ksaca bu mekanizma bug oluumuna msait kt bir mekanizmadr. Bunun zm C++ Template olarak bilinen Genericlerdir. Yukardaki rnein generic olarak tasarm aadaki gibidir. ncelikle bu sre iinde hibir tr ismi obje de dahil olarak gememelidir. Bu durum tanmlanrken deil yaratlrken de olmamaldr.

using System; using System.Collections.Generic; using System.Linq; using System.Text;

337

namespace MyStack { class MyStack<T> { private T[] arr; private int cursor = 0; public MyStack(int size) { arr = new T[size]; cursor = 0; } public void Push(T val) { arr[cursor++] = val; } public T Pop() { return arr[--cursor]; } } class Submarine : Object { private string name; public string Name { get { return name; } set { name = value; } } private string no; public string No { get { return no; } set { no = value; } } public Submarine(string name, string no) { this.name = name; this.no = no; } } class Program { static void Main(string[] args) { 338

MyStack<string> stk = new MyStack<string> (10); stk.Push("kaan"); Console.WriteLine(stk.Pop()); } } } Bir tr jeneric olarak tasarlanacaksa renin bir snf: Snf isminden sonra alp kapatlan asal parantezler iine bir yer tutucu karakter kullanp artk o snfn iinde herhangi bir zel tr belirtmeyiz. Snf bildiriminde asal parantezler iine yazlan yer tutucu daha sonra osnf trnden bir nesne yaratlrken zgn bir tr ismiyle deitirilecek ve de o tr ismi artk geerli olacaktr. Generic olarak tasarlanm yaplarda yukarda bahsedilen sorun yaanmayacaktr. Aadaki rnekte stack in byme faktr de tutuluyor. (Array.Resize la bu i ok kolay) using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyStack { class MyStack<T> { private T[] arr; private int cursor = 0; private int growth_Factor; public MyStack(int size, int GrowthFactor) { arr = new T[size]; cursor = 0; growth_Factor = GrowthFactor; } public void Push(T val) { if (cursor >= arr.Length) { Array.Resize(ref arr, arr.Length * growth_Factor); } else { arr[cursor++] = val; } } public T Pop() { return arr[--cursor]; 339

} } class Submarine : Object { private string name; public string Name { get { return name; } set { name = value; } } private string no; public string No { get { return no; } set { no = value; } } public Submarine(string name, string no) { this.name = name; this.no = no; } } class Program { static void Main(string[] args) { MyStack<Submarine> stk = new MyStack<Submarine> (10, 2); stk.Push(new Submarine("Anafartalar", "S-300" )); Submarine ship = stk.Pop(); } } } Transaction Nedir? Birbirleriyle mantksal Ya da ilevsel anlamda ilikili olan bir Ya da daha fazla saydaki ilemi tek ve tmleik bir yap altnda toplayan ve de bunlarn atomik davranmasn salayan kavramd r. Bu kavram dahaok veritaban programclnn bir terimidir. Bunu anlamak iin ACIT doktirinini bilmek gerekir A: Atomicity C:Consistency I: Isolation D:Durability Bu drt kavram olmadan transaction anlalmaz.

340

Atomicity: Atomiklikok nemli bir kavramdr. Bunun tek cmleyle zeti ya hep ya hi tir. Transaction ilemlerini Transaction Boundery denilen bir ereve iinde gerekleir. rnek olarak bir EFT de bu tmlesik yap iinde birinci ilem. Hesaptan parann ekilii hedef hesaba parann yatrl, EFT Onay ve Dekont Basm yani bir EFT ilemi 4 alt ilemden olu uyor. Bu ilemin atomik olmas gerekiyor. Yani bu ilemlerin hibirinde hata olmamas gerekir. rnein Kaynak hesaptan paray ekelim ama hedef hesaba para yatrlamad. Bu durumda transaction ilemi atomik olarak bu ilem gereklememi saylr. Transaction ilemi baaryla sonulanana kadar bu ilemler havada kalr hepsi baarl olursa transaction baarl olmu olur. Atomiklik ite budur. Consistency: Tutarllk; birtransaction ilemi tutarl olmas gerekir. Diyelimki 1000 ytlilik hesapta 200 ytl havale ettik ama hesapta 800 kalmas gerekir. 900 kalyorsa bu tutarszlktr. Isolation: Bir transaction bir sistem zerinde alrken ayn anda almakta olan dier transactionlardan sistemi izole eder. Bir transaction banka hesabmzdan 1000 ytl nin Gelir vergisini hesaplayacak bu hesap ilemi bitene kadar bu hesap zerinde baka bir transaction bir ilem yapamamal. Bu izolasyon durumu dier transactionlara izin vermez ve onlar baarsz klar. Fakat bu transaction durumunda kilitin esneklii ayarlanabilir. Durability: Kararllk, Srdrlebilirlik; Transaction zerinde alt ilemde bir problem oldu ve ilem gerekleemedi. Bu ilkeye gre bir problem halinde yaplan ilemin geri alnabilmesi ve son halinde kalabilmesi gerekir. Bir transaction ACID ilkelerini tam olarak yerine getirilebiliyorsa o transaction doru tasarlanm demektir. Gerekte veritaban zelinde transaction ilemi nasl yaplyor. Veritabanlarnda 2 ayr trde transaction ilemi var. 1. Manuel Transaction veya Local Transactionlar 2. Otomotik Transaction veya Global Transaction lar Manuel transactionlar biz ynetiyoruz. Otamatik transactionlar birden fazla network sistemi trafndan ynetiliyor. Manuel Transactionlar ADO.NET, T-SQL lar ynetir. Otomatik Transactionlar COM+ ynetiyor Windows NT den nce MTS: Microsoft Transaction Server d. ADO.NET te Transactionlar model olarak nasl ynetiliyor? Transaction ynetimi connection nesnesiyle balyor. Ado.net ncesindeconnection nesnesinin transaction ynetme fonksiyonlar vard. Ama Ado.net Connection nesnesi modeli byle deil. Connection nesnesi yratldktan sonra XXXConnection snfnn Begin Transaction (); ile Transaction ilemi balar. Isolation nesnesinin yumu aklk sertliini ayarlamak iin BeginTransaction(Isolation Level) Isolation Level enum kullanlr. Connection nesnesinin ynetimi iin XXXTransaction nesnesini yneten yeni bir nesnenin ynetimi iin Begin Transaction yaratt nesne refarans kullanlr. XXXTransaction trs = con.BeginTransaction(-); Daha sonra Binding ilemeleri ve Exacute ilemleri yaplr. Exacute ilemlerin genelde try Catch ilemleri iinde yaplr. Biz bir transaction iine bind ettikten sonra komutumuzu yaplan hibir ilem veritabanna yansmaz. Bu Execute ilemi iinde transaction ileminin kalc olmas iin Commit ileminin bitmesi gerekir. Yani Exception baarl olmamas gerekir. Eer Exception ilemi gerekleirse btn transactionlar RollBack ilemi ile geri alnr. 341

trs.RollBack(); TransactionSmp1(Kt tasarmHakan n yznden oldu:)) yerletir. Normalde try catch ile yaplmal... using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; namespace TransactionSmp { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { SqlConnection cnn = new SqlConnection(); cnn.ConnectionString = "server=PC6; database=CSDSite; integrated security=true"; cnn.Open(); // Transaction balat SqlTransaction trs = cnn.BeginTransaction(); SqlCommand cmd = cnn.CreateCommand(); cmd.CommandText = "Delete from Egitmenler where EgitmenID=11"; SqlCommand cmd2 = cnn.CreateCommand(); cmd2.CommandText = "Delete from Kurslar where KursID=50"; // Transactiona komutlarn bind edilii, transaction boundary belirlenmesi cmd.Transaction = trs; cmd2.Transaction = trs; if (cmd.ExecuteNonQuery() != 0) { if (cmd2.ExecuteNonQuery() != 0) { trs.Commit(); } else { trs.Rollback(); } 342

} else { trs.Rollback(); } cnn.Close();

} } } Biri uygulamasnn yapmas gereken ilemler 1. Verinin kullanc sunumu / alnmas 2. kurallarna gre verinin ilenmesi 3. Veritaban ilemleri ok katmanl mimari: ok katmanl programlama mimarisini ren Yukardaki i uygulamalar ok katmanl mimaride yle katmanlatrlabilir. 1. Presentation Layer 2. Bussines Layer 3. Data Layer DAL Yerletir. Data Access Layer (ok katmanl yap) using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient; using System.Data.Common; namespace DAL { public abstract class CGenelDBIslemleri { public abstract DataTable GetDataTable(string qry, DbParameter[] prs); public abstract DataSet GetDataSet(string qry, DbParameter[] prs); public abstract int QueryExecute(string qry, DbParameter[] prs); // ... } public class CSQLHelper : CGenelDBIslemleri { private string m_CnnStr = ""; private SqlConnection m_Cnn = null; private SqlCommand m_Cmd = null; 343

public CSQLHelper(string cnnStr) { m_CnnStr = cnnStr; } private void Open() { try { m_Cnn = new SqlConnection(m_CnnStr); m_Cnn.Open(); } catch (SqlException exc) { throw exc; } } private void Close() { if (m_Cnn.State != ConnectionState.Closed) { m_Cnn.Close(); } } public override DataTable GetDataTable(string qry, DbParameter[] prs) { Open(); m_Cmd = new SqlCommand(qry, m_Cnn); if (prs != null) { foreach (SqlParameter p in prs) { m_Cmd.Parameters.Add(p); } } SqlDataAdapter a = new SqlDataAdapter(m_Cmd); DataTable t = new DataTable(); a.Fill(t); Close(); return t; }

344

public override DataSet GetDataSet(string qry, DbParameter[] prs) { Open(); m_Cmd = new SqlCommand(qry, m_Cnn); if (prs != null) { foreach (SqlParameter p in prs) { m_Cmd.Parameters.Add(p); } } SqlDataAdapter a = new SqlDataAdapter(m_Cmd); DataSet t = new DataSet (); a.Fill(t); Close(); return t; } public override int QueryExecute(string qry, DbParameter[] prs) { Open(); m_Cmd = new SqlCommand(qry, m_Cnn); if (prs != null) { foreach (SqlParameter p in prs) { m_Cmd.Parameters.Add(p); } } int i = m_Cmd.ExecuteNonQuery(); Close(); return i; } } } Setup: Program debug ile yazldktan sonra Release le tekrar build edilir. (.net te setup uygulamasn aratr...)

345

ASP.Net: Sunucu tarafl alan dinmaik web uygulamalarn gelitirmekte kullanlan bir net teknolojisinin ismidir. ASP.net .net teknolojileri iinde nasl bir konuma sahiptir. Bunu anlmak iin .net framework bilmek gerekir.

.net uygulamalar System.Web.Forms.dll/ASP.net System.Windows.Forms.dll System.Data.dll/ADO.Net System.Drawing.dll BCL mscorlib.dll CLR mscoree.dll letim Sistemi .net Framework

.net Framework demek Visula Studio demek deil. Dier programlama dilleriylede .net ktphanesi kullanarak programlar yazlabilir.

346

You might also like