using System; using System.Collections; using System.Diagnostics; using System.Drawing; using System.IO; using System.Reflection; using System.Threading; using System.Windows.Forms; namespace System.Globalization { public class FormLanguageSwitchSingleton { #region Version und Copyright // Version und Copyright string dllName = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); //Den Programmnamen auslesen string dllVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); static object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); string copyright = GenerateCopyright(); string icon = Application.StartupPath + "\\Info.bmp"; //Assembly Datum und Zeit static DateTime value = AssemblyDateTime(); string date = value.ToShortDateString(); string time = value.ToLongTimeString(); private static DateTime AssemblyDateTime() { var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; var buildDateTime = new DateTime(2000, 1, 1).Add(new TimeSpan(TimeSpan.TicksPerDay * version.Build + TimeSpan.TicksPerSecond * 2 * version.Revision)); //Tage seit dem 1. Januar 2000 und Sekunden seit Mitternacht, (multiplizier mit 2 ergibt das Original) return buildDateTime; } private static string CurrentYear() { DateTime dtn = DateTime.Now; return dtn.Year.ToString(); } private static string StartYear() { string startYear = ""; if (((AssemblyCopyrightAttribute)attributes[0]).Copyright.Contains("Copyright © ")) { startYear = ((AssemblyCopyrightAttribute)attributes[0]).Copyright.Replace("Copyright © ", ""); while (startYear.StartsWith(" ")) { startYear = startYear.Remove(0, 1); } startYear = startYear.Remove(startYear.IndexOf(" ")); return startYear; } else { DateTime dtn = DateTime.Now; return dtn.Year.ToString(); } } private static string GenerateCopyright() { string startYear = StartYear(); string currentYear = CurrentYear(); if (startYear == currentYear) { return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; } else { return ((AssemblyCopyrightAttribute)attributes[0]).Copyright.Replace(startYear, String.Concat(startYear, "-", currentYear)); } } #endregion #region DLL-Info /// /// Contains the name of the program file /// public static string DllName { set; get; } /// /// Contains the version of the program file /// public static string DllVersion { set; get; } /// /// Contains the copyright notice /// public static string Copyright { set; get; } private void SetDllInfo() { //Name, Version und Copyright setzen DllName = dllName; DllVersion = dllVersion; Copyright = copyright; } #endregion /// /// Static read-only instance. /// protected static readonly FormLanguageSwitchSingleton m_instance = new FormLanguageSwitchSingleton(); /// /// Hidden constructor called during static member m_instance initialization. /// protected FormLanguageSwitchSingleton() { SetDllInfo(); } /// /// Gets the only instance of the object. /// public static FormLanguageSwitchSingleton Instance { get { return m_instance; } } /// /// Changes the current culture used by the Resource Manager to look up culture-specific resources at run time. /// /// /// A CultureInfo object that will be applied to the application thread. /// public void ChangeCurrentThreadUICulture(System.Globalization.CultureInfo cultureInfo) { Thread.CurrentThread.CurrentUICulture = cultureInfo; } /// /// Changes the language of the Form object provided to the currently selected language. /// /// /// Form object to apply changes to. /// public void ChangeLanguage(System.Windows.Forms.Form form) { ChangeLanguage(form, Thread.CurrentThread.CurrentUICulture); } /// /// Changes the language of the Form object provided and all its MDI /// children (in the case of MDI UI) to the currently selected language. /// /// /// Form object to apply changes to. /// /// /// CultureInfo to which language has to be changed. /// public void ChangeLanguage(System.Windows.Forms.Form form, System.Globalization.CultureInfo cultureInfo) { m_cultureInfo = cultureInfo; ChangeFormLanguage(form); foreach (System.Windows.Forms.Form childForm in form.MdiChildren) { ChangeFormLanguage(childForm); } } /// /// Changes Text properties associated with following /// controls: AxHost, ButtonBase, GroupBox, /// Label, ScrollableControl, StatusBar, /// TabControl, ToolBar. Method is made virtual so it /// can be overriden in derived class to redefine types. /// /// /// Control object. /// /// /// ResourceManager object. /// protected virtual void ReloadTextForSelectedControls(System.Windows.Forms.Control control, System.Resources.ResourceManager resources) { if (control is System.Windows.Forms.AxHost || control is System.Windows.Forms.ButtonBase || control is System.Windows.Forms.GroupBox || control is System.Windows.Forms.Label || control is System.Windows.Forms.ScrollableControl || control is System.Windows.Forms.StatusBar || control is System.Windows.Forms.TabControl || control is System.Windows.Forms.ToolBar) { control.Text = (string)GetSafeValue(resources, control.Name + ".Text", control.Text); } } /// /// Reloads properties common to all controls (except the Text property). /// /// /// Control object for which resources should be reloaded. /// /// /// ResourceManager object. /// protected virtual void ReloadControlCommonProperties(System.Windows.Forms.Control control, System.Resources.ResourceManager resources) { SetProperty(control, "AccessibleDescription", resources); SetProperty(control, "AccessibleName", resources); SetProperty(control, "BackgroundImage", resources); SetProperty(control, "Font", resources); SetProperty(control, "ImeMode", resources); SetProperty(control, "RightToLeft", resources); SetProperty(control, "Size", resources); // following properties are not changed for the form if (!(control is System.Windows.Forms.Form)) { SetProperty(control, "Anchor", resources); SetProperty(control, "Dock", resources); SetProperty(control, "Enabled", resources); SetProperty(control, "Location", resources); SetProperty(control, "TabIndex", resources); SetProperty(control, "Visible", resources); } if (control is System.Windows.Forms.ScrollableControl) { ReloadScrollableControlProperties((System.Windows.Forms.ScrollableControl)control, resources); if (control is System.Windows.Forms.Form) { ReloadFormProperties((System.Windows.Forms.Form)control, resources); } } } /// /// Reloads properties specific to some controls. /// /// /// Control object for which resources should be reloaded. /// /// /// ResourceManager object. /// protected virtual void ReloadControlSpecificProperties(System.Windows.Forms.Control control, System.Resources.ResourceManager resources) { // ImageIndex property for ButtonBase, Label, TabPage, ToolBarButton, TreeNode, TreeView SetProperty(control, "ImageIndex", resources); // ToolTipText property for StatusBar, TabPage, ToolBarButton SetProperty(control, "ToolTipText", resources); // IntegralHeight property for ComboBox, ListBox SetProperty(control, "IntegralHeight", resources); // ItemHeight property for ListBox, ComboBox, TreeView SetProperty(control, "ItemHeight", resources); // MaxDropDownItems property for ComboBox SetProperty(control, "MaxDropDownItems", resources); // MaxLength property for ComboBox, RichTextBox, TextBoxBase SetProperty(control, "MaxLength", resources); // Appearance property for CheckBox, RadioButton, TabControl, ToolBar SetProperty(control, "Appearance", resources); // CheckAlign property for CheckBox and RadioBox SetProperty(control, "CheckAlign", resources); // FlatStyle property for ButtonBase, GroupBox and Label SetProperty(control, "FlatStyle", resources); // ImageAlign property for ButtonBase, Image and Label SetProperty(control, "ImageAlign", resources); // Indent property for TreeView SetProperty(control, "Indent", resources); // Multiline property for RichTextBox, TabControl, TextBoxBase SetProperty(control, "Multiline", resources); // BulletIndent property for RichTextBox SetProperty(control, "BulletIndent", resources); // RightMargin property for RichTextBox SetProperty(control, "RightMargin", resources); // ScrollBars property for RichTextBox, TextBox SetProperty(control, "ScrollBars", resources); // WordWrap property for TextBoxBase SetProperty(control, "WordWrap", resources); // ZoomFactor property for RichTextBox SetProperty(control, "ZoomFactor", resources); // ButtonSize property for ToolBar SetProperty(control, "ButtonSize", resources); // ButtonSize property for ToolBar SetProperty(control, "DropDownArrows", resources); // ShowToolTips property for TabControl, ToolBar SetProperty(control, "ShowToolTips", resources); // Wrappable property for ToolBar SetProperty(control, "Wrappable", resources); // AutoSize property for Label, RichTextBox, ToolBar, TrackBar SetProperty(control, "AutoSize", resources); } /// /// Scans controls that are not contained by Controls collection, /// like MenuItems, StatusBarPanels and ColumnHeaders. /// /// /// ContainerControl object to scan. /// /// /// ResourceManager used to get localized resources. /// protected virtual void ScanNonControls(System.Windows.Forms.ContainerControl containerControl, System.Resources.ResourceManager resources) { FieldInfo[] fieldInfo = containerControl.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); for (int i = 0; i < fieldInfo.Length; i++) { object obj = fieldInfo[i].GetValue(containerControl); string fieldName = fieldInfo[i].Name; if (obj is System.Windows.Forms.MenuItem) { System.Windows.Forms.MenuItem menuItem = (System.Windows.Forms.MenuItem)obj; menuItem.Enabled = (bool)(GetSafeValue(resources, fieldName + ".Enabled", menuItem.Enabled)); menuItem.Shortcut = (System.Windows.Forms.Shortcut)(GetSafeValue(resources, fieldName + ".Shortcut", menuItem.Shortcut)); menuItem.ShowShortcut = (bool)(GetSafeValue(resources, fieldName + ".ShowShortcut", menuItem.ShowShortcut)); menuItem.Text = (string)GetSafeValue(resources, fieldName + ".Text", menuItem.Text); menuItem.Visible = (bool)(GetSafeValue(resources, fieldName + ".Visible", menuItem.Visible)); } if (obj is System.Windows.Forms.ToolStripMenuItem) { System.Windows.Forms.ToolStripMenuItem menuItem = (System.Windows.Forms.ToolStripMenuItem)obj; menuItem.Enabled = (bool)(GetSafeValue(resources, fieldName + ".Enabled", menuItem.Enabled)); menuItem.Text = (string)GetSafeValue(resources, fieldName + ".Text", menuItem.Text); } if (obj is System.Windows.Forms.StatusBarPanel) { System.Windows.Forms.StatusBarPanel panel = (System.Windows.Forms.StatusBarPanel)obj; panel.Alignment = (System.Windows.Forms.HorizontalAlignment)(GetSafeValue(resources, fieldName + ".Alignment", panel.Alignment)); panel.Icon = (System.Drawing.Icon)(GetSafeValue(resources, fieldName + ".Icon", panel.Icon)); panel.MinWidth = (int)(GetSafeValue(resources, fieldName + ".MinWidth", panel.MinWidth)); panel.Text = (string)(GetSafeValue(resources, fieldName + ".Text", panel.Text)); panel.ToolTipText = (string)(GetSafeValue(resources, fieldName + ".ToolTipText", panel.ToolTipText)); panel.Width = (int)(GetSafeValue(resources, fieldName + ".Width", panel.Width)); } if (obj is System.Windows.Forms.ColumnHeader) { System.Windows.Forms.ColumnHeader header = (System.Windows.Forms.ColumnHeader)obj; header.Text = (string)(GetSafeValue(resources, fieldName + ".Text", header.Text)); header.TextAlign = (System.Windows.Forms.HorizontalAlignment)(GetSafeValue(resources, fieldName + ".TextAlign", header.TextAlign)); header.Width = (int)(GetSafeValue(resources, fieldName + ".Width", header.Width)); } if (obj is System.Windows.Forms.ToolBarButton) { System.Windows.Forms.ToolBarButton button = (System.Windows.Forms.ToolBarButton)obj; button.Enabled = (bool)(GetSafeValue(resources, fieldName + ".Enabled", button.Enabled)); button.ImageIndex = (int)(GetSafeValue(resources, fieldName + ".ImageIndex", button.ImageIndex)); button.Text = (string)(GetSafeValue(resources, fieldName + ".Text", button.Text)); button.ToolTipText = (string)(GetSafeValue(resources, fieldName + ".ToolTipText", button.ToolTipText)); button.Visible = (bool)(GetSafeValue(resources, fieldName + ".Visible", button.Visible)); } } } /// /// Gets resource value. If resource for new culture does not exists, leaves the current. /// /// /// /// /// private object GetSafeValue(System.Resources.ResourceManager resources, string name, object currentValue) { object newValue = resources.GetObject(name, m_cultureInfo); if (newValue == null) { Trace.WriteLine(string.Format("Resource for {0} not found, using current value.", name)); return currentValue; } return newValue; } /// /// Reloads items in following controls: ComboBox, /// ListBox, DomainUpDown. Method is made virtual so /// it can be overriden in derived class to redefine types. /// /// /// Control object. /// /// /// ResourceManager object. /// protected virtual void ReloadListItems(System.Windows.Forms.Control control, System.Resources.ResourceManager resources) { if (control is System.Windows.Forms.ComboBox) { ReloadComboBoxItems((System.Windows.Forms.ComboBox)control, resources); } else if (control is System.Windows.Forms.ListBox) { ReloadListBoxItems((System.Windows.Forms.ListBox)control, resources); } else if (control is System.Windows.Forms.DomainUpDown) { ReloadUpDownItems((System.Windows.Forms.DomainUpDown)control, resources); } } /// /// Changes the language of the form. /// /// /// Form object to apply changes to. /// private void ChangeFormLanguage(System.Windows.Forms.Form form) { form.SuspendLayout(); Cursor.Current = Cursors.WaitCursor; System.Resources.ResourceManager resources = new System.Resources.ResourceManager(form.GetType()); // change main form resources form.Text = (string)(GetSafeValue(resources, "$this.Text", form.Text)); ReloadControlCommonProperties(form, resources); ToolTip toolTip = GetToolTip(form); // change text of all containing controls RecurControls(form, resources, toolTip); // change the text of menus ScanNonControls(form, resources); form.ResumeLayout(); } /// /// Gets the ToolTip member of the control (Form or UserControl). /// /// /// Control for which tooltip is requested. /// /// /// ToolTip of the control or null if not defined. /// private ToolTip GetToolTip(System.Windows.Forms.Control control) { Debug.Assert(control is System.Windows.Forms.Form || control is System.Windows.Forms.UserControl); FieldInfo[] fieldInfo = control.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); for (int i = 0; i < fieldInfo.Length; i++) { object obj = fieldInfo[i].GetValue(control); if (obj is System.Windows.Forms.ToolTip) { return (ToolTip)obj; } } return null; } /// /// Recurs Controls members of the control to change corresponding texts. /// /// /// Parent Control object. /// /// /// ResourceManager object. /// private void RecurControls(System.Windows.Forms.Control parent, System.Resources.ResourceManager resources, System.Windows.Forms.ToolTip toolTip) { foreach (Control control in parent.Controls) { control.SuspendLayout(); ReloadControlCommonProperties(control, resources); ReloadControlSpecificProperties(control, resources); if (toolTip != null) { toolTip.SetToolTip(control, (string)GetSafeValue(resources, control.Name + ".ToolTip", control.Text)); } if (control is System.Windows.Forms.UserControl) { RecurUserControl((System.Windows.Forms.UserControl)control); } else { ReloadTextForSelectedControls(control, resources); ReloadListItems(control, resources); if (control is System.Windows.Forms.TreeView) { ReloadTreeViewNodes((System.Windows.Forms.TreeView)control, resources); } if (control.Controls.Count > 0) { RecurControls(control, resources, toolTip); } } control.ResumeLayout(); } } /// /// Reloads resources specific to the Form type. /// /// /// Form object to apply changes to. /// /// /// ResourceManager object. /// private void ReloadFormProperties(System.Windows.Forms.Form form, System.Resources.ResourceManager resources) { SetProperty(form, "AutoScaleBaseSize", resources); SetProperty(form, "Icon", resources); SetProperty(form, "MaximumSize", resources); SetProperty(form, "MinimumSize", resources); } /// /// Reloads resources specific to the ScrollableControl type. /// /// /// Control object for which resources should be reloaded. /// /// /// ResourceManager object. /// private void ReloadScrollableControlProperties(System.Windows.Forms.ScrollableControl control, System.Resources.ResourceManager resources) { SetProperty(control, "AutoScroll", resources); SetProperty(control, "AutoScrollMargin", resources); SetProperty(control, "AutoScrollMinSize", resources); } /// /// Reloads resources for a property. /// /// /// Control object for which resources should be reloaded. /// /// /// Name of the property to reload. /// /// /// ResourceManager object. /// private void SetProperty(System.Windows.Forms.Control control, string propertyName, System.Resources.ResourceManager resources) { try { PropertyInfo propertyInfo = control.GetType().GetProperty(propertyName); if (propertyInfo != null) { string controlName = control.Name; if (control is System.Windows.Forms.Form) { controlName = "$this"; } object resObject = resources.GetObject(controlName + "." + propertyName, m_cultureInfo); if (resObject != null) { propertyInfo.SetValue(control, Convert.ChangeType(resObject, propertyInfo.PropertyType), null); } } } catch (AmbiguousMatchException e) { Trace.WriteLine(e.ToString()); } } /// /// Recurs UserControl to change. /// /// /// UserControl object to scan. /// private void RecurUserControl(System.Windows.Forms.UserControl userControl) { System.Resources.ResourceManager resources = new System.Resources.ResourceManager(userControl.GetType()); ToolTip toolTip = GetToolTip(userControl); RecurControls(userControl, resources, toolTip); // addition suggested by Piotr Sielski: ScanNonControls(userControl, resources); } /// /// Reloads items in the ListBox. If items are not sorted, selections are kept. /// /// /// ListBox to localize. /// /// /// ResourceManager object. /// private void ReloadListBoxItems(System.Windows.Forms.ListBox listBox, System.Resources.ResourceManager resources) { if (listBox.Items.Count > 0) { int[] selectedItems = new int[listBox.SelectedIndices.Count]; listBox.SelectedIndices.CopyTo(selectedItems, 0); ReloadItems(listBox.Name, listBox.Items, listBox.Items.Count, resources); if (!listBox.Sorted) { for (int i = 0; i < selectedItems.Length; i++) { listBox.SetSelected(selectedItems[i], true); } } } } /// /// Reloads items in the ComboBox. If items are not sorted, selection is kept. /// /// /// ComboBox to localize. /// /// /// ResourceManager object. /// private void ReloadComboBoxItems(System.Windows.Forms.ComboBox comboBox, System.Resources.ResourceManager resources) { if (comboBox.Items.Count > 0) { int selectedIndex = comboBox.SelectedIndex; ReloadItems(comboBox.Name, comboBox.Items, comboBox.Items.Count, resources); if (!comboBox.Sorted) { comboBox.SelectedIndex = selectedIndex; } } } /// /// Reloads items in the DomainUpDown control. If items are not sorted, selection is kept. /// /// /// DomainUpDown to localize. /// /// /// ResourceManager object. /// private void ReloadUpDownItems(System.Windows.Forms.DomainUpDown domainUpDown, System.Resources.ResourceManager resources) { if (domainUpDown.Items.Count > 0) { int selectedIndex = domainUpDown.SelectedIndex; ReloadItems(domainUpDown.Name, domainUpDown.Items, domainUpDown.Items.Count, resources); if (!domainUpDown.Sorted) { domainUpDown.SelectedIndex = selectedIndex; } } } /// /// Reloads content of a TreeView. /// /// /// TreeView control to reload. /// /// /// ResourceManager object. /// private void ReloadTreeViewNodes(System.Windows.Forms.TreeView treeView, System.Resources.ResourceManager resources) { if (treeView.Nodes.Count > 0) { string resourceName = treeView.Name + ".Nodes"; TreeNode[] newNodes = new TreeNode[treeView.Nodes.Count]; newNodes[0] = (System.Windows.Forms.TreeNode)resources.GetObject(resourceName, m_cultureInfo); // VS2002 generates node resource names with additional ".Nodes" string if (newNodes[0] == null) { resourceName += ".Nodes"; newNodes[0] = (System.Windows.Forms.TreeNode)resources.GetObject(resourceName, m_cultureInfo); } Debug.Assert(newNodes[0] != null); for (int i = 1; i < treeView.Nodes.Count; i++) { newNodes[i] = (System.Windows.Forms.TreeNode)resources.GetObject(resourceName + i.ToString(), m_cultureInfo); } treeView.Nodes.Clear(); treeView.Nodes.AddRange(newNodes); } } /// /// Clears all items in the IList and reloads the list with items according to language settings. /// /// /// Name of the control. /// /// /// IList with items to change. /// /// /// Number of items. /// /// /// ResourceManager object. /// private void ReloadItems(string controlName, IList list, int itemsNumber, System.Resources.ResourceManager resources) { string resourceName = controlName + ".Items"; object obj = resources.GetString(resourceName, m_cultureInfo); // VS2002 generates item resource name with additional ".Items" string if (obj == null) { resourceName += ".Items"; obj = resources.GetString(resourceName, m_cultureInfo); } if (obj != null) { list.Clear(); Debug.Assert(obj != null); list.Add(obj); for (int i = 1; i < itemsNumber; i++) { list.Add(resources.GetString(resourceName + i, m_cultureInfo)); } } } /// /// CultureInfo used by Resource Manager. /// private System.Globalization.CultureInfo m_cultureInfo; } }