InputLanguage.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / InputLanguage.cs / 1305376 / InputLanguage.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Windows.Forms { 
    using System.Text; 
    using System.Runtime.InteropServices;
    using System.Runtime.Remoting; 
    using System.Security.Permissions;

    using System.Diagnostics;
 
    using System;
    using Microsoft.Win32; 
    using System.Globalization; 
    using System.ComponentModel;
    using System.Drawing; 

    /// 
    /// 
    ///     
    ///       Provides methods and fields to manage the input language.
    ///     
    ///  
    public sealed class InputLanguage {
 
        /// 
        /// 
        ///     The HKL handle.
        ///  
        /// 
        private readonly IntPtr handle; 
 
        /// 
        ///  
        /// 
        /// 
        internal InputLanguage(IntPtr handle) {
            this.handle = handle; 
        }
 
        ///  
        /// 
        ///     
        ///       Returns
        ///       the culture of the current input language.
        ///    
        ///  
        public CultureInfo Culture {
            get { 
                return new CultureInfo((int)handle & 0xFFFF); 
            }
        } 

        /// 
        /// 
        ///     
        ///       Gets or sets the input language for the current thread.
        ///     
        ///  
        public static InputLanguage CurrentInputLanguage {
            get { 
                Application.OleRequired();
                // note we can obtain the KeyboardLayout for a given thread...
                return new InputLanguage(SafeNativeMethods.GetKeyboardLayout(0));
            } 
            set {
                IntSecurity.AffectThreadBehavior.Demand(); 
 
                // (NDPWhidbey 8362) OleInitialize needs to be called before we can call ActivateKeyboardLayout.
                Application.OleRequired(); 
                if (value == null) {
                    value = InputLanguage.DefaultInputLanguage;
                }
                IntPtr handleOld = SafeNativeMethods.ActivateKeyboardLayout(new HandleRef(value, value.handle), 0); 
                if (handleOld == IntPtr.Zero) {
                    throw new ArgumentException(SR.GetString(SR.ErrorBadInputLanguage), "value"); 
                } 
            }
        } 

        /// 
        /// 
        ///     
        ///       Returns the default input language for the system.
        ///     
        ///  
        public static InputLanguage DefaultInputLanguage {
            get { 
                IntPtr[] data = new IntPtr[1];
                UnsafeNativeMethods.SystemParametersInfo(NativeMethods.SPI_GETDEFAULTINPUTLANG, 0, data, 0);
                return new InputLanguage(data[0]);
            } 
        }
 
        ///  
        /// 
        ///     
        ///       Returns the handle for the input language.
        ///    
        /// 
        public IntPtr Handle { 
            get {
                return handle; 
            } 
        }
 
        /// 
        /// 
        ///    
        ///       Returns a list of all installed input languages. 
        ///    
        ///  
        public static InputLanguageCollection InstalledInputLanguages { 
            get {
                int size = SafeNativeMethods.GetKeyboardLayoutList(0, null); 

                IntPtr[] handles = new IntPtr[size];
                SafeNativeMethods.GetKeyboardLayoutList(size, handles);
 
                InputLanguage[] ils = new InputLanguage[size];
                for (int i = 0; i < size; i++) 
                    ils[i] = new InputLanguage(handles[i]); 

                return new InputLanguageCollection(ils); 
            }
        }

        ///  
        /// 
        ///     
        ///       Returns 
        ///       the name of the current keyboard layout as it appears in the Windows Regional Settings on the computer.
        ///     
        /// 
        public string LayoutName {
            get {
                // There is no good way to do this in Win32...  GetKeyboardLayoutName does what we want, 
                // but only for the current input language; setting and resetting the current input language
                // would generate spurious InputLanguageChanged events. 
 
                /*
                            HKL is a 32 bit value. HIWORD is a Device Handle. LOWORD is Language ID. 

                HKL
                +------------------------+-------------------------+
                |     Device Handle      |       Language ID       | 
                +------------------------+-------------------------+
                31                     16 15                      0   bit 
 

                Language ID 
                +---------------------------+-----------------------+
                |     Sublanguage ID        | Primary Language ID   |
                +---------------------------+-----------------------+
                15                        10 9                     0   bit 

                WORD LangId  = MAKELANGID(primary, sublang) 
                BYTE primary = PRIMARYLANGID(LangId) 
                BYTE sublang = PRIMARYLANGID(LangID)
 
                How Preload is interpreted: example US-Dvorak
                Look in HKEY_CURRENT_USER\Keyboard Layout\Preload
                Name="4"  (may vary)
                Value="d0000409"  -> Language ID = 0409 
                Look in HKEY_CURRENT_USER\Keyboard Layout\Substitutes
                Name="d0000409" 
                Value="00010409" 
                Look in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00010409
                "Layout File": name of keyboard layout DLL (KBDDV.DLL) 
                "Layout Id": ID of this layout (0002)
                Win32k will change the top nibble of layout ID to F, which makes F002.
                Combined with Language ID, the final HKL is F0020409.
                */ 

                string layoutName = null; 
 
                IntPtr currentHandle = handle;
                int language = unchecked( (int) (long)currentHandle) & 0xffff; 
                int device = (unchecked( (int) (long)currentHandle) >> 16) & 0x0fff;

                // SECREVIEW : We have to get the input information from the registry. These two
                //           : keys only contain keyboard information. This is safe to do. 
                //
                new RegistryPermission(PermissionState.Unrestricted).Assert(); 
 
                try {
                    if (device == language || device == 0) { 
                        // Default keyboard for language
                        string keyName = Convert.ToString(language, 16);
                        keyName = PadWithZeroes(keyName, 8);
                        RegistryKey key = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\" + keyName); 

                        // Attempt to extract the localized keyboard layout name 
                        // using the SHLoadIndirectString API... 
                        layoutName = GetLocalizedKeyboardLayoutName(key.GetValue("Layout Display Name") as string);
 
                        // Default back to our legacy codepath and obtain the name
                        // directly through the registry value
                        if (layoutName == null) {
                            layoutName = (string) key.GetValue("Layout Text"); 
                        }
 
                        key.Close(); 
                    }
                    else { 
                        // Look for a substitution
                        //
                        RegistryKey substitutions = Registry.CurrentUser.OpenSubKey("Keyboard Layout\\Substitutes");
                        string[] encodings = null; 
                        if (substitutions != null) {
                            encodings = substitutions.GetValueNames(); 
 
                            foreach (string encoding in encodings) {
                                int encodingValue = Convert.ToInt32(encoding, 16); 
                                if (encodingValue == unchecked( (int) (long)currentHandle) ||
                                    (encodingValue & 0x0FFFFFFF) == (unchecked( (int) (long)currentHandle) & 0x0FFFFFFF) ||
                                    (encodingValue & 0xFFFF) == language) {
 
                                    currentHandle = (IntPtr)Convert.ToInt32((string)substitutions.GetValue(encoding), 16);
                                    language = unchecked( (int) (long)currentHandle) & 0xFFFF; 
                                    device = (unchecked( (int) (long)currentHandle) >> 16) & 0xFFF; 
                                    break;
                                } 
                            }

                            substitutions.Close();
                        } 

                        RegistryKey layouts = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts"); 
                        if (layouts != null) { 
                            encodings = layouts.GetSubKeyNames();
 
                            // Check to see if the encoding directly matches the handle -- some do.
                            //
                            foreach (string encoding in encodings) {
                                Debug.Assert(encoding.Length == 8, "unexpected key in registry: hklm\\SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\" + encoding); 
                                if (currentHandle == (IntPtr)Convert.ToInt32(encoding, 16)) {
                                    RegistryKey key = layouts.OpenSubKey(encoding); 
 
                                    // Attempt to extract the localized keyboard layout name
                                    // using the SHLoadIndirectString API... 
                                    layoutName = GetLocalizedKeyboardLayoutName(key.GetValue("Layout Display Name") as string);

                                    // Default back to our legacy codepath and obtain the name
                                    // directly through the registry value 
                                    if (layoutName == null) {
                                        layoutName = (string) key.GetValue("Layout Text"); 
                                    } 

                                    key.Close(); 
                                    break;
                                }
                            }
                        } 

                        if (layoutName == null) { 
 
                            // No luck there.  Match the language first, then try to find a layout ID
                            // 
                            foreach (string encoding in encodings) {
                                Debug.Assert(encoding.Length == 8, "unexpected key in registry: hklm\\SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\" + encoding);
                                if (language == (0xffff & Convert.ToInt32(encoding.Substring(4,4), 16))) {
                                    RegistryKey key = layouts.OpenSubKey(encoding); 
                                    string codeValue = (string) key.GetValue("Layout Id");
                                    if (codeValue != null) { 
                                        int value = Convert.ToInt32(codeValue, 16); 
                                        if (value == device) {
 
                                            // Attempt to extract the localized keyboard layout name
                                            // using the SHLoadIndirectString API...
                                            layoutName = GetLocalizedKeyboardLayoutName(key.GetValue("Layout Display Name") as string);
 
                                            // Default back to our legacy codepath and obtain the name
                                            // directly through the registry value 
                                            if (layoutName == null) { 
                                                layoutName = (string) key.GetValue("Layout Text");
                                            } 
                                        }
                                    }
                                    key.Close();
                                    if (layoutName != null) { 
                                        break;
                                    } 
                                } 
                            }
                        } 

                        layouts.Close();
                    }
                } 
                finally {
                    System.Security.CodeAccessPermission.RevertAssert(); 
                } 

                if (layoutName == null) { 
                    layoutName = SR.GetString(SR.UnknownInputLanguageLayout);
                }
                return layoutName;
            } 
        }
 
        ///  
        ///     Attempts to extract the localized keyboard layout name using the
        ///     SHLoadIndirectString API (only on OSVersions >= 5).  Returning 
        ///     null from this method will force us to use the legacy codepath
        ///     (pulling the text directly from the registry).
        /// 
        private static string GetLocalizedKeyboardLayoutName(string layoutDisplayName) { 

            if (layoutDisplayName != null && Environment.OSVersion.Version.Major >= 5) { 
 
                StringBuilder sb = new StringBuilder(512);
 
                uint res = UnsafeNativeMethods.SHLoadIndirectString(layoutDisplayName, sb, (uint)sb.Capacity, IntPtr.Zero);

                if (res == NativeMethods.S_OK) {
                    return sb.ToString(); 
                }
            } 
 
            return null;
        } 

        /// 
        /// 
        ///     Creates an InputLanguageChangedEventArgs given a windows message. 
        /// 
        ///  
        internal static InputLanguageChangedEventArgs CreateInputLanguageChangedEventArgs(Message m) { 
            return new InputLanguageChangedEventArgs(new InputLanguage(m.LParam), unchecked((byte)(long)m.WParam));
        } 

        /// 
        /// 
        ///     Creates an InputLanguageChangingEventArgs given a windows message. 
        /// 
        ///  
        internal static InputLanguageChangingEventArgs CreateInputLanguageChangingEventArgs(Message m) { 
            InputLanguage inputLanguage = new InputLanguage(m.LParam);
 
            // NOTE: by default we should allow any locale switch
            //
            bool localeSupportedBySystem = !(m.WParam == IntPtr.Zero);
            return new InputLanguageChangingEventArgs(inputLanguage, localeSupportedBySystem); 

        } 
 
        /// 
        ///  
        ///    Specifies whether two input languages are equal.
        /// 
        public override bool Equals(object value) {
            if (value is InputLanguage) { 
                return(this.handle == ((InputLanguage)value).handle);
            } 
            return false; 
        }
 
        /// 
        /// 
        ///    Returns the input language associated with the specified
        ///       culture. 
        /// 
        public static InputLanguage FromCulture(CultureInfo culture) { 
 
            // KeyboardLayoutId is the LCID for built-in cultures, but it
            // is the CU-preferred keyboard language for custom cultures. 
            int lcid = culture.KeyboardLayoutId;

            foreach(InputLanguage lang in InstalledInputLanguages) {
                if ((unchecked( (int) (long)lang.handle) & 0xFFFF) == lcid) { 
                    return lang;
                } 
            } 

            return null; 
        }

        /// 
        ///  
        ///    Hash code for this input language.
        ///  
        public override int GetHashCode() { 
            return unchecked( (int) (long)handle);
        } 

        private static string PadWithZeroes(string input, int length) {
            return "0000000000000000".Substring(0, length - input.Length) + input;
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK