Makale Özeti

Bu makalemizde mobil cihazlarımızda kullandığımız standart System.Windows.Form.Label class’ının bir örneği olan label nesnemiz yerine kendi transparan label’imizi nasıl yapabileceğimizi irdeleyeceğiz..(Aslında herhangi bir transparent control’ün nasıl yapılabileceğini...)

Makale

Bu makalemizde mobil cihazlarımızda kullandığımız standart System.Windows.Form.Label class’ının bir örneği olan label nesnemiz yerine kendi transparan label’imizi nasıl yapabileceğimizi irdeleyeceğiz..(Aslında herhangi bir transparent control’ün nasıl yapılabileceğini...)

Bildiğiniz gibi mobil cihazlar desktop bir pc ye istinaden daha kısıtlı kaynaklara sahip olduğundan haliyle yazılım geliştiricilerin bir çoğu platformun bu kısıtlılıklardan ötürü mümkünse desktop ya da web tabanlı uygulamalara müşterilerini yönlendiriyorlar..Burda yönlendirmekten kastım sadece sunum katmanını içeriyor..Yalnis anlasilmasin J Yoksa mobil çözüm üreten bir cok uygulama geliştirici zaten .NET çercevesi  içerisinde özgürce bilgileri dahilinde istedikleri gibi çözümlerini üretmeye devam ediyor..Hatta .NET 3.5 ile gelen yeniliklerle bu olay cok daha zirveye tırmanmış durumda..Sonuç itibariyle bileşen  pazarına bakıldığında 3. Parti bileşen üreticilerinin windows ve web pazarının büyüklüğünden ötürü mobile alanında yaptıkları ürünlerin  sayısı oldukca kısıtlı..(Zorluğuda cabası..) İsterseniz onlara inat .NET CF içerisinde olmayan bir transparan bir label’ı nasıl yapabileceğimize başlayalim J

Öncelikle ihtiyacımız olan kodsal tasarım bileşenlerini yazmaya başlayalım..

    public interface IBackground

    {

        Image BackgroundImage { get; }

    }

Bu interface sayesinde bunu kullanan classların Image tipinde ki “bu image bizim ilgili formumuzun zemin rengi için gerekli” property’iyi tanımlama zorunluluğu getiriyoruz..

    public class TransFxControlBase : Control

    {

        protected bool HasImage = false;

 

        protected override void OnPaintBackground(PaintEventArgs e)

        {

            IBackground form = Parent as IBackground;  //DİKKAT! Burda ilgili kontrolün parent’ının bu interface’i implemente edip etmediğini kontrol ediyoruz.. Değilse zaten normal bir şekilde calismaya devam edecektir.

            if (form == null)

            {

                base.OnPaintBackground(e); // normal...

                return;

            }

            else

            {

                HasImage = true;  // evet implementasyon yapıldıysa OK!!

            }

 

            e.Graphics.DrawImage(

              form.BackgroundImage,

              0,

              0,

              Bounds,

              GraphicsUnit.Pixel);  // işte şimdi resmi zemine oturtuyoruz..!

        }

 

        protected override void OnTextChanged(EventArgs e)

        {

            base.OnTextChanged(e);  //Text değişimine karşı resmin geçerliliği kontrol ediliyor..Invalidate kullanmazsak bu evet fire edildiğinde refresh problemi yaşaniyor..

            Invalidate();

        }

 

        protected override void OnParentChanged(EventArgs e)

        {

            base.OnParentChanged(e); // Aynı şekilde ilgili kontrolün parent’inin değişmesi de kontrolün refresh’ini gerektiren durumlardan birisidir..

            Invalidate();

        }

    }

 

Evet yukarıda kod içerisinde durumu açıkca ifade etmeye calistik.Şimdi isterseniz gelin yazdığımız bu customcontrol classindan türeyecek olan TransFxLabel isimli class’imizi yazalım..

        public class TransFxLabel : TransFxControlBase

    {

        ContentAlignment alignment = ContentAlignment.TopRight; // ilgili kontrolümüz içerisinde text ifadenin nerede yer alacağını set ediyoruz..

        StringFormat format = null;

        Bitmap scr_pix = null;

 

        public TransFxLabel()

        {

            format = new StringFormat();

        }

 

        public ContentAlignment TextAlign // bu property sayesinde de tam olarak string ifadenin nerede belirleneceği enumeration ile set edilmiş oluyor...

        {

            get

            {

                return alignment;

            }

            set

            {

                alignment = value;

                switch (alignment)

                {

                    case ContentAlignment.TopCenter:

                        format.Alignment = StringAlignment.Center;

                        format.LineAlignment = StringAlignment.Center;

                        break;

                    case ContentAlignment.TopLeft:

                        format.Alignment = StringAlignment.Near;

                        format.LineAlignment = StringAlignment.Near;

                        break;

                    case ContentAlignment.TopRight:

                        format.Alignment = StringAlignment.Far;

                        format.LineAlignment = StringAlignment.Far;

                        break;

                }

            }

        }

// en önemli metodlardan biri olan on paint de de eğer türetme yaptığımız base control class’inda  background tanımı yoksa temizlik kontrolün areasi temizleniyor..

        protected override void OnPaint(PaintEventArgs e)

        {

            if (!base.HasBackground)

            {

                if (scr_pix == null)

                {

                    scr_pix = new Bitmap(ClientSize.Width, ClientSize.Height);

                }

                using (Graphics g = Graphics.FromImage(scr_pix))

                {

                    using (SolidBrush brush = new SolidBrush(Parent.BackColor))

                    {

                        g.Clear(BackColor);

                        g.FillRectangle(brush, ClientRectangle);

                    }

                }

            } // eğer varsa da  burda ilgili text ifadeyi kontrolümüzün içerisine basıyoruz...!

            else

            {

                using (SolidBrush brush = new SolidBrush(ForeColor))

                {

                    e.Graphics.DrawString(

                      Text,

                      Font,

                      brush,

                      new Rectangle(0, 0, Width, Height),

                      format);

                }

            }

        }

    }

 

 

