C# ile Yazıcı Çıktısı Alma İşlemleri

C# ile Yazıcı Çıktısı Alma İşlemleri

C# ile Windows iş uygulaması geliştiriyorsanız programınızın mutlaka yazıcı çıktısı alma bölümü olacaktır. Bu makalede C# ile nasıl yazıcı çıktısı alınabileceğinin temelleri üzerinde duracağım.

.NET sınıf kütüphanesi her alanda olduğu gibi yazıcı çıktısı alma ile ilgili bir takım sınıflar sağlamıştır. PrintDocument sınıfı yazı çıktısı alma ile ilgili en temel sınıftır. Bu yazıda bu sınıfın özelliklerini, olaylarını ve metotlarını ayrıntılı bir şekilde inceleyip tek sayfalı yada çok sayfalı yazıcı çıktısının nasıl alınabileceğini göstereceğim. Ayrıca yazıcı çıktısı alma ile çok yakından ilgili  olan PrintPreview, PageSetupDialog ve PrintDialog gibi sınıflarıda inceleyeceğiz.

PrintDocument Sınıfı

Bu sınıf programlarımıza yazıcı çıktısı alma desteğini eklemek için kullanabileceğimiz en temel yapıdır. Bu sınıf türünden bir nesne yaratıldığında çıktı alma ile ilgili hemen her tür bilgiye erişmemiz mümkündür.

PrintDocument YaziciCiktisi = new PrintDocument();

şeklinde bir tanımlama yaptığımızda varsayılan yazıcı(default printer) ile çalışılmaktadır. Bir dökümanı yazıcıya göndermek için PrintDocument sınıfının Print() metodu kullanılır. Print() metodu çağrıldığı anda PrintPage olayı meydana gelir. Bu olayı yakalayan kontrol yazıcıya gönderilecek döküman üzerinde işlemler yaparak çıktının şeklini belirlemelidir. Her bir sayfa için ayrıca PrintPage olayı meydana geleceği için her bir olay içinde doğru sayfaları yazıcıya göndermek için bir takım işlemler yapmak gerekecektir. Aksi halde her defasında birinci sayfayı yazıcıya gönderme ihtimalimiz vardır. Kısacası PrintPage olayı olmadan yazıcıya çıktı bilgilerini gönderemeyiz. Bu yüzden ilk olarak PrintPage olayını ve bu olaya ait argümanları içeren PrintPageEventArgs sınıfını inceleyelim.

Önce PrintPage olayının argümanlarını içeren PrintPageEventArgs sınıfının üye elemanlarını inceleyelim, ardında bir konsol uygulamasından yazıcıya nasıl bir döküman göndereceğimizi göstereceğim.

PrintPageEventArgs sınıfnın üye elemanları :

Graphics : Yazıcıya gönderilecek döküman bilgilerini belirleyen grafik nesnesidir. Yazıcya gönderilecek bilgilerin tamamı bu nesne içerisinde belirtilecektir. Not : Graphics sınıf GDI+ kütüphanesinin en önemli sınıfıdr. 

Cancel : Çıktı alma işleminin iptal edilip edilemeyeceği ile ilgili bilgi veren bool türünden bir elemandır. Eğer değeri true ise çıktı alma işlemi iptal edilecektir.

HasMorePages : Yazıcıya gönderilecek çıktının birden fazla sayfa kapladığı durumlarda PrintPage olayına ilişkin metotta bu özelliğin true olarak değiştirilmesi gerekir. Böylece bundan sonraki PrintPage olaylarında bu değişken kontrol edilerek diğer sayfaların çıktıya gönderilmesi ile ilgili işlemler yapılır.

MarginBounds 
: Yazıcıya gönderilen çıktı dökümanının en ve boyutlarını temsil eden Rectangle türünden bir özelliktir. Rectangle sınıfıda GDI+ kütüphanesinin bir parçasıdır. Bu özellikte yazıcıya gönderilecek çıktının sadece üzerine çizim yapılabilen kısmı belirtilir.

PageBounds : Yazıcıya gönderilen dökümanın tamamının en ve boy değerlerini tutan yine Rectangle sınıfı türünden bir elemandır.

PageSettings: İlgili dökümana ait sayfa ayarlarını tutan ve PageSettings sınıfı türünden bir elemandır. PageSettings sınıfının Color, Landscape, Margins, PaperSize, PaperSource, PrinterResolution gibi sayfa ile ilgili bilgi tutan üye özellikleri bulunmaktadır.

Şimdi basit bir örnekle yazıcıya çıktı gönderelim. Örneğimizde varsayılan yazıcınıza, sol üst köşesi (20,20) koordinatlarında eni ve boyu 100 olan bir dörtgen içeren sayfayı göndereceğiz. Gönderilecek sayfadaki dörtgeni çizmek için tahmin edeceğiniz üzere Graphics nesnesini kullanacağız.

using System;
using System.Drawing.Printing;
using System.Drawing;

class Printer

    static void Main() 
    { 
        PrintDocument PD = new PrintDocument(); 
        PD.PrintPage += new PrintPageEventHandler(OnPrintDocument); 

         try 
        { 
            PD.Print(); 
        } 
         catch 
        { 
            Console.WriteLine(“Yazıcı çıktısı alınamıyor…”); 
        } 
         finally 
        { 
            PD.Dispose(); 
        } 
    } 

    private static void OnPrintDocument(object sender, PrintPageEventArgs e) 
    { 
        e.Graphics.DrawRectangle(Pens.Red,20,20,100,100); 
    }
}

Yukarıdaki programı derleyip çalıştırdığınızda hiç bir uyarı eğer verilmeden sisteminize bir yazıcı bağlı OnPrintDocument() metodunda hazırlanan içerik yazıcıya gönderilecektir. Eğer sisteminize bağlı bir yazıcı yoksa doğal olarak catch bloğundaki kod çalışacaktır.

Çizilen dörtgen nesnesinin kağıdın neresine basılacağını biz belirliyoruz. MarginBounds özelliğini kullanarak çizilecek içeriğin doğru noktaya çizilmesini sağlayabiliriz. Bu özellik sizin yazıcı ayarlarınız ile ilgili olduğu için programlama yolu ile kod içerisinden değiştirilemez. Yani bu özellik “read only” bir özelliktir. Dikkat edilmesi gereken diğer bir noktada yazıcıya gönderilecek içeriğin PageBounds özelliği ile belirtilen dörtgenin dışına taşmamasıdır. Bu yüzden çizimleri yapılırken bu özellik baz alınmalıdır.

Yukarıda yazdığımız basit programda eksiklik bulunmaktadır. Bu eksiklik çizilecek dörtgenin tek bir sayfaya sığmadığı durumlarda görülür. Söz gelimi eğer dörtgenin yüksekliğini 2000 yaparsak yazıcıdan sadece ilk kağıda sığan bölümü çıkacaktır. Birden fazla sayfası olan çıktıları yazıcıya göndermek için PrintPageEventArgs sınıfnın HasMorePages özelliği kullanılır. Bu özellik OnPrintDocument() metodu içerisinde true değerine çekilerek çıktı alma işleminin devam ettiği belirtilmelidir. Ayrıca her bir sayfanın içeriğide metot her çağrıldığında farklı bir biçimde oluşturulacağı için programcının bu ayrımı da kodlaması gerekmektedir. Örneğin yüksekliği 2000 pixel olan bir dikdörtgeni tek sayfada bastıramayacağımız için ilk sayfaya sığmayan diğer bölümleri parçalayarak her bir sayfaya sığacak şekilde ayarlamalıyız. Bu işlem için PrintPageEventArgs sınıfnın HasMorePages değişkenini kullanacağız.

Hemen diğer bölümlere geçmeden önce birden fazla sayfalı yazıcı çıktısı alma işlemine örnek verelim. Bu örnekte bir text dosyasının içeriğini yazıcıya nasıl gönderebileceğimizi inceleyeceğiz. Tabi burda yazının birden fazla sayfada olup olmadığının kontrolünü yapmamız gerekir. Yazıları yazıcı çıktısına göndermek için Graphics sınıfnın DrawString metodunu kullanacağız. Bu metot grafik arayüzüne belirli bir fontta ve font büyüklüğünde yazı yazmamızı sağlar. Önce örneği inceleyelim ardından örnek üzerinde biraz konuşacağız.

using System;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Printing;

class Printer
{
    private static StreamReader dosyaAkimi;  

    static void Main(string[] args) 
    { 
        dosyaAkimi = new System.IO.StreamReader(“C:\\Print.txt”); 

        PrintDocument PD = new PrintDocument(); 
        PD.PrintPage += new PrintPageEventHandler(OnPrintDocument); 

        try 
        { 
            PD.Print(); 
        } 
        catch 
        { 
            Console.WriteLine(“Yazici çiktisi alinamiyor…”); 
        } 
        finally 
        { 
            PD.Dispose(); 
        } 
    } 

    public static void OnPrintDocument(object sender,PrintPageEventArgs e) 
    { 
        Font font = new Font(“Verdana”, 11) ; 
        float yPozisyon = 0 ; int LineCount = 0 ; 
        float leftMargin = e.MarginBounds.Left; 
        float topMargin = e.MarginBounds.Top; 

        string line=null; 

        float SayfaBasinaDusenSatir = e.MarginBounds.Height / font.GetHeight() ; 

        while (((line=dosyaAkimi.ReadLine()) != null) && LineCount < SayfaBasinaDusenSatir) 
        { 
            yPozisyon = topMargin + (LineCount * font.GetHeight(e.Graphics)); 
            e.Graphics.DrawString (line, font, Brushes.Red, leftMargin,yPozisyon); 

            LineCount++; 
        } 

        if (line = = null) 
            e.HasMorePages = false ; 
        else 
            e.HasMorePages = true ; 

    }
}

