使用 .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 属性。那已经创建好的控件怎么办呢?是不是需要重新创建呢? 寻找 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 就行了哦!
经过试验,上述的方法还是可行的:) 示例代码如下:
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 方法,如:
2 private static void Main()
3 {
4 ApplicationHelper.SetupCultureInfo();
5 Application.Run(new MainForm());
6 }