2009-03-19 4 views
8

से कीबोर्ड लेआउट निकालना ठीक है, यह थोड़ा अजीब सवाल है।विंडोज

हम एक टच स्क्रीन आवेदन (यानी, कोई कीबोर्ड) है। जब उपयोगकर्ताओं को टेक्स्ट दर्ज करने की आवश्यकता होती है, तो एप्लिकेशन वर्चुअल कीबोर्ड दिखाता है - WinForms में हाथ से निर्मित।

प्रत्येक नई भाषा के लिए इन चीजों को हाथ से बनाना बंदर का काम है। मुझे लगता है कि विंडोज़ में कुछ डीएलएल में कहीं भी इस कुंजीपटल लेआउट की जानकारी होनी चाहिए। विंडोज़ से यह जानकारी प्राप्त करने के लिए वैसे भी होगा?

अन्य विचारों का स्वागत (मैं कम से कम एक xml फ़ाइल से बात पैदा करने वी.एस. में हाथ से यह कर की तुलना में बेहतर हो गया है आंकड़ा)।

(नोट: कहा है जो सभी, मैं ध्यान दें एक जापानी कुंजीपटल, राज्य मशीन है कि वहाँ और सभी ..., तो एक्सएमएल नहीं पर्याप्त हो सकता है)

अद्यतन: इस विषय पर बहुत अच्छी श्रृंखला (मेरा मानना ​​है कि) here

+2

यह वास्तव में एक अच्छा सवाल है ... अन्य वातावरण (लिनक्स) को लेआउट पोर्ट करना संभव भी हो सकता है, लेकिन शायद यह पाठ्यक्रम के कॉपीराइट का उल्लंघन हो सकता है। – unwind

+0

बिल्ट-इन विंडोज टैबलेट कीबोर्ड का उपयोग करना आसान नहीं होगा? (जाहिर है कि ओएस में स्थापित सही एक्सटेंशन की आवश्यकता है, लेकिन ऐसा लगता है कि इन दिनों इसमें केवल एक वाकम प्लगिंग करना पर्याप्त है, तो शायद और तरीके हो सकते हैं?)। –

उत्तर

6

Microsoft Keyboard Layout Creator प्रणाली कीबोर्ड लोड और उन्हें .klc files के रूप में निर्यात कर सकते हैं। चूंकि यह .NET में लिखा गया है, यह देखने के लिए कि आप इसे कैसे करते हैं, Reflector का उपयोग कर सकते हैं और इसे चलाने के लिए प्रतिबिंब का उपयोग कर सकते हैं। नीचे दिए गए C# कोड का उपयोग करके बनाया गया zip file of .klc files for the 187 keyboards in Windows 8 है। ध्यान दें कि मैं मूल रूप से Windows XP के लिए यह लिखा था, और अब विंडोज 8 और ऑन-स्क्रीन कीबोर्ड के साथ, यह वास्तव में धीमी है और टास्कबार दुर्घटना लगता है:/हालांकि, यह काम :)

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(); 
    } 

} 

करता है मूल रूप से, यह सिस्टम पर सभी कीबोर्ड की एक सूची प्राप्त करता है, फिर प्रत्येक के लिए, इसे एमएसकेएलसी में लोड करता है, "इस रूप में सहेजें" फ़ाइल नाम सेट करता है, यह इस बारे में है कि यह पहले से ही कस्टम कीबोर्ड गुणों को कॉन्फ़िगर कर चुका है या फिर फ़ाइल पर एक क्लिक अनुकरण करता है - > मेनू आइटम सहेजें।

+0

यह एक अच्छा जवाब है! मुझे इसे आज़मा देना होगा ... – Benjol

+0

-1 क्योंकि टैरबॉल अब नहीं मिल सकता है। एक बार फिर से पहुंचने के बाद मैं अपडेट करूंगा। – Deleted

+0

@ केंट लिंक तय किया गया है – andrewdotn

0

कृपया Windows API निम्नलिखित की जाँच

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

चेक MSDN here

+0

एचएम, यह सिर्फ वर्तमान प्रक्रिया/धागे में एक कीबोर्ड लेआउट लोड करता है, यह मुझे इसे दृष्टि से पुन: पेश करने की अनुमति नहीं देता है (यानी, किस स्थिति में कुंजी है)। – Benjol

+0

यद्यपि आप यहां कुछ भी हो सकते हैं, जाहिर है MapVirtualKey वर्चुअलकी में स्कैनकोड (हार्डवेयर) को मैप कर सकता है, और GetKeyNameText एक स्कैनकोड को स्ट्रिंग में परिवर्तित कर सकता है ... – Benjol

2

आप ऑन-स्क्रीन कीबोर्ड (osk.exe) का उपयोग क्यों नहीं करते? ऐसा लगता है कि आप पहिया का पुन: आविष्कार कर रहे हैं। और सबसे आसान नहीं!

+0

लुकअप का एक प्रश्न, मुझे डर है। ध्यान रखें कि यह एक प्री-डब्लूपीएफ प्रोजेक्ट है जहां उन्होंने हाथ से सभी नियंत्रणों को दोहराया, ताकि उन्हें सुंदर बना दिया जा सके। – Benjol

+0

यह टच-स्क्रीन के लिए भी छोटा है। – ProfK

1

मुझे पता है, जहां इन DLL फ़ाइलों 'पथ कर रहे हैं:

अपनी रजिस्ट्री में, आप देख:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts 

जहां प्रत्येक शाखा "Layout File"="KBDSP.dll" जैसे कुछ मूल्य है। रूट निर्देशिका

C:\Windows\System32 

और

C:\Windows\SystemWOW64 

उन सभी कीबोर्ड लेआउट फ़ाइलें स्थित हैं कर रहे हैं। उदाहरण के लिए, KBDUS.dll का अर्थ है "यूएस के लिए कीबोर्ड"।

मैं अपने कस्टम MSKLC द्वारा किए गए DLL साथ DLL फ़ाइल स्थानापन्न करने की कोशिश की, और मैं इसे "भाषा" में स्वचालित रूप से लेआउट मैपिंग छवियाँ लोड करता पाया - "इनपुट विधि" - "पूर्वावलोकन":

enter image description here

तो हम जानते हैं कि मैपिंग डीएलएल में है।