Yukarıdaki program herhangi bir text formatındaki dosyayı yazıcıya gönderek çıktı almanızı sağlayacaktır. Dosyanın içeriğini yazıcıya gönderirken çıktının ne şekilde olacağı tamamen programlama yolu ile bizim tarafımızdan yapılmaktadır. Örneğin çıktının yazı fontunu GDI+ kütüphanesinin bir sınıfı olan Font ile yazı renginide yine GDI+ kütüphanesinin Brushes sınıfının üye elemanları ile rahatlıkla değiştirebiliriz.

Yukarıdaki örnek uygulamada en önemli kısım dosya içeriğinin yazıcıyı gönderilmesi sırasında görülür. Dosya içeriğinin birden fazla sayıda sayfa içermesi durumunda dosya akımından bir sayfaya sığacak kadar satır okunmalıdır. Eğer dosya akımının sonuna gelinmediyse HasMorePages özelliği true yapılarak OnPrintDocument metodunun yeniden çağrılması gerekir. Kaynak koddanda gördüğünüz üzere dosya akımından okunan satır null değereeşit olduğunda yani dosyanın sonuna gelindiğinde HasMorePages özeliiği false yapılarak Print() metodunun icrası sonlandırılmıştır.

Bir diğer önemli nokta ise yazıcıya gönderilecek her bir sayfada kaç satırın bulunacağının belirlenmesidir. Sayfa başına düşen satır sayısı, sayfanın yazıcıya gönderilecek bölümünün yüksekliğinin yani e.MarginBounds.Height ‘in çıktıya gönderilecek yazıya ait fontun yüksekliğine bölümü ile elde edilir. Sayfa başına üşen satır sayısı elde edildikten sonra herbir sayfanın içeriği while döngüsü yardımı ile hazırlanır. Okunan satır sayısı null değere eşit olmayana kadar ve okunan satır sayısı sayfa başına düşen satır sayısı olana kadar döngüye devam edilir. Döngü içerisinde PrintPageEventArgs olay argümanlarını içeren sınıfın Graphics nesnesine DrawString() metodu yardımıyla dosya akımından okunan satır yazılır. Bir sonraki satırın çıktı ekranının neresinden başlayacağını tutmak için ise her bir satır okunduğunda yPozisyon’u kullanılan font’un yüksekliği kadar artırılır. Bütün bu işlemleri yaptıktan sonra HasMorePages özelliği ayarlanır ki sonraki sayfalar çıktıya gönderilsin. Eğer dosya sonuna gelinmişse artık basılacak sayfa yok demektir ve HasMorePages özelliği false olarak belirlenir.

Not : Dosya akımının neden OnPrintDocument() metodunun içinde tanımlanmadığını merak ediyor olabilirsiniz. Bunun sebebi OnPrintDocument() metodunun her bir sayfa için yeniden çağrılmasıdır. Eğer dosya akımını bahsi geçen metotta tanımlamış olsaydık her defasında dosya akımı baştan okunacağı için hiç bir zaman dosya akımının sonuna gelemeyecektik ve her defasında sonsuza dek ilk sayfayı çıktıya göndermiş olacaktık. Bu yüzden dosya akımını global düzey diyebileceğimiz bir noktada yani ana sınıfımın bir üye elamanı olacak şekilde tanımladık.

Aklınıza takılmış olabilecek diğer bir nokta ise yazıcının renk ayarlarıdır. Eğer yazcınız renkli çıktı almayı desteklemiyorsa DrawString() metoduna parametre olarak geçtiğimiz Brushes.Red parametresinin bir önemi olmayacaktır. Bu yüzden dökümanları yazıcya göndermeden yazcının renkli baskıyı desteleyip desteklemediğini kontrol etmek en akıllıca yöntemdir.  Bu şekildeki bri kontrol için PrintDocument sınıfının PrinterSettings özelliği kullanılabilir. Bu özellik varsayılan yazcınız ile ilgili bir takım ayarları yapısında barındıran özelliklere sahiptir. Örneğin varsayılan yazıcınızın renkli bakıyı destekleyip desteklemediğini kontrol etmek için SupportsColor özelliğini aşağıdaki gibi kullanabilirsiniz. Not : SupportsColor özelliği bool türündendir.

using System;
using System.Drawing.Printing;
using System.Drawing;

class Printer

    static void Main() 
    { 
        PrintDocument PD = new PrintDocument(); 
        PD.PrintPage += new PrintPageEventHandler(OnPrintDocument); 

         if ( PD.PrinterSettings.SupportsColor )
         {
              //renkli baskı ayarları
         }
         else
         {
              //renksiz baskı ayarları
         }

    } 

    private static void OnPrintDocument(object sender, PrintPageEventArgs e) 
    { 
        …. 
    }
}

