2009-03-19 18 views
8

Tamam, bu biraz garip bir soru.Klavye düzenlerini ayıklar penceresinden ayıkla

Biz dokunmatik ekranlı uygulama (yani hiçbir klavyesi) var. Kullanıcıların metin girmesi gerektiğinde, uygulama sanal klavyeyi gösterir - WinForms'ta el yapımı.

Her yeni dil için bunları el ile yapmak, maymun işi. Pencerelerin, bazı dll'de bir yerde saklanan bu klavye düzeni bilgilerine sahip olması gerektiğini düşünüyorum. Bu bilgiyi pencerelerden çıkarmak için yine de var mıdır?

Diğer fikirler (en az VS elle yapıyor daha iyi olmak zorunda olan bir xml dosyasından şeyi üreten rakam) bekliyoruz.

bu konuda oldukça iyi serisi:

GÜNCELLEME (Not Bir Japon klavye, durum makinesi var olduğuna dikkat hangi tüm ve tüm ... Böylece XML yeterli olmayabilir söyledikten) here

+2

Bu gerçekten harika bir soru ... Düzenleri diğer ortamlara (Linux) aktarmak da mümkün olabilir, ancak bu belki de bir telif hakkı ihlali anlamına gelebilir. – unwind

+0

Yerleşik windows tablet klavyesini kullanmak daha kolay olmaz mıydı? (Açıkçası, işletim sisteminde yüklü olan doğru uzantılara ihtiyaç var ama bu günlerde bir wacom'u takmak yeterli görünüyor, bu yüzden daha fazla yol olabilir mi?). –

cevap

6

Microsoft Keyboard Layout Creator sistem klavyeleri yük ve .klc files olarak dışa aktarabilirsiniz. NET'te yazıldığından beri, bunu nasıl yaptığını görmek için Reflector'u kullanabilir ve sürücüyü kullanmak için yansımayı kullanabilirsiniz. İşte aşağıdaki C# kodu kullanılarak oluşturulmuş bir zip file of .klc files for the 187 keyboards in Windows 8. Başlangıçta Windows XP için yazdım ve şimdi Windows 8 ve ekrandaki klavye ile, gerçekten yavaş ve görev çubuğunu çökmesine görünüyor Not: Temelde çalışma :)

using System; 
using System.Collections; 
using System.IO; 
using System.Reflection; 

class KeyboardExtractor { 

    static Object InvokeNonPublicStaticMethod(Type t, String name, 
      Object[] args) 
    { 
     return t.GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic) 
      .Invoke(null, args); 
    } 

    static void InvokeNonPublicInstanceMethod(Object o, String name, 
      Object[] args) 
    { 
     o.GetType().GetMethod(name, BindingFlags.Instance | 
       BindingFlags.NonPublic) .Invoke(o, args); 
    } 

    static Object GetNonPublicProperty(Object o, String propertyName) { 
     return o.GetType().GetField(propertyName, 
       BindingFlags.Instance | BindingFlags.NonPublic) 
      .GetValue(o); 
    } 

    static void SetNonPublicField(Object o, String propertyName, Object v) { 
     o.GetType().GetField(propertyName, 
       BindingFlags.Instance | BindingFlags.NonPublic) 
      .SetValue(o, v); 
    } 

    [STAThread] public static void Main() { 
     System.Console.WriteLine("Keyboard Extractor..."); 

     KeyboardExtractor ke = new KeyboardExtractor(); 
     ke.extractAll(); 

     System.Console.WriteLine("Done."); 
    } 

    Assembly msklcAssembly; 
    Type utilitiesType; 
    Type keyboardType; 
    String baseDirectory; 

    public KeyboardExtractor() { 
     msklcAssembly = Assembly.LoadFile("C:\\Program Files\\Microsoft Keyboard Layout Creator 1.4\\MSKLC.exe"); 
     utilitiesType = msklcAssembly.GetType("Microsoft.Globalization.Tools.KeyboardLayoutCreator.Utilities"); 
     keyboardType = msklcAssembly.GetType("Microsoft.Globalization.Tools.KeyboardLayoutCreator.Keyboard"); 

     baseDirectory = Directory.GetCurrentDirectory(); 
    } 

    public void extractAll() { 

     DateTime startTime = DateTime.UtcNow; 

     SortedList keyboards = (SortedList)InvokeNonPublicStaticMethod(
       utilitiesType, "KeyboardsOnMachine", new Object[] {false}); 

     DateTime loopStartTime = DateTime.UtcNow; 

     int i = 0; 
     foreach (DictionaryEntry e in keyboards) { 
      i += 1; 
      Object k = e.Value; 

      String name = (String)GetNonPublicProperty(k, "m_stLayoutName"); 
      String layoutHexString = ((UInt32)GetNonPublicProperty(k, "m_hkl")) 
       .ToString("X"); 

      TimeSpan elapsed = DateTime.UtcNow - loopStartTime; 
      Double ticksRemaining = ((Double)elapsed.Ticks * keyboards.Count) 
         /i - elapsed.Ticks; 
      TimeSpan remaining = new TimeSpan((Int64)ticksRemaining); 
      String msgTimeRemaining = ""; 
      if (i > 1) { 
       // Trim milliseconds 
       remaining = new TimeSpan(remaining.Hours, remaining.Minutes, 
         remaining.Seconds); 
       msgTimeRemaining = String.Format(", about {0} remaining", 
         remaining); 
      } 
      System.Console.WriteLine(
        "Saving {0} {1}, keyboard {2} of {3}{4}", 
        layoutHexString, name, i, keyboards.Count, 
        msgTimeRemaining); 

      SaveKeyboard(name, layoutHexString); 

     } 

     System.Console.WriteLine("{0} elapsed", DateTime.UtcNow - startTime); 

    } 

    private void SaveKeyboard(String name, String layoutHexString) { 
     Object k = keyboardType.GetConstructors(
       BindingFlags.Instance | BindingFlags.NonPublic)[0] 
      .Invoke(new Object[] { 
         new String[] {"", layoutHexString}, 
        false}); 

     SetNonPublicField(k, "m_fSeenOrHeardAboutPropertiesDialog", true); 
     SetNonPublicField(k, "m_stKeyboardTextFileName", 
       String.Format("{0}\\{1} {2}.klc", 
        baseDirectory, layoutHexString, name)); 
     InvokeNonPublicInstanceMethod(k, "mnuFileSave_Click", 
       new Object[] {new Object(), new EventArgs()}); 

     ((IDisposable)k).Dispose(); 
    } 

} 

yapar/Ancak, sistemdeki tüm klavyelerin bir listesini alır, sonra her biri için, MSKLC'ye yükler, "Farklı Kaydet" dosya adını ayarlar, özel klavye özelliklerini yapılandırmış olup olmadığına yatar ve daha sonra Dosya üzerinde bir tıklamayı simüle eder - > Menü öğesini kaydet. Bu DLL dosyaları yol nerede

+0

Bu harika bir cevap! Bunu denemek zorunda kalacağım ... – Benjol

+0

-1 tarball artık bulunamadı. Tekrar erişilince güncellenir. – Deleted

+0

@Kent bağlantı düzeltildi – andrewdotn

0

Windows API aşağıdakileri kontrol edin (inanıyorum)

[DllImport("user32.dll")] 
private static extern long LoadKeyboardLayout(string pwszKLID, uint Flags); 

kontrol MSDN here

+0

Hm, bu sadece mevcut işlem/iş parçacığı içinde bir klavye düzeni yükler, görsel olarak yeniden üretmeme izin vermez (diğer bir deyişle, hangi konumda anahtardır). – Benjol

+0

Burada bir şeye sahip olsanız da, MapVirtualKey bir tarayıcı kodunu (donanım) bir VirtualKey ile eşleştirebilir ve GetKeyNameText bir tarama kodunu bir dizgeye dönüştürebilir ... – Benjol

2

Neden ekran klavyesini (osk.exe) kullanmıyorsunuz? Direksiyonu yeniden icat ettiğine benziyor. Ve en kolay olanı değil!

+0

Bir bakma sorusu, korkarım. Unutmayın ki bu, tüm kontrolleri elleriyle hazırladıkları ve daha güzel hale getirecekleri bir pre-wpf projesidir. – Benjol

+0

Ayrıca bir dokunmatik ekran için biraz küçük. – ProfK

1

biliyorum: En kayıt olarak

, gördüğünüz: Her dal "Layout File"="KBDSP.dll" gibi bazı değere sahiptir

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts 

. kök dizin

C:\Windows\System32 

ve

C:\Windows\SystemWOW64 

olanlar dosyaların bulunduğu tüm klavye düzeni olmasıdır. Örneğin, KBDUS.dll, "ABD için klavye" anlamına gelir.

Ben MSKLC tarafından yapılan benim özel DLL ile DLL dosyasını atamayı denedi ve bunu "Dil" otomatik düzen harita görüntüleri yükleyen bulundu - "giriş yöntemi" - "önizleme":

enter image description here

Bu nedenle, eşlemenin DLL'de olduğunu biliyoruz.

İlgili konular