Makale Özeti

Programlama dillerinin yetersiz kaldığı durumlarda Windows’un API adı verilen fonksiyonlarından yararlanılır. Bu fonksiyonlar bazı işlemlerin kısa yoldan yapılmasını ya da programımızı daha işlevsel hale getirebilmek için diğer programlardan yararlanma amaçlı ek görevleri sağlamaktadır.

Makale

API FONKSIYONLARI VE C#.NET ÖRNEKLERİ

 

Programlama dillerinin yetersiz kaldığı durumlarda Windows’un API adı verilen fonksiyonlarından yararlanılır. Bu fonksiyonlar bazı işlemlerin kısa yoldan yapılmasını ya da programımızı daha işlevsel hale getirebilmek için diğer programlardan yararlanma amaçlı ek görevleri sağlamaktadır.

 

API fonksiyonlarını C#.Net projelerinde kullanabilmek için System.Runtime.InteropServices isimli namespace’e ihtiyaç duyarız. Bundan dolayı API fonksiyonlarını kullanacağımız her projemizde, bu namespace’i using deyimi ile C#.Net projemize dahil etmemiz gerekmektedir. Bu işlem şöyle yapılmaktadır;

 

using System.Runtime.InteropServices;

 

C#.Net projeleri içerisinde Windows’a ait API fonksiyonlarını kullanmak için, kullanacağımız fonksiyonun DLL dosyasını DllImport attribute’i ile belirtmemiz gerekmektedir. Kullanılmak istenen Windows API fonksiyonunun tanımlandığı DLL dosyasını import ettikten sonra fonksiyonumuzu deklare etmemiz gerekmektedir.

 

Örneğin Windows ile gelen MessageBox fonksiyonunu değerlendirelim. Bu fonksiyon “users32.dll” adlı DLL dosyasında tanımlanmaktadır ve kullanıcılara mesaj verip onayını almaya yarar. Bir console application’da bu fonksiyonu nasıl kullanacağımızı görelim;

 

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

 

namespace API_Ornekleri

{

    class Program

    {

        [DllImport("user32")]

        public static extern int MessageBox(int hWnd, string IpText, string IpCaption, int UType);

        static void Main(string[] args)

        {

            MessageBox(0, "Dosya silinsin mi", "Silme Onayı", 35);

        }

    }

}

 

Programımızı çalıştırdığımızda bizden silme onayı isteyip ona göre işlem yaptığını göreceksiniz.

 

 

Burada 4.parametre olarak verdiğimiz 35 sayısı sayının (32+3) toplamından oluşmaktadır. 3 sayısı diyalog kutusuna Evet, Hayır ve İptal buttonlarının olmasını sağlar. 32 sayısı ise diyalog kutusuna soru işaretinin konulmasını sağlamaktadır.

 

Biz .Net Framework’ün MessageBox sınıfından yararlandığımız için bu fonksiyonun detaylarını anlatmaya gerek duymuyorum. Arzu edenler, Win32.hlp dosyasına bakarak Windows’un API fonksiyonları hakkında bilgi edinebilir. Ayrıca API fonksiyonlarının orijinallerinde bazen sayısal değer yerine akılda kolayca kalabilen sabitler kullanılmaktaydı. Bu sabitlerin tanımlı olduğu WIN32API.TXT dosyası Visual Studio’nun eski sürümleriyle birlikte veriliyordu. Bunlardan bazıları;

 

Public Const WM_SHOWWINDOW = &H18

Public Const WM_SETCURSOR = &H20

Public Const WM_MOVE = &H3

Public Const WM_KEYDOWN = &H100

Public Const WM_CLOSE = &H10

Public Const WM_CANCELMODE = &H1F

Public Const FO_DELETE = &H3

Public Const FO_RENAME = &H4

 

Örneklerle bazı API Fonksiyonları

 

Windows oturumu kapatmak ya da yeniden başlatmak: Bu tip bir istekte Windows’un ExitWindowsEx() fonksiyonundan yararlanılmaktadır. Bu fonksiyon, Windows ile gelen “user32.dll” adlı DLL dosyasında tanımlı bulunmaktadır. Hemen bir örnekle bu fonksiyonun nasıl kullanılabildiğini görelim. Bir Windows application açıyoruz ve formumuza bir button ekliyoruz. Önce DLL dosyasımızı import etmemiz gerekiyor;

[DllImport("user32.dll")]

        public static extern int ExitWindowsEx(

        int hFlags, int dwReserved);

 

Daha sonra buttonumuzun click olayına şunları yazıyoruz;

private void oturumkapat_Click_1(object sender, EventArgs e)

        {

            System.Windows.Forms.DialogResult Secim;

            Secim = MessageBox.Show("Oturum kapatılsın mı?", "Oturum kapatma", MessageBoxButtons.YesNoCancel);

            if (Secim == DialogResult.Yes)

            {

                //eger bu fonksiyona 2.parametre olarak 1 verilseydi pc kapanirdi

                //2.parametre olarak 2 kullanilirsa da pc yeniden baslardi

                int sonuc = ExitWindowsEx(0, 0);

            }

        }

 

Bu fonksiyon çalıştırılıp MessageBox sınıfının Show() metodu tarafından ekrana gelen diyalog kutusundaki Evet buttonu tıklanınca geriye “DialogResult.Yes” gönderilir ve ExitWindowsEx() fonksiyonu çalışarak oturum kapatılır. Bu API fonksiyonu geçerli Windows sürümü ve kullanıcının yetkilerinden etkilendiği için farklı tepkiler alabiliriz.

 

WAV uzantılı ses dosyalarını çalmak: Windows’un sndPlaySound() isimli API fonksiyonundan yararlanarak ses dosyalarını çalabiliriz. Hemen örneğimize geçelim. Yine bir Windows application açıyoruz ve bir button ile bir OpenFileDialog koyuyoruz. Önce DLL’imizi import ediyoruz;

[DllImport("winmm")]

        public static extern long sndPlaySound(string IpszSoundName, long uFlags);

 

Tıklama olayına şu kodları yazıyoruz;

        private void wavac_Click(object sender, EventArgs e)

        {

            long  sonuc;

            string dosya;

            openFileDialog1.ShowDialog();

            dosya = openFileDialog1.FileName;

            sonuc = mciExecute("Play " + dosya);

                   

        }

 

Birisi string diğeri long tipinde 2 parametreyi barındıran bu fonksiyon, geriye long tipinde bilgi döndürmektedir. Fonksiyonu çalıştırdığımızda ve buttonumuzu tıkladığımızda openfiledialog kutumuz açılacak ve istediğimiz wav uzantılı ses dosyasını açıp çalmamızı sağlayacak.

 

Video dosyalarını oynatmak: Windows’un yukarıda tanıdığımız sndPlaySound() fonksiyonu ile hem WAV dosyalı ses dosyalarını çalabiliyoruz hem de mciSendString() fonksiyonu ile video dosyalarını oynatabiliyoruz. Bir Windows application açıp 2 button ekliyoruz. Bunlardan biri ac isminde, ikincisi kapa isminde olacak. İlk önce DLL’imizi import ediyoruz.

 

[DllImport("winmm")]

        private static extern int mciSendString(string strCommand, StringBuilder strReturn, int iReturnLenght, IntPtr hwndCallback);

 

Şimdi ac isimli buttonumuzun click metoduna şu kodları yazıyoruz;

 

private void ac_Click(object sender, EventArgs e)

        {

            StringBuilder str = new StringBuilder(128);

            IntPtr ptr = IntPtr.Zero;

            string dosya;

            int sonuc;

            openFileDialog1.ShowDialog();

            dosya = openFileDialog1.FileName;

            sonuc = mciSendString("Open " + dosya + " Type AVIVideo Alias Video", str, 0, ptr);

            sonuc = mciSendString("Play Video", str, 0, ptr);

        }

 

Burada mciSendString() fonksiyonunun “Open” parametresi yoluyla önce AVI dosyası açılmaktadır. Sonra fonksiyonun “Play Video” parametresi ile ikinci kez çağrılarak AVI dosyası oynatılmaktadır. Video oynatıldıktan sonra pencereyi kapatmak için kapa isimli buttonun click metoduna şunları yazıyoruz;

 

   private void btnkapa_Click(object sender, EventArgs e)

        {

            StringBuilder str = new StringBuilder(128);

            IntPtr ptr = IntPtr.Zero;

            int sonuc;

            sonuc = mciSendString("Close Video", str, 0, ptr);

        }

 