PrinterSettings yolu ile elde edebileceğimiz diğer önemli özellikler aşağıda listelenmiştir.

CanDuplex : bool türünden olan bu değişken yazıcının arkalı önlü çıktı almayı destekleyip desteklemediğini belirtir.

Copies: short türünden olan bu değişken yazıcıya gönderilecek dökümanın kaç kopya çıkarılacğını belirtir. Eğer 10 sayfalık bir döküman için bu özelliği 5 olarak girerseniz 50 adet kağıdınızı yazıcıya yerleştirmeyi unutmayın.

CanDuplex
: bool türünden olan bu değişken yazıcının arkalı önlü çıktı almayı destekleyip desteklemediğini belirtir.

Duplex : Duplex enum sabiti türünden olan bu değişken arkalı önlü baskı özelliğini belirler. Duplex numaralandırması Default,Sizmplex,Horizontal ve Vertical olmak üzere dört tane üyesi vardır.

IsDefaultPrinter : PrinterName ile belirtilen yazıcının bilgisayarınızdaki varsayılan yazıcı(default printer) olup olmadığını belirtir.

IsValid
: PrinterName ile belirtilenin  gerçekten sisteminize ait bir yazıcı olup olmadığını belirtir.

PaperSizes : Yazıcı tarafından desteklenen sayfa ebatlarının PaperSizeCollection türünden bir koleksiyon nesnesi ile geri döner. Bu koleksiyondaki her bir eleman System.Drawing isim alanında bulunan PaperSize türündendir. PaperSize sınıfnın Width(sayfa eni), Height(sayfa boyu),Kind(sayfa türü) gibi özellikleri bulunmaktadır.

PaperSources : Yazıcı tarafından desteklenen sayfa kağıt alma kaynaklarını PaperSourceCollection türünden bir koleksiyon nesnesi ile geri döner. Bu koleksiyondaki her bir eleman System.Drawing isim alanında bulunan PaperSource türündendir. PaperSource sınıfnın Kind özelliği PaperSourceKind numaralandırması türünden bir nesne olup kağıt kaynağının tipini belirtir.Bu numaralandırmanın bazı semboleri şunlardır : Envelope, Cassette, Custom, Manuel, TractorFeed.

PrintToFile : Çıktının herhangi port yerine bir dosyaya yazdırılıp yazdırılmayacağını tutan bool türünden bir değişken. Bu değişken daha çok birazdan göreceğimiz PrintDialog ekranının görüntülenmesi sırasında değiştirilip kullanılır.

Çıktı Ön-İzleme Penceresi

Profesyonel uygulamaların tamamında yazıcıya çıktı göndermeden önce kullanıcıya ön izleme imkanı sağlanır. .NEt ortamında program geliştiriyorsanız Windows’un standart ön izleme penceresini programlama yolu ile görüntülemeniz son derece kolaydır. Bu ekranın görüntülenmesi için System.Drawing isim alanında bulunan PrintPreviewDialog sınıfı kullanılır. Bu sınıf ile ilişkilendirilmiş PrintDocument nesnesinin PrintPage olayına ilişkin metot çalıştırılarak ön-izleme penceresindeki içerik elde edilir.

Bir PrintPreviewDialog nesnesi oluşturulduktan sonra nesnenin Document özelliğine PrintDocument türünden bir nesne atanır. Ve ardından PrintPreviewControl türünden olan nesne üzerinden Show() yada ShowDialog() metotları kullanılarak ön izleme ekranı gösterilir.

Ön izleme çıktısnın görüntülendiği pencereyi elbette PrintDocument sınıfnın Print() metodunu çağırmadan önce göstermeliyiz. Daha önce yaptığımız ve dosya içeriğini yazıcıya gönderen uygulmanın Main() metodunu aşağıdaki gibi değiştirerek ön izleme ekranından çıktıya gönderilecek içeriği görüntüleyelim.

static void Main(string[] args) 

        dosyaAkimi = new System.IO.StreamReader(“C:\\Print.txt”); 

        PrintDocument PD = new PrintDocument(); 
        PD.PrintPage += new PrintPageEventHandler(OnPrintDocument); 

         PrintPreviewDialog pdlg = new PrintPreviewDialog();
         pdlg.Document = PD;
         pdlg.ShowDialog(); 

        try 
        { 
            PD.Print(); 
        } 
        catch 
        { 
            Console.WriteLine(“Yazici çiktisi alinamiyor…”); 
        } 
        finally 
        { 
            PD.Dispose(); 
        } 

Programı yeni haliyle derleyip çalıştırdığımızda ilk önce öıktı ön izleme ekranı aşağıdaki gibi gösterilecektir. Not : Çıktıya gönderilecek dosyanın yolu örneğimiz için “C:\Print.txt” şeklinde olmalıdır.

