Yeni Blog Sayfam

Sonunda kendi adıma ait .net uzantılı alan adını satın almayı başardım :) .
Bundan sonra yazılarıma http://oguzkoroglu.net adresinden devam edeceğim.

public class CursorCreator

 

Bir Yazılım Sexi Olmalıdır.

“.NET Framework çok iyidir, nimetleri boldur” diyoruz ama geçen gün başıma gelen bir problem bana böyle bir class ‘ı yaratmam ve paylaşmam gerektiğini farkettirdi. ODTÜ mezunu ve sonra da hollanda da yüksek lisans yapmış bir arkadaş firmaya geldi ve bize arayüz tasarımı nasıl olmalı ve süreçleri nelerdir yani “better user experience” olayını anlattı. Son zamanlarda Multitouch Software geliştirme nedeniyle WPF ile feci şekilde de kafayı bozduğumdan ve WPF ile yatıp kalktığımdan, artık gözümde bir yazılımın veri modeli, algoritması, mimarisi ve işlevselliği kadar kullanılabilirliği ve çekiciliğide benim için önem kazandı. “Yazılım seksi olmalıdır.”, temel mantığıma artık bu da eklendi.

Örnek Olay:

Karşıma bir olay çıktı, bir kare alan (rectangle) mouse ile tutulup bir resim üzerinde taşınacak (move işlevi). Bütün işlevi başarılı bir şekilde kodladıktan sonra dedim ki kullanıcı taşıma yapacağı zaman bir el mouse cursor ‘ı olsun, sonrada sol tuş ile tıklanınca o karenin üzerinde el kapansın (avuçlama :) ) sonra taşıyıp bırakınca da el açılsın oraya rectangle nesneyi bıraksın. Grafikerimden bir adet açık el, bir adet de kapalı el .png dosyası yaratmasını isteyecektim, baktım çok işi var :) bende www.iconlet.com dan bir açık bir de kapalı el .png dosyası arakladım (çaresizliğin gözü kör olsun :)). Aklım sıra çok hoş bir drag & drop user experience ‘i yaratacam.

Yanlız .NET Framework içinde bulunan System.Windows.Forms.Cursor class ‘ının constructorunun overloadlarından biri sadece .cur dosyalarından cursor yaratabiliyordu. Bendeki .png leride nasıl .cur dosyasına çeviririm diye düşündüm. Grafikerime baktım, çooook işi var hiç umut yok :) . O zaman kendime “Oğuz, iş başa kaldı, öyle bir class yazki artık Cursor’ lar png, bmp, gif ve jpg dosyalarından da meydana gelebilsin.” dedim. Aklıma emektar user32.dll geldi, hemen onun içindeki iki adet unmanaged metodu kullanayım dedim.

        /// <summary>
        /// bir ikonun info bilgilerini çağıran
        /// user32.dll içinde bulunan UnManaged bir C/C++ fonksiyounu
        /// </summary>
        /// <param name="hIcon">Girdi olarak icon</param>
        /// <param name="pIconInfo">Çıktı olarak icon bilgileri</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
        /// <summary>
        /// Icon oluşturma fonksiyonu
        /// user32.dll içinde bulunan UnManaged bir C/C++ fonksiyounu
        /// </summary>
        /// <param name="icon"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern IntPtr CreateIconIndirect(ref IconInfo icon);

yanlız burada dikkat edilmesi gereken bir durum var CreateIconIndirect metodu içinde IconInfo diye bir struct var onun veri yapısını bilmek lazım ve programa tanıtmak lazım.

/// <summary>
        /// icon bilgileri için özel veri yapısı
        /// </summary>
        public struct IconInfo
        {
            public bool fIcon;
            /// <summary>
            /// Tıkladığı noktanın X Koordinatı
            /// </summary>
            public int xHotspot;
            /// <summary>
            /// Tıkladığı boktanın Y Koordinatı
            /// </summary>
            public int yHotspot;
            /// <summary>
            /// Icon Maskesi
            /// </summary>
            public IntPtr hbmMask;
            /// <summary>
            /// Icon Rengi
            /// </summary>
            public IntPtr hbmColor;
        }

Şimdi sırada bir Bitmap nesnesinden bir cursor yaratmaya.

/// <summary>
        /// Bir bitmap ten bir cursor yaratır.
        /// </summary>
        /// <param name="bmp">Cursor olacak olan bitmap resmi</param>
        /// <param name="xHotSpot">Tıkladığı noktanın X Koordinatı</param>
        /// <param name="yHotSpot">Tıkladığı boktanın Y Koordinatı</param>
        /// <returns>Cursor olarak döner</returns>
        public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot)
        {
            IntPtr ptr = bmp.GetHicon();
            IconInfo tmp = new IconInfo();
            GetIconInfo(ptr, ref tmp);
            tmp.xHotspot = xHotSpot;
            tmp.yHotspot = yHotSpot;
            tmp.fIcon = false;
            ptr = CreateIconIndirect(ref tmp);
            return new Cursor(ptr);

        }
        /// <summary>
        /// Bit bitmap dosya yolundan cursor yaratır.
        /// </summary>
        /// <param name="BitmapPath">Cursor olacak olan bitmap resmi dosya yolu</param>
        /// <param name="xHotSpot">Tıkladığı noktanın X Koordinatı</param>
        /// <param name="yHotSpot">Tıkladığı boktanın Y Koordinatı</param>
        /// <returns>Cursor olarak döner</returns>
        public static Cursor CreateCursor(string BitmapPath, int xHotSpot, int yHotSpot)
        {
            Bitmap bmp= new Bitmap(BitmapPath);
            return CreateCursor(bmp, xHotSpot, yHotSpot);
        }

Evet, böylece bu iki kez overload edilmiş metodun yanıtını mouse.cursor nesnemize atadığımızda o resim kaynak dosyamızı bir mouse cursor ‘ı halinde kullanabiliriz.

Kullandım, programı bitirdim ve öğleden sonra programı kullanacak olan kitlenin departman şefi gelip kullandığında user experience olayına önem vermenin ne kadar gerekli olduğunu onun yüzündeki gülümsemeden anladım.

Örneğin Tüm Kodları:

    /// <summary>
    /// Yeni bir mouse cursoru yaratmak için metodlar içeren bir class
    /// </summary>
    public class CursorCreator
    {
        /// <summary>
        /// bir ikonun info bilgilerini çağıran
        /// user32.dll içinde bulunan UnManaged bir C/C++ fonksiyounu
        /// </summary>
        /// <param name="hIcon">Girdi olarak icon</param>
        /// <param name="pIconInfo">Çıktı olarak icon bilgileri</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
        /// <summary>
        /// Icon oluşturma fonksiyonu
        /// user32.dll içinde bulunan UnManaged bir C/C++ fonksiyounu
        /// </summary>
        /// <param name="icon"></param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern IntPtr CreateIconIndirect(ref IconInfo icon);

        /// <summary>
        /// icon bilgileri için özel veri yapısı
        /// </summary>
        public struct IconInfo
        {
            public bool fIcon;
            /// <summary>
            /// Tıkladığı noktanın X Koordinatı
            /// </summary>
            public int xHotspot;
            /// <summary>
            /// Tıkladığı boktanın Y Koordinatı
            /// </summary>
            public int yHotspot;
            /// <summary>
            /// Icon Maskesi
            /// </summary>
            public IntPtr hbmMask;
            /// <summary>
            /// Icon Rengi
            /// </summary>
            public IntPtr hbmColor;
        }
        /// <summary>
        /// Bir bitmap ten bir cursor yaratır.
        /// </summary>
        /// <param name="bmp">Cursor olacak olan bitmap resmi</param>
        /// <param name="xHotSpot">Tıkladığı noktanın X Koordinatı</param>
        /// <param name="yHotSpot">Tıkladığı boktanın Y Koordinatı</param>
        /// <returns>Cursor olarak döner</returns>
        public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot)
        {
            IntPtr ptr = bmp.GetHicon();
            IconInfo tmp = new IconInfo();
            GetIconInfo(ptr, ref tmp);
            tmp.xHotspot = xHotSpot;
            tmp.yHotspot = yHotSpot;
            tmp.fIcon = false;
            ptr = CreateIconIndirect(ref tmp);
            return new Cursor(ptr);

        }
        /// <summary>
        /// Bit bitmap dosya yolundan cursor yaratır.
        /// </summary>
        /// <param name="BitmapPath">Cursor olacak olan bitmap resmi dosya yolu</param>
        /// <param name="xHotSpot">Tıkladığı noktanın X Koordinatı</param>
        /// <param name="yHotSpot">Tıkladığı boktanın Y Koordinatı</param>
        /// <returns>Cursor olarak döner</returns>
        public static Cursor CreateCursor(string BitmapPath, int xHotSpot, int yHotSpot)
        {
            Bitmap bmp= new Bitmap(BitmapPath);
            return CreateCursor(bmp, xHotSpot, yHotSpot);
        }
    }

Yazılımda Matematik : Basamaklara Ayırma

Yazılımda matematik önemlidir. Günümüzde temel matematik bilgileri ile de yazılım geliştirmek mümkündür, yanlız matematiği zayıf birinin yazılım geliştirme ekibinde yer alması ilerde o projenin kötü şekilde ilerlemesine sebep olacaktır. Daha sonra bu tarz projeleri matematiği iyi olan kişiler bile biraz zor kurtarır. Aslında matematik her konuda önemlidir, her meslek grubundan kişinin matematiği iyi olmalıdır, yoksa mesleğini doğru bir biçimde icraa edemiyor demektir. Çok iyi tanıdığım ve sevdiğim bir grafiker arkadaşımın, grafiker olmasına ve hayatı photoshop içinde geçmesine rağmen matematiği çok iyidir, mümkün olduğunca matematiği kullanır ve yaptığı işleri matematiğe dayandırarak yapar. Ama konu algoritma geliştirmek ise matematik çok çok daha iyi olmak zorundadır.

Kendimize bir soru soralım (manyağız çünkü :) ):

1′ den 1.000.000.000′a kadar kaç adet sayının rakkamları toplamı 20′dir?

ÖSS’de değiliz, bana bir formül verin demeyin. Biz bunu kafadan yapamayız bence, bırakalım bilgisayar çözsün bunu. Önce bunun için bir int primitive türünden sayının basamak değerlerinin toplamını bulan metodu yazalım, OOP standartlarına sadık kalalım.

        /// <summary>
        /// Bir Sayının Rakkamları Toplamı
        /// </summary>
        /// <param name="sayi">Rakkamları Toplanacak Olan Sayı</param>
        /// <returns></returns>
        private static int RakkamlariToplami(int sayi)
        {
            int m=sayi;
            int b = 0;
            while (m>0)
            {
                b += m % 10;
                m /= 10;
            }
            return b;
        }

Bu yukarıdaki metod aslında işimizi görmeye yeter. Yanlız çok değerli bir yazılımcı olan kardeşim Yavuz Köroğlu olaya daha derinlemesine ve ileride hem C# hemde java dillerinde kullanılabilecek aşağıdaki gibi bir metodlar silsilesi geliştirmiştir.

Öncelikle sayı tüm basamaklarına ayıran ve int[] döndüren bir metod yazılır.

public static int[] splitDigits(int number) {
	// This method splits all of the digits of a number
		int[] digits = new int[countDigits(number)];

		for(int i=0; i < digits.length; i++) {
			digits[digits.length - i - 1] = number % 10;
			number = (number - digits[digits.length - i - 1]) / 10;
		}

		return digits;
	}

Daha sonra bu metodun cevabı aşağıda bulunan metoda input olarak gönderilerek basamakları toplamı elde edilmiş olur.

public static int calcSumOf(int[] array) {
	// Returns the sum of the numbers in an integer array
		int sum = 0;

		for(int i=0; i < array.length; i++)
			sum += array[i];

		return sum;
	}

İşte burada kardeşimin yazdığı ikinci metodunda bize gösterdiği şey java platformunun .NET Framework platformu karşısında biraz aciz olduğudur. Çünkü .NET Framework ile bir int[] array nesnesinin elemanları toplamını extension metodlardan biri olan int Enumarable<int>.Sum() metodunu [Array'imin adı].Sum(); şeklinde kullanarak bulabilirdik. Ama javada görüldüğü gibi böyle metodlar bulunmamaktadır.

Sorumuza dönecek olursak sıra geldi, metodumuzu kullanarak 1′ den 1.000.000.000′a kadar sayılar arasındaki basamakları toplamı 20 olan sayıları bulalım.

        public static int Soru1
        {
            get
            {
                int retVal=0;
                for (int i=0; i<1000000000; i++)
                {
                    retVal += Convert.ToInt32((RakkamlariToplami(i) == 20));
                }
                return retVal;
            }
        }

Bundan sonra haftada en az bir adet olmak üzere bu tarz matematiksel problemler ile ilgili yazı yazacağım. Çünkü matematiği unutursak, programlamada ve algoritma geliştirmede zayıf düşeriz.

Takip Et

Get every new post delivered to your Inbox.