Buraya kadar herşeyi kolayca hallettik..Bir üstünden geçelim , once interface’imizi tasarladık ve daha sonra ilgili base controlümüzü yazdık.Bu kontrolde resim olup olmayacağına dair gerekli bilgiyi bu kontrolün containeri pozisyonda olan ilgili form nesnesinden öğreniyoruz..Burası cok onemli...Gerekli invalidate lerimizi ilgili metodları override ederek gerçekleştirdik..Peki geriye üzerine text ifademizi belirteceğimiz ve basecontrol ümüzden türeyecek olan label’imizi geliştirmek kaldı..Onun içinde onemli 2 nokta var 1. Yazılacak olan text ifadenin tam olarak nerede cıkacağı 2.onemli olan da text ifadenin ne olduğu..Bir burda 2 property ile sınırlı tuttuk lakin siz fontun size’dan tutunda font type’ina kadar hepsini set edebileceğiniz property’leri tanımlayarak cok daha şık ve esnek bir kontrol yapabilirsiniz...Bu label kontrolümüzde de oncelikle türettiğimiz base class içerisinde yer alan bool tipindeki HasBackground un true olup olmadığını “ki bu da IBackGround interfaceine bağlı olarak set ediliyordu” kontrol ediyoruz..yoksa ilgili alan temizleniyor yani kontrolun sınırları dahilinde olan değilsede kontrole text ifademizi  belli değerler ile basıyoruz..

 

Şimdi ise gelelim son noktaya ; burda da ilgili olan parent’ın set edilmesine geldi sıra..Yaptığımız şey aslında System.Windows.Form class’ından türeyen bir baseForm class yazmak ve ilgili parent object imiz olan default Form1 nesnesini bundan ve Ibackground nesnesinden türetmek...Tabi bunun doğurduğu bazı sakıncalar yok değil örnek vermek gerekirse , form1 nesnesinin designer’ı bu noktada fail oluyor.Design kısmına geçmek istediğinizde error alıyorsunuz..Ama kodunuz build success diyecektir..Form’un kendisine direkt bir müdahele olduğu için designer bu noktada tıkanıyor..Eğer control library olacak şekilde yazacak olursak sorun olmayacaktır...

 

    public class FormBase : Form, IBackground

    {

        Bitmap background;

 

        public FormBase()

        {

            background = new Bitmap(@"PROGRAM FILES\TRANSPARENTFX\MobilMain.JPG");

        }

 

        protected override void OnPaint(PaintEventArgs e)

        {

            e.Graphics.DrawImage(background, 0, 0);

        }

 

        public Image BackgroundImage

        {

            get { return background; }

        }

 

    }

 

Burda ilgili formbase classinin içerisinde yine image içeriğine sahip olan bir attribute tanımlıyoruz..Bu bizim backgroundimizi oluşturacak ...peki bu nerden geliyordu , Ibackground! İnterface’imiz işte tam bu noktada devreye giriyor..!ilgili mobilMain.jpg dosyasını oluşturduğunuz mobil projenin içerisine sürükle bırakla atın ya da siz hangi isimde hangi tip resim vermek isterseniz tamamen size kalmış.( Resmin properties kısmında Copy to output Directory property’sini Copy if newer olarak set etmeyi unutmayın!.)Dikkat ettiyseniz formbase’in her onpaint event’i fire olduğunda ekrana ilgili image’i çizdiriyoruz..

 

    public partial class Form1 : FormBase

    {

        TransFxLabel label;

 

        public Form1()

        {

            InitializeComponent();

            label = new TransFxLabel();

            label.Font = new Font("Times New Roman", 12f, FontStyle.Bold);

            label.ForeColor = Color.White;

            label.Text = "Rock C#!";

            label.Bounds = new Rectangle(20, 60, 200, 50);

            this.Controls.Add(label);

            this.MinimizeBox = false;          

        }

    }

 

 

Bu kısımda ilgili Form1 classini az önce yazdığımız FormBase classından türetip Initalize component’inden hemen sonra kendi private olan TransFxLabel kontrolümüzü örnekliyor ve ilgili contanier olan form1 in kontrolleri içerisine yerleştiriyoruz..İşte hepsi bu..Geriye sadece calistirmak kalıyor..

 

Sonuç ;

 

resim1 bulunamadı!

 

Başka bir makalede görüşmek dileğiyle..

 

Kaynakça : MSDN , Christian Helle

 

Eralp Erat

MVP – Mobile Devices

MCP,MCAD.NET,MCSD.NET

http://www.eralperat.com

HIMS