Sayfa Düzenleme Ekranı (PageSetupDialog Sınıfı)

Dökümanı çıktıya göndermeden önce gönderme işleminin hangi yazıcı ayarları ile yapılacağını belirlemek için genellikle sayfa düzenleme ekranı gösterilir. Bu ekranda kağıt tipinden, yazcının kağıt kaynağına kadar bir çok özelliği değiştirmeniz mümkündür. Bu ekranda yapılan bütün değişiklikler PrintDocument sınıfının PrinterSettings özelliğine aktarılır. Sayfa düzenleme ekrana System.Drawing isim alanında bulunan PrintSetupDialog sınıfı ile gerçekleştirilir. Bu sınıfının kullanımı PrintPreviewDialog sınıfının kullanımı ile nerdeyse aynıdır. Bu yüzden ayrıca açıklmaya gerek duymuyorum.

Son olarak yazıcı ön izleme ekranından önce sayfa düzenleme ekranının gösterilmesini sağlamak için uygulamamaızın Main() metodunu aşağıdaki gibi değiştirin ve çalıştırın.

static void Main(string[] args) 

        dosyaAkimi = new System.IO.StreamReader(“C:\\Print.txt”); 

        PrintDocument PD = new PrintDocument(); 
        PD.PrintPage += new PrintPageEventHandler(OnPrintDocument); 

         PrintDialog pdiyalog = new PrintDialog(); 
         pdiyalog.Document = PD; 
         pdiyalog.ShowDialog();

        PrintPreviewDialog pdlg = new PrintPreviewDialog(); 
        pdlg.Document = PD; 
        pdlg.ShowDialog(); 

        try 
        { 
            PD.Print(); 
        } 
        catch 
        { 
            Console.WriteLine(“Yazici çiktisi alinamiyor…”); 
        } 
        finally 
        { 
            PD.Dispose(); 
        } 

Programı derleyip çalıştırdığınızda karşınıza ilk çıkacak görüntü aşağıdaki ekran olacaktır.

Bu örnekle birlikte yazıcı çıktısı alma ile ilgili temel işlemlerin anlatıldığı yazımızın sonuna geldik. .NET teki yazıcı çıktısı alma işlemleri bu anlattıklarımla sınırlı değildir. Ancak bu yazıda anlatılanlar bu konuya çok hızlı bir giriş yapmanızı sağlamıştır. İlerleyen yazılarda görüşmek dileğiyle.

Kaynaklar :

MSDN Yardım Dökümanları

 

 

Düzenli İfadeler(Regular Expressions) Nedir?

Regular expression bir metni düzenlemek yada metin içerisinden belli kurallara uyan alt metinler elde etmek için kullandığımız bir dildir. Bir regular expression, string tipindeki karakter topluluğuna uygulanır. Sonuç olarak substringler oluşur yada orjinal metnin bir kısmını içeren değiştirilmiş yeni metinler elde edilir.

Regular Expression’larda Kullanılan Özel Karakterler ve Etkileri

Regular expression desenleri tanımlamada kullanılan özel karakterleri örnekleri ile anlatırsak sanırım regular expressionlar daha tanıdı ve kolay gelebilir.

1.)  “.” Karakteri

Tek bir karakteri temsil eder(yeni satır karakteri hariç).
“CSharp.edir” şeklindeki bir desen CSharpnedir, CSharpNedir, CSharpSedir, CSharp3edir gibi stringleri döndürebilir.

2.)  “[]” Karakterleri

Bir arrayi yada aralığı temsil eder.
“CSharp[SNY]edir” deseni, CSharpSedir, CSharpNedir ve CSharpYedir stringlerini döndürür.
“CSharp[a-z]edir” şeklindeki kullanım aralık belirtmeye yarar.
“CSharp[0-9]edir” şeklindeki kılanlım ise sayısal aralık belirtmeye yarar.

3.)  “?” Karakteri

Kendinden önceki karakterin stringte olması yada olmamasını sağlar.
“CSharpn?edir” deseni CSharpedir yada CSharpnedir döndürür.

4.)  “\” Karakteri

Kendinden sonraki özel karakterin stringe dahil edilmesini sağlar.
“CSharpnedir\?” deseni CSharpnedir? Stringini döndürür. (Eğer “\” karakterini kullanmamış olsaydık CSharpnedi yada CSharpnedir dönerdi.)

5.)  “*” Karakteri

Kendinden önceki karakterin yada stringin hiç olmaması yada istediği sayıda olmasını sağlar.
“CSharpnedir*” deseni, CSharpnedi, CSharpnedir, CSharpnedirr, CSharpnedirrr, … döndürür. “CSharp(nedir)*” deseni ise CSharp, CSharpnedir, CSharpnedirnedir, … döndürür.

6.)  “{}” Karakterleri

Kendinden önce gelen karakterin belirtilen sayıda tekrar etmesini sağlar.
“C{4}Sharpnedir” deseni, CCCCSharpnedir stringini döndürür.

7.)  “^” Karakteri

Satır başını ifade eder.
“^CSharpnedir” deseni, satır başında “CSharpnedir” stringi varsa bunu döndürür.

8.)  “$” Karakteri

Satır sonunu ifade eder.
“CSharpnedir$” deseni, satır sonunda “CSharpnedir” stringi varsa bunu döndürür.

Basit Bir Tarih Deseni Yapalım

Şimdi işin pratiğine gelelim ve adım adım tarih deseni oluşturalım. Daha sonra ise oluşturduğumuz bu tarih desenini bir konsol programında kullanalım.

Tarih desenimiz bir string içerisindeki, GG/AA/YYYY formatlarındaki tarihleri yakalayacak yapıda olsun.

Önce desenimizin GG yani tarihin gün belirtilen kısmını tanımlayalım :

“(0?[1-9])”
// 1, 2, .., 9, 01, 02, …, 09 gibi yazılmış günleri tanımlar.

“([12][0-9])”
// 10, 11, …, 29 gibi yazılmış günleri tanımlar.

“(3[01])”
// 30, 31 günlerini tanımlar.

// Bu üç tanımı OR (|) işlemiyle
// birleştirirsek gün tanımını elde ederiz.

// Gün tanımı :
“((0?[1-9])|([12][0-9])|(3[01]))”
Şimdi desenimizin AA yani tarihin ay belirtilen kısmını tanımlayalım :

“(0?[1-9])”
// 1, 2, .., 9, 01, 02, .., 09 gibi yazılmış ayları tanımlar.

“(1[0-2])”
// 10, 11, 12 aylarını tanımlar.

// Bu iki tanımı OR işlemiyle
// birleştirirsek ay tanımını elde ederiz.

// Ay Tanımı :
“((0?[1-9])|(1[0-2]))”
Şimdi desenimizin YYYY yani tarihin yıl belirtilen kısmını tanımlayalım :

“([12][0-9][0-9][0-9])”
//1000 ile 2999 yılları arasındaki tüm yılları içerir.
Ve son olarak tanımladığımız gün, ay ve yıl desenlerini “/” ile birleştirelim :

“((0?[1-9])|([12][0-9])|(3[01]))(/)(0?[1-9]|1[0-2])(/)([12][0-9][0-9][0-9]))”

Basit Bir Test Programı Yazalım

Şimdi elde ettiğimiz tarih desenini test edebileceğimiz basit bir konsol programı yazalım. Ek bilgi olarak “?” şeklindeki bir ifadeyi desenin önüne ilave ederseniz, bir desen grubu ifade etmiş olursunuz ve birkaç deseni aynı anda kontrol edebilirsiniz.

using System;

using System.Text.RegularExpressions;

class Test

{

      public static void Main()

      {

            // Regular Expression için bir desen (pattern) tanımlıyoruz :

            string tarihDeseni=@”(?((0?[1-9])|([12][0-9])|(3[01]))(/)(0?[1-9]|1[0-2])(/)([12][0-9][0-9][0-9]))”;

            // Regular Expression’umuzu tanımlıyoruz :

            Regex benimRegex=new Regex(tarihDeseni);

            // Kullanıcıdan tarih içeren metni talep ediyoruz :

            Console.WriteLine(“Lütfen içinde tarih olan bir metin giriniz :”);

            // Tarih arayacağımız metni konsoldan alıyoruz :

            string metin=Console.ReadLine();

            // Metin içerisindeki tarihleri (birden fazla olabilir) Collection nesnesine atıyoruz :

            MatchCollection benimMatchCollection=benimRegex.Matches(metin);

            // Metin içindeki herbir tarihi ekrana yazdırıyoruz :

            foreach(Match benimMatch in benimMatchCollection)

            {

                  Console.WriteLine(benimMatch.Groups[“tarih”]);

            }

            Console.Read();

      }

}

 

 

 

Bir Web Sitesindeki E-Mail Adreslerini Yakalamak (Düzenli İfadeler 2)

Gene şu sıkıcı düzenli ifadeler değil mi? Bu makalede düzenli ifadelerin ne kadar etkileyici olduğunu bir örnek üzerinde anlatmaya çalışacağım.
Web sitelerinin birebir kopyasını kendi bilgisayarınıza kopyalayan ( Teleport gibi) programları bilirsiniz. Önce bir sayfanın kaynak kodunu indirir. İçindeki linkleri ve resim dosyalarını belirler. Sonra sıra bu link ve resim dosyalarına gelir.

Hiç elinizdeki kaynak kodun linklerini nasıl ayıklayacağınızı düşündünüz mü?
İşte düzenli ifadeler burada gerçekten harikalar yaratır.
Fazla uzatmadan örneğimize geçelim…

E-Mail Yakalayıcı

Şimdi yapacağımız örnekte önce bir web sitesinin kaynak kodunu indirip, içerisindeki e-mail linklerini elde edeceğiz.
Öncelikle sayfanın kaynak kodunu indirelim
Bunun için iki basit metod yazdım. İlki sayfanın adresini kullanıcıdan alıyor, ikincisi sayfaya bağlanıp kaynak kodu indiriyor :

// Adresi Alan Metod :
private string AdresiAl()
{
    string adres=”http://” + txtAdres.Text;
    return adres;
}

// Sayfanın Kaynak Kodunu Döndüren Metod :
private string KaynakAl(string adres)
{
    lblStat.Text=”Siteye Bağlanıyor…”;
    WebResponse benimResponse=null;
    try
    {
        WebRequest benimWebRequest=WebRequest.Create(adres);
        benimResponse=benimWebRequest.GetResponse();
    }
    // Eğer internet bağlantısı yoksa yada site adresi yanlış ise :
    catch(WebException e)
    {
        lblStat.Text=”Siteye Bağlanamıyor.”;
        return null;
    }
    // Site içeriği stream olarak alınıyor :
    Stream str=benimResponse.GetResponseStream();
    StreamReader reader=new StreamReader(str);
    string kaynak=reader.ReadToEnd();
    // Tüm içerik küçük harfle döndürülüyor.
    //Daha fazla kontrol yapmamak için bir önlem
    return kaynak.ToLower();
}

Sayfanın kaynak kodunu indirdikten sonra içindeki e-mail linklerini bulup bir diziye atan bir başka fonksiyon daha yazdım. Öncelikler e-mail linkini yakalayan deseni (pattern) açıklamaya çalışalım.

Bildiğiniz gibi e-mail linkleri
<a href=”mailto:aaa@bbb.ccc”> gibi ifade edilir.

O zaman desenimiz (href=) ifadesi ile başlamalıdır.
Ardından (‘) yada (“) karakterleri gelebilir.

“(href=)((‘)|(“”))”

Sonra “mailto:” ifadesi gelir :

“(href=)((‘)|(“”))(mailto:)”

“mailto:” ifadesinden sonra istediğimiz ifade yani e-mail adresi gelir. Bunu “mail” isminde bir grup tanımlayarak elde edeceğiz.

“(href=)((‘)|(“”))(mailto:)(?<mail>(.*))”
// (.*) ifadesi kendinden sonra gelen desene kadar her karakteri alan bir desendir.

Şimdi desenimizi sonlandıralım :

“(href=)((‘)|(“”))(mailto:)(?<mail>(.*))((‘)|(“”))”
Kısaca, “mailto:” ile tırnak karakterleri arasındaki her ifade bizim için mail grubuna dahil oldu.

Şimdi E-mail adreslerini dizi şeklinde döndüren metodumuzu yazalım :

// Sayfanın içindeki mail adreslerini dizi şeklinde döndüren metod :
private string[] MailAl(string kaynak)
{
    lblStat.Text+= “Kaynak kod alındı… ” + “Mailler ayrıştırılıyor… “;
    // Desenimiz :
    string mailDeseni=@”(href=)((‘)|(“”))(mailto:)(?<mail>(.*))((‘)|(“”))”;
    int i=0;
    // Regular Expressionumuzu tanımlıyoruz :
    Regex benimRegex=new Regex(mailDeseni);
    Match str=benimRegex.Match(kaynak);
    // Oluşturduğumuz deseni sitenin kaynak kodunda karşılaştırıyoruz :
    MatchCollection mailCol=benimRegex.Matches(kaynak);
    string[] mail=new string[mailCol.Count];
    // Bulunan her e-mail adresini mail[] dizisine atıyoruz :
    foreach(Match mailMatch in mailCol)
    {
        mail[i]=mailMatch.Groups[“mail”].ToString();
        i++;
    }
    return mail;
}

Şimdi Yakala butonuna basılınca icra edilecek olay kodunu yazalım :

// Şimdi e-mail yakalamak için bu yazdığımız metodları button_Click olayı ile birleştirelim :
private void btnYakala_Click(object sender, System.EventArgs e)
{
    lblStat.Text=””;
    if(txtAdres.Text==””)
    {
        MessageBox.Show(“Lütfen Bir Adres Girin !”);
    }
    else
    {
        // Sitenin Adresini alıyoruz :
        string adres=AdresiAl();
        // Sitenin Kaynak Kodunu alıyoruz :
        string kaynak=KaynakAl(adres);
        // E-Mail adreslerini alıyoruz :
        if(kaynak!=null)
        {
            string[] mail=MailAl(kaynak);
            lblStat.Text+=”İşlem sona erdi.” + mail.Length + ” tane mail adresi yakalandı.”;
            foreach(string yakalananMail in mail)
            {
                // Her e-mail adresi listbox’a giriliyor :
                lbxEmail.Items.Add(yakalananMail);
            }
        }
    }
}

Açıklama

Bazı sitelerde frameset kullanıldığından sayfada e-mail linki görülse bile programımız bunları döndürememekte. Bu sayfaların framelerinin linkleri verilerek e-mail adresleri elde edilebilir.
Yine bazı sitelerde linkler javascript kodu ile erişildiğinden bu adreslerde programımız tarafından erişilememektedir.

 

C# ile Taskbarda Çalışan Program Hazırlamak

Bu makalemde size NotifyIcon ve ContextMenu kullanarak bir taskbara yerleşen program nasıl yapılır, onu göstereceğim. Daha fazla uzatmadan hemen kodlarımızı yazmaya başlayalım.

İlk olarak Visual Studio’yu açalım ve yeni bir proje yaratalım. Bu projenin adına istediğiniz gibi bir isim verebilirsiniz. Projemiz “C# Windows Application” olmalıdır.

Projemizi yarattıktan sonra Add / New Item diyerek yeni bir Icon ekleyelim. Iconumuzun Build Action’ı mutlaka “Embedded Resource” olmalı. Daha sonra Form1’ın kod kısmına gecelim. 

Sınıfımızın içine

private NotifyIcon notifyicon;
private ContextMenu menu;

kodlarını ekleyelim. Formumuza iki kere tıklayalım ve aşağıdaki metotları kaynak kodumuza ekleyelim.

private void Form1_Load(object sender, System.EventArgs e)
{
    notifyicon = new NotifyIcon(); //Yeni bir NotifyIcon tanımladık

    notifyicon.Text = “NotifyIcon Ornegimiz”; //Mouse ile uzerine geldiğimizde olusacak yazı

    notifyicon.Visible = true; //Gorunur ozelligi

    notifyicon.Icon = new Icon(“Icon1.ico”); //Iconumuzu belirledik

    menu = new ContextMenu(); //Yeni bir ContextMenu tanımladık

    menu.MenuItems.Add(0, new MenuItem(“Goster”, new System.EventHandler(Goster_Click))); //Menuye eklemeler yapıyoruz.

    menu.MenuItems.Add(1, new MenuItem(“Gizle”, new System.EventHandler(Gizle_Click)));

    menu.MenuItems.Add(2, new MenuItem(“Kapat”, new System.EventHandler(Kapat_Click)));

    notifyicon.ContextMenu = menu; //Menumuzu notifyiconun menusu olarak tanımladık
}

protected void Goster_Click(object sender, System.EventArgs e)
{
   Show(); //Formumuzu normal ebatlara getirecek
}

protected void Gizle_Click(object sender, System.EventArgs e)
{
   Hide(); // Formumuzu minimize edecek
}

protected void Kapat_Click(object sender, System.EventArgs e)
{
   Close(); //Formumuzu kapatacak
}

Evet, şimdi programımızı çalıstırmaya hazırız. E o zaman çalıstıralım ve sonucu görelim. Gorduğunuz gibi programımız çalıştı. Programı kapatalım. O da ne! Iconumuz hala taskbarda duruyor. Peki bunu nasıl düzelteceğiz? Hemen cevap verelim. Kaynak kodumuzun biraz üstlerine bakıyoruz ve şu satırları goruyoruz:

protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components ! null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

Bu satırları aşağıdaki gibi değiştirdiğimizde progrm kapatıldığında taskbar daki icon da silinecektir.

protected override void Dispose( bool disposing )
{
if( disposing )
{
this.notifyicon.Dispose();;
components.Dispose();
}
base.Dispose( disposing );
}

Ve bir sorunumuz daha var. Programımızı açtığımız anda Form1 de gözuküyor. Peki Form1 gözükmeden sadece Iconumuzun gözükmesini nasıl sağlayacağız? Bunun da çozümü var. Biraz daha yukarılara bakıp

InitializeComponent();

satırından bir sonraki satıra su kodları koyuyoruz:

this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;

Bunları yaptıktan sonra yapmamız gerek bir değişiklik daha var. O da Goster_Click ve Gizle_Click’i su sekilde değiştirmek:

protected void Goster_Click(object sender, System.EventArgs e)
{
this.WindowState = FormWindowState.Normal; //Formumuzu normal ebatlara getircek
}

protected void Gizle_Click(object sender, System.EventArgs e)
{
this.WindowState = FormWindowState.Minimized; // Formumuzu minimize edecek
}

Ve şimdi hersey tamam. Programımız artık calısmaya hazır durumda. Hemen calıştırıp sonucu görebiliriz.

Umarım herkes için faydalı bir yazı olmustur. Benim için kod yazmak yazı yazmaktan daha kolay, bunu herkesin tatmasını isterim :)) Yeni yazılarda gorusmek dileğiyle hoşçakalın.

tuna

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir