Code:
/ 4.0 / 4.0 / 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; ////// /// public sealed class InputLanguage { ////// Provides methods and fields to manage the input language. /// ////// /// The HKL handle. /// ///private readonly IntPtr handle; /// /// /// ///internal InputLanguage(IntPtr handle) { this.handle = handle; } /// /// /// public CultureInfo Culture { get { return new CultureInfo((int)handle & 0xFFFF); } } ////// Returns /// the culture of the current input language. /// ////// /// 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"); } } } ////// Gets or sets the input language for the current thread. /// ////// /// 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 default input language for the system. /// ////// /// public IntPtr Handle { get { return handle; } } ////// Returns the handle for the input language. /// ////// /// 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 a list of all installed input languages. /// ////// /// 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; } } ////// Returns /// the name of the current keyboard layout as it appears in the Windows Regional Settings on the computer. /// ////// 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); } /// /// /// public override bool Equals(object value) { if (value is InputLanguage) { return(this.handle == ((InputLanguage)value).handle); } return false; } ///Specifies whether two input languages are equal. ////// /// 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; } ///Returns the input language associated with the specified /// culture. ////// /// 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. //------------------------------------------------------------------------------ //Hash code for this input language. ///// 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; ////// /// public sealed class InputLanguage { ////// Provides methods and fields to manage the input language. /// ////// /// The HKL handle. /// ///private readonly IntPtr handle; /// /// /// ///internal InputLanguage(IntPtr handle) { this.handle = handle; } /// /// /// public CultureInfo Culture { get { return new CultureInfo((int)handle & 0xFFFF); } } ////// Returns /// the culture of the current input language. /// ////// /// 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"); } } } ////// Gets or sets the input language for the current thread. /// ////// /// 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 default input language for the system. /// ////// /// public IntPtr Handle { get { return handle; } } ////// Returns the handle for the input language. /// ////// /// 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 a list of all installed input languages. /// ////// /// 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; } } ////// Returns /// the name of the current keyboard layout as it appears in the Windows Regional Settings on the computer. /// ////// 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); } /// /// /// public override bool Equals(object value) { if (value is InputLanguage) { return(this.handle == ((InputLanguage)value).handle); } return false; } ///Specifies whether two input languages are equal. ////// /// 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; } ///Returns the input language associated with the specified /// culture. ////// /// 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.Hash code for this input language. ///
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ScriptControlDescriptor.cs
- SqlProviderManifest.cs
- InputProcessorProfiles.cs
- HierarchicalDataSourceControl.cs
- RulePatternOps.cs
- StylusDevice.cs
- EnumerableRowCollectionExtensions.cs
- IdentityManager.cs
- RuntimeHandles.cs
- PropertyMetadata.cs
- SRef.cs
- WebPartDeleteVerb.cs
- ItemCheckEvent.cs
- EditorBrowsableAttribute.cs
- InvalidDataException.cs
- ServicesSection.cs
- MobileComponentEditorPage.cs
- WebPartRestoreVerb.cs
- NetworkInterface.cs
- Funcletizer.cs
- IndexerNameAttribute.cs
- EpmAttributeNameBuilder.cs
- TraceUtils.cs
- DotNetATv1WindowsLogEntrySerializer.cs
- GradientStopCollection.cs
- ToolStripSeparatorRenderEventArgs.cs
- DragEvent.cs
- PageCatalogPart.cs
- KeySpline.cs
- DataGridViewCellStyle.cs
- ClientProtocol.cs
- FlowDocumentPageViewerAutomationPeer.cs
- DefaultMemberAttribute.cs
- Rect.cs
- CommandTreeTypeHelper.cs
- Int16AnimationUsingKeyFrames.cs
- DataSourceView.cs
- HttpValueCollection.cs
- PassportAuthenticationModule.cs
- WebHttpBinding.cs
- WrapperEqualityComparer.cs
- Object.cs
- DecoderReplacementFallback.cs
- BamlWriter.cs
- CodeSubDirectory.cs
- RemoteTokenFactory.cs
- WindowsSecurityToken.cs
- SizeChangedInfo.cs
- ADMembershipUser.cs
- EncryptedType.cs
- HostTimeoutsElement.cs
- DrawItemEvent.cs
- RemotingConfiguration.cs
- DirectoryNotFoundException.cs
- clipboard.cs
- MaterialGroup.cs
- ActivityCollectionMarkupSerializer.cs
- ToolStripItemTextRenderEventArgs.cs
- DbConnectionPoolGroup.cs
- PngBitmapDecoder.cs
- ClusterRegistryConfigurationProvider.cs
- WebUtil.cs
- SupportsPreviewControlAttribute.cs
- ColorDialog.cs
- InvokeProviderWrapper.cs
- ServiceMemoryGates.cs
- UpdatableGenericsFeature.cs
- DataMisalignedException.cs
- TypeConverterHelper.cs
- Executor.cs
- Double.cs
- MimePart.cs
- _LoggingObject.cs
- OrderedDictionary.cs
- Menu.cs
- DetailsView.cs
- WebPartDisplayModeCollection.cs
- StringSorter.cs
- Tracer.cs
- FontStretch.cs
- FormClosingEvent.cs
- UnhandledExceptionEventArgs.cs
- InvokePattern.cs
- MergeFailedEvent.cs
- MessageDesigner.cs
- CodeSubDirectory.cs
- FontCacheLogic.cs
- AnnotationHighlightLayer.cs
- HttpCacheVaryByContentEncodings.cs
- ExtenderControl.cs
- SubordinateTransaction.cs
- CachedFontFace.cs
- SqlGatherConsumedAliases.cs
- RayHitTestParameters.cs
- NonParentingControl.cs
- SHA256Managed.cs
- PersonalizableAttribute.cs
- CompositeTypefaceMetrics.cs
- BindableTemplateBuilder.cs
- __FastResourceComparer.cs