Coding with .NET

Live with passion, coding with passion....

首页 新随笔 联系 订阅 管理

使用 .net 开发一个多语言支持的 WinForm 程序是很容易的,特别是在 C# 2.0 中为资源文件提供了 ResXFileCodeGenerator 自定义工具就更方便了。然而好像不是很容易在运行时选择界面显示使用的语言(不知道是不是其实很简单,只是我不知道:) 下面的东东就当是抛砖引玉吧)。就像常用的 BT 下载软件 BitComet,可以方便得在菜单中设置界面显示使用不同的语言。

在 .net 程序中,多语言的支持是以 satellite assemblies 的形式实现的,只要在相应的位置存在某种语言的 satellite assembly即可。而在vs.net工程中,只要为每个资源文件添加相应语言的资源文件就能实现(比如:Resources.resx对应的简体中体的资源文件为 Resources.zh-CHS.resx,英语的资源文件为 Resources.en.resx ),至于如何生成合适的 satellite assembly,就交给vs.net来完成了。

在程序运行的时候,默认情况下会使用计算机默认的语言。如果装了中文的操作系统,一般会使用中文作为默认语言的。

在程序运行的时候,要改变当前使用的语言,可以设置下面的属性:

  • Thread.CurrentThread.CurrentCulture
  • Thread.CurrentThread.CurrentUICulture
要改变窗体上各个控件在显示时使用的语言,必须在此控件创建好之前设置 CurrentUICulture 属性。如果在窗体显示之后再设置,由于控件都已经创建好了,即使设置了 CurrentUICulture 属性,窗体上各控件显示的文字仍然不会有变化。

前面说了,我们需要在窗体上的控件被创建之前设置 CurrentUICulture 属性。那已经创建好的控件怎么办呢?是不是需要重新创建呢? 寻找 System.Windows.Forms.Form 类,好像没有与重新创建控件相关的方法。再看与 Form 密切相关的 System.Windows.Forms.Application 类,有个 Restart 方法!可以试着运行一下。设置 CurrentUICulture,调用 Application.Restart;或者调用 Application.Restart,设置 CurrentUICulture,可是都没有任何效果!失望中....

再试着找其他相关的方法,好像除了 Restart 方法外都不怎么沾边。再用 Reflector 看看 Application.Restart 方法的源代码看看。原来这个 Restart 方法是调用 Application.ExitThread 方法结束当前的线程,然后再新创建一个进程来运行当前程序。原来是这样,设置 CurrentUICulture 属性当然不会有任何效果啦。那么我们能不能在这个新的进程上想什么办法呢?结果还是不行:( System.Diagnostics.Process 类和 System.Diagnostics.ProcessStartInfo 类似乎都不含和 CultureInfo 相关的方法或属性之类的。唉,路又被堵上了:( 别急,我们再接再厉,接着来:)

根据上面的方法,我们是调用 Application.Restart 方法(或者是Process.Start方法吧)重新启动程序,而且需要在程序重新启动之后、显示窗体之前设置 Thread.CurrentThread.CurrentUICulture/CurrentCulture 属性。我们只要在 Process.Start 和 Thread.CurrentThread.CurrentUICulture/CurrentCulture 之类建立起联系就 OK 了! :) 再来看看 Process 类或者 ProcessStartInfo 类,ProcessStartInfo 类有个 Arguments 属性,用于设置命令行参数。参数!参数不是可以用来传递数据的吗?那我们在调用 Process.Start 方法(Application.Restart 方法看来是不行了,它并不接受任何的参数)时,可以将使用语言的信息传递过去呀,然后在程序启动的时候(一般是 Main 方法啦)设置 Thread.CurrentThread.CurrentUICulture 就行了哦!

经过试验,上述的方法还是可行的:) 示例代码如下:

 1 public sealed class AppliationHelper
 2 {
 3   public static void SetupCultureInfo()
 4   {
 5     int lcid;
 6     string lcidString;
 7     string arguments;
 8     
 9     arguments = Environment.GetCommandLineArgs();
10     
11     if( arguments.Length>=2 ){
12       lcidString = arguments[1];
13       
14       if (Int32.TryParse(lcidString, out lcid) && lcid > 0) {
15         try {
16           cultureInfo = new CultureInfo(lcid);          
17           Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = cultureInfo;
18         }
19         catch { }
20       }
21     }
22   }
23   
24   public static void Restart( int lcid )
25   {
26     ProcessStartInfo startInfo = Process.GetCurrentProcess().StartInfo;
27     startInfo.FileName = Application.ExecutablePath;
28     startInfo.Arguments = lcid.ToString();
29 
30     Application.ExitThread();
31     Process.Start(startInfo);
32   }
33 }

在程序入口 Main 方法中需要调用 ApplicationHelper.SetupCultureInfo 方法,如:

1 [STAThread]
2 private static void Main()
3 {
4   ApplicationHelper.SetupCultureInfo();
5   Application.Run(new MainForm());
6 }
posted on 2005-08-20 00:53  Lin  阅读(3358)  评论(6编辑  收藏  举报