Tuşa basıldığında, Windows işletim sistemine bir "tarama kodu" bildiren bir donanım olayı oluşturulur. Bu tarama kod sonra (Caps da beklemede olan ölü anahtar devlet, Shift/Alt/Ctrl keystate Kilit ve diğer klavye devlet faktörleri ile birlikte tarama koduna göre bir "sanal anahtar kodu" dönüştürülür vuruş). Dönüştürülen VK değeri, KeyDown
olayı tarafından bildirilen değerdir.
Tarama kodundan VK koduna dönüştürme, geçerli giriş yerel ayarına bağlıdır - basitçe, giriş yerel ayarı tarama kodları ile sanal anahtar kodları arasındaki bir eşlemeyi tanımlar. Klavye girişinin tam açıklaması için the MSDN documentation'a bakın.
Bu arama işlemini tersine çevirerek, her sanal anahtar koduna karşılık gelen tarama kodunu belirlemek mümkündür (elbette, aynı tarama kodu, shift/ctrl/alt durumu vb. Nedeniyle birden çok VK koduna eşlenecektir). Win32 API, MAPVK_VK_TO_VSC_EX
seçeneğini kullanarak bu eşleştirmeyi gerçekleştirmek için MapVirtualKeyEx
işlevini sağlar. Hangi tarama kodunun belirli VK kodunu oluşturduğunu belirlemek için bunu kullanabilirsiniz.
Ne yazık ki, programatik olarak gidebildiğiniz kadarıyla - klavyenin fiziksel düzenini veya her tarama kodu için anahtarın yerini belirlemenin bir yolu yoktur. Bununla birlikte, çoğu fiziksel klavyeyle aynı şekilde bağlanır, bu nedenle (örneğin) üst sol tuşun çoğu fiziksel klavye tasarımlarında aynı tarama koduna sahip olacaktır. Temel fiziksel klavye düzenine (101-tuş, 102-anahtar vb.) Bağlı olarak, bir tarama koduna karşılık gelen fiziksel konumu bulmak için bu varsayılan sözleşmeyi kullanabilirsiniz. Garanti edilmiyor, ama oldukça güvenli bir tahmin.
Aşağıdaki kod, yazdığım daha büyük bir klavye kullanım kitaplığından (açık kaynak oluşturmayı planlıyorum ama zamanım olmadı) bir alıntıdır. Yöntem, belirli bir giriş yerel ayarı için VK koduyla indekslenen (this._inputLanguage
içinde saklanan ve System.Windows.Forms.InputLanguage
olarak bildirilen bir dizi (this._virtualKeyScanCodes
) diziyi başlatır. Örneğin, this._virtualKeyScanCodes[VK_NUMPAD0]
inceleyerek VK koduna karşılık gelen tarama kodunu belirlemek için diziyi kullanabilirsiniz. - Tarama kodu sıfır ise, bu VK mevcut giriş yerel ayarında klavyede mevcut değildir, sıfır değilse, fiziksel anahtarı çıkarabileceğiniz tarama kodudur.
Ne yazık ki, ölü tuşların alemine girdiğinizde (örneğin, aksanlı karakterler oluşturan çoklu tuş kombinasyonları), konular bundan biraz daha karmaşıktır. Şu ana kadar çok karmaşık bir durum var ama Michael S. Kaplan, daha fazla araştırmak isterseniz blog posts numaralı seriyi yazdı. İyi şanslar!
private void Initialize()
{
this._virtualKeyScanCodes = new uint[MaxVirtualKeys];
// Scroll through the Scan Code (SC) values and get the Virtual Key (VK)
// values in it. Then, store the SC in each valid VK so it can act as both a
// flag that the VK is valid, and it can store the SC value.
for (uint scanCode = 0x01; scanCode <= 0xff; scanCode++)
{
uint virtualKeyCode = NativeMethods.MapVirtualKeyEx(
scanCode,
NativeMethods.MAPVK_VSC_TO_VK,
this._inputLanguage.Handle);
if (virtualKeyCode != 0)
{
this._virtualKeyScanCodes[virtualKeyCode] = scanCode;
}
}
// Add the special keys that do not get added from the code above
for (KeysEx ke = KeysEx.VK_NUMPAD0; ke <= KeysEx.VK_NUMPAD9; ke++)
{
this._virtualKeyScanCodes[(uint)ke] = NativeMethods.MapVirtualKeyEx(
(uint)ke,
NativeMethods.MAPVK_VK_TO_VSC,
this._inputLanguage.Handle);
}
this._virtualKeyScanCodes[(uint)KeysEx.VK_DECIMAL] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_DECIMAL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_DIVIDE] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_DIVIDE, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_CANCEL] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_CANCEL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_LSHIFT] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_LSHIFT, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_RSHIFT] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_RSHIFT, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_LCONTROL] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_LCONTROL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_RCONTROL] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_RCONTROL, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_LMENU] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_LMENU, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_RMENU] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_RMENU, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_LWIN] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_LWIN, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_RWIN] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_RWIN, NativeMethods.MAPVK_VK_TO_VSC, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_PAUSE] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_PAUSE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_UP] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_VOLUME_UP, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_DOWN] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_VOLUME_DOWN, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_VOLUME_MUTE] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_VOLUME_MUTE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_NEXT_TRACK] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_MEDIA_NEXT_TRACK, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_PREV_TRACK] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_MEDIA_PREV_TRACK, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_PLAY_PAUSE] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_MEDIA_PLAY_PAUSE, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
this._virtualKeyScanCodes[(uint)KeysEx.VK_MEDIA_STOP] =
NativeMethods.MapVirtualKeyEx(
(uint)KeysEx.VK_MEDIA_STOP, NativeMethods.MAPVK_VK_TO_VSC_EX, this._inputLanguage.Handle);
this._stateController = new KeyboardStateController();
this._baseVirtualKeyTable = new VirtualKeyTable(this);
}
Düzenleme: Ayrıca sizinkine benzer this question bakın.
Birisinin yazabileceği güzel bir eklenti gibi görünüyor;) – Oded
Uluslararası klavye düzenlerinin resimlerini yalnızca Google Görseller'i kullanarak bulabilirsiniz. Örneğin, [Fransızca klavye düzeni] (http://www.google.com/images?hl=tr&q=french+keyboard+layout) için googling yapmayı deneyin. – Timwi
Evet ama önceden belirlenmiş bir stil ile sıfırdan çizmem gerekiyor. Ayrıca mizanpaj kullanırsam, tüm görüntüleri saklamak zorundayım, değil mi? Bunu çalışma zamanında dinamik olarak yapmalıyım (özelleştirme iletişim kutusu başlatıldığında). –