Gördüğünüz gibi burada da “Close Video” parametresi kullanılarak oynatılan videonun penceresi kapatılıyor.

 

Ses sürücü veya donanımlarının olup olmadığını kontrol etmek: Aslında bu fonksiyonu en başta tanımlamam gerekiyordu ama şimdi tanıtmamda da bir zararı yok. Video yada ses dosyalarımızı çalmadan önce, bilgisayarımızın ses sürücülerinin yada ses donanımının olup olmadığını waveOutGetNumDevs() isimli API fonksiyonuyla öğrenebiliriz. Önce DLL’imizi import edelim sonra windows application’ımıza button ve openfiledialog ekleyelim.

 

[DllImport("winmm")]

        public static extern long waveOutGetNumDevs();

 

Şimdi buttonumuzun click olayına şu kodları yazalım;

 

private void btnses_Click(object sender, EventArgs e)

        {

            IntPtr ptr;

            ptr = IntPtr.Zero;

            long sonuc;

            sonuc = waveOutGetNumDevs();

            if (sonuc == 0)

                MessageBox.Show("Ses dosyalarını çalacak donanım bulunmamaktadır");

            else

            {

                openFileDialog1.ShowDialog();

                sonuc = sndPlaySound(openFileDialog1.FileName, ptr);

            }

        }

 

Bu fonksiyon dışarıdan herhangi bir bilgi almaktadır. Geriye sadece yapılan araştırmanın sonucu ile ilgili bilgi göndermektedir. Bilgisayarda ses aygıyı yoksa 0 değeri gönderir.

 

C#.Net projelerinde başka programları çalıştırmak: Projelerimizde diğer programlardan da destek alabilmek için Windows’un  WinExec() fonksiyonundan yararlanabiliriz. Bu fonksiyon 2 parametreye sahiptir. İlk parametrede çalıştırılacak program dosyasının adı verilmektedir, ikinci parametrede ise programa ait pencerenin ilk şekli belirtilmektedir. Örneğin bir notepad dosyasını çalıştıralım. İlk bir windows projesi açalım ve forma bir button ekleyelim. Önce DLL dosyamızı import ediyoruz;

 

[DllImport("kernel32")]

        private static extern long WinExec(string IpCmdLine, int nCmdShow);

 

Daha sonra buttonumuzun click olayına şu kodları yazıyoruz;

 

private void btnnotepad_Click(object sender, EventArgs e)

        {

            long sonuc;

            sonuc = WinExec("C:\\Windows\\System32\\Notepad.exe", 9);

        }

 

Bu fonksiyonda çalıştırılmak istenen program dosyası bulunamazsa, geriye 2 değeri döner. Belirtilen sürücü veya klasör bulunamazsa fonksiyon geriye 3 değeri döndürür. Belirtilen programı çalıştırmak için yeterli bellek yoksa geriye 8 değeri döndürür. Bizim yazdığımız 9 değeri, pencerenin orijinal boyutlarında açılmasını sağlamaktadır. Bu değer 6 olsaydı, program simge durumuna küçültülüp açılırdı.

 

Herhangi bir dosyayı ilgili programla açmak: İstediğimiz bir dosyayı (word, excel, powerpoint, photoshop, autocad vb.) ilgili programla açmak veya print etmek istiyorsak ShellExecute() fonksiyonunu kullanırız. “shell32.dll” dosyasında tanımlı olan bu fonksiyon hakkında bir örnek verelim. Önce windows projemizi açıyoruz bir button ekliyoruz. İlk kod olarak dll’imizi import ediyoruz;

 

[DllImport("shell32.dll")]

        public static extern int ShellExecute(int hWnd, string IpOperation, string IpFile, string IpParameters, string IpDirectory, int snShowCmd);

 

Şimdi buttonumuzun click olayına şu kodları yazıyoruz;

 

private void btnie_Click(object sender, EventArgs e)

        {

            ShellExecute(0, "Open", "http://www.microsoft.com", "", "", 1);

        }

 

ShellExecute() fonksiyonu 6 parametreye sahiptir. 1. parametrede handle numarası, 2. parametrede yapılacak işlem ve 3. parametrede seçilen işlemin uygulanacağı dosya olmaktadır. Yukarıda 0 diyerek bilgisayarımızda kullandığımız default web browser’ı seçmiş oluruz. Örneğin şu şekilde geçerli e-mail programımızı çalıştırıp (genelde outlook olur) e-mail gönderebiliriz;

 

private void btnout_Click(object sender, EventArgs e)

        {

            ShellExecute(0, "Open", "mailto:yagizgonuler@gmail.com", "", "", 1);

        }

 

Gördüğünüz gibi burada da default mail programımızı çalıştırıp mail yolayabiliriz.

 

WinExec() ve ShellExecute() yerine Shell() fonksiyonunu kullanmak:  C#.Net projelerimizde bu fonksiyonları kullanmak yerine Visual Basic’in Shell() fonksiyonu nu da kullanabiliriz. Bu durumda dll import etmemiz gerekmiyor, solution explorer penceresinden add reference diyerek Microsoft.Visual Basic isimli reference’ı projemize eklememiz gerekiyor. Bu işlemden sonra windows projemize bir button koyup click olayına şu kodları yazalım;

 

       private void btnshellnotepad_Click(object sender, EventArgs e)

        {

            Microsoft.VisualBasic.Interaction.Shell("C:\\Windows\\Notepad.exe", Microsoft.VisualBasic.AppWinStyle.NormalFocus, true, -1);

        }

 

1.Parametrede belirtilen değer, programın yoludur. Biz burada sadece programı normal pencere boyutlarında açarız. Ancak istersek programla beraber bir dosyayı da açabiliriz. Bu durumda buttonumuzun click olayına şu kodları yazmamız gerekir;

 

private void btnshellfile_Click(object sender, EventArgs e)

        {

            Microsoft.VisualBasic.Interaction.Shell("C:\\Windows\\Notepad.exe C:\\test.txt", Microsoft.VisualBasic.AppWinStyle.NormalFocus, true, -1);

        }

 

Böylece notepad dosyamızı çalıştırırken, C’nin içerisindeki test.txt isimli dosya açılır. NormalFocus koduyla programın penceresi normal konumda ve normal boyutta ekrana gelir. Eğer bunun küçültülmesini isteseydik AppWinStyle.MinimizedFocus kodunu yazardık. Ekranı kaplamasını isteseydik AppWinStyle.MaximizedFocus,  programın aktif pencere olmasını istemeseydik AppWinStyle.NormalNoFocus veya MinimizedNoFocus seçeneklerini 2.parametre olarak yazabilirdik.

 

Belgeler klasörüne kısayol eklemek: Windows XP’de son kullandığımız belgelerin kısayolunu başlat menüsüne ekleyen “en son kullandıklarım” adlı bir bölüm vardır. Bu bölüme Windows’un SHAddToRecentDocus fonksiyonundan yararlanarak belge adı veya komut ekleyebiliriz. Önce dll’imizi import edelim;

 

[DllImport("shell32")]

        public static extern int SHAddToRecentDocs(int uFlags, string pv);

 

Şimdi windows projemize bir button ekleyelim ve click olayına şunları yazalım;

 

        private void btnekle_Click(object sender, EventArgs e)

        {

            int sonuc;

            sonuc = SHAddToRecentDocs(2, "C:\\cekys.dwg");

        }

 

Burada C’nin içerisindeki cekys.dwg isimli autocad dosyasını, başlat menüsündeki “en son kullandıklarım” isimli bölüme kısayol olarak eklemiş oldum.

 

Bilgisayarın açık kaldığı süreyi öğrenmek: Windows’un GetTickCount() isimli fonksiyonundan yararlanarak ne kadar zamandır açık bulunduğunu öğrenebiliriz.

Önce bir windows projesi açalım ve dll’imizi import edelim;

 

[DllImport("kernel32.dll")]

        public static extern long GetTickCount();

 

Şimdi ise projemize bir textbox ekliyip formun load olayına şu kodları yazalım;

 

        private void Form1_Load(object sender, EventArgs e)

        {

            long gecen_sure;

            gecen_sure = GetTickCount() / 1000;

            textBox1.Text = gecen_sure.ToString();

        }

 

Burada textboxımıza bilgisayarımızın açık kaldığı süreyi saniye cinsinden yazdırıyoruz. Dilersek bunu gün, saat, dakika şeklinde de ifade edebiliriz.

 

Bilgisayarın adını öğrenmek: Kullandığımız bilgisayarın adını C#.Net projemizin dahilinde öğrenmek istediğimiz zaman Windows’un GetComputerName() fonksiyonundan yararlanabiliriz. Not olarak ekliyim; Windows’un “Sistem Özellikleri” diyalog kutusundan, bilgisayarımızın adını değiştirebiliriz. Şimdi bir windows projesi açalım ve gerekli olan dll’imizi import edelim;

 

[DllImport("kernel32.dll")]

        public static extern int GetComputerName(StringBuilder IpBuffer, ref int nSize);

 

Şimdi ise bir button ve bir textbox ekleyip click olayına şu kodları yazalım;

 

        private void pcname_Click_1(object sender, EventArgs e)

        {

            StringBuilder str = new StringBuilder(128);

            int sonuc, sayi;

            sayi = str.Capacity;

            sonuc = GetComputerName(str, ref sayi);

            textBox1.Text = str.ToString();

        }

 

Fonksiyonumuz birisi stringbuilder diğeri int tipinde 2 parametreye sahiptir ve geriye yine int tipinde bilgi göndermektedir. Kullanılan bilgisayarın bir adı olmasaydı, fonksiyon geriye 0 değeri döndürürdü.

 

Duvar kağıdını değiştirmek: Windows’un SystemParametersInfo() isimli fonksiyonunu kullanarak duvar kağıdımızı değiştirebiliriz. Bu fonksiyonun farklı parametrelere sahip çok sayıda overlay versiyonu bulunmaktadır. Eğer biz sadece duvar kağıdını değiştiriceksek aşağıdaki gibi 4 parametreye sahip dll’imizi import etmeliyiz;

 

[DllImport("user32.dll")]

        public static extern int SystemParametersInfo(int uAction, int uParam, string IpvParam, int fuWinIni);

 

Çok değişik amaçlarla kullanılan bu fonksiyonda sayısal değerler çok olduğundan akılda kalması kolay olan sabitler tanımlanıp kullanılması daha işlevsel olur. Bu yüzden fonksiyonu deklara ettikten sonra ayrıca da 2 sabit tanımladım;

 

public const int SPI_SETDESKWALLPAPER = 20;

public const int SPIT_UPDATEINIFILE = 0x1;

 

Windows projemizin formuna bir button ve bir openfiledialog kutusu nesnesi yerleştirip, buttonumuzun click olayına şunları yazalım;

 

private void btnwall_Click(object sender, EventArgs e)

        {

            string dosya;

            openFileDialog1.ShowDialog();

            dosya = openFileDialog1.FileName;

            int sonuc = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, dosya, SPIT_UPDATEINIFILE);

        }

 

CD sürücüsünü açmak: Gelelim en son API fonksiyonumuza. Programlamayla ilk haşır neşir olduğum zamanlarda, cd sürücüsünün kod yoluyla nasıl açıldığı en merak ettiğim işlemlerden biriydi. Sanki çok lüzumlu bir iş, buttona tıklamaktansa sürücü düğmesine tıklar açarım en azından vücud biraz hareket edip yağ deposu haline gelmez J Bu fonksiyon mciSendString() ile işlenir ve “winmm.dll” dosyasında tanımlıdır. C#.Net’e uyarlanmış hali için önce bir windows projesi açıp dll import işlemlerini gerçekleştiriyoruz;

 

[DllImport("winmm")]

        private static extern int mciSendString(string strCommand, StringBuilder strReturn, int iReturnLenght, IntPtr hwndCallback);

 

Daha sonra formumuza bir button ekleyelim ve click olayına şu kodları yazalım;

 

       private void button15_Click(object sender, EventArgs e)

        {

            IntPtr ptr;

            ptr = IntPtr.Zero;

            mciSendString("Set cdaudio door open", null, 0, ptr);

        }

 

 

Böylelikle API fonksiyonlarının işleyişini görmüş olduk ve birkaç örnekle pekiştirdik. En başlarda da dediğim gibi bu fonksiyonlar oldukça fazladır ancak çok işlevseldir. Arama motorlarından hertürlü bilgiyi bulmanız mümkün J Umarım faydalı bir makale olmuştur. Farklı makalelerde tekrar görüşmek üzere, iyi çalışmalar dilerim.

 

 

Yağız GÖNÜLER

yagizgonuler@gmail.com

 

 

Kaynaklar:

Wikipedia, MSDN

Visual C# for .Net Framework 2.0 – Memik Yanık