C#(99):资源与本地化 System.Resources

原文:

https://docs.microsoft.com/zh-cn/dotnet/framework/resources/

https://docs.microsoft.com/zh-cn/dotnet/framework/resources/creating-resource-files-for-desktop-apps

一、创建资源文件

可以将字符串、图像或对象数据等资源包含在资源文件中,方便应用程序使用。

创建资源文件的方法:

1、手动或使用IDE工具自动生成XML 资源 (.resx) 文件。(推荐)

创建一个包含字符串、图像或对象数据的 XML 资源 (.resx) 文件。

使用 Visual Studio 创建一个资源文件并将其包含在项目中。

Visual Studio 提供一个资源编辑器,借助该编辑器,可添加、删除和修改资源。 编译时,资源文件会自动转换成二进制 .resources 文件,并嵌入应用程序程序集或附属程序集中。

注意:内部使用资源文件生成器 (Resgen.exe) 将文本文件转换成二进制资源 (.resources) 文件。 然后使用语言编译器将这个二进制资源文件嵌入可执行应用程序或应用程序库,或者使用程序集链接器 (Al.exe) 将这个二进制资源文件嵌入附属程序集。

2、以编程方式创建一个 XML 资源 (.resx) 文件。 使用ResXResourceWriter类

可以创建一个 .resx 文件、枚举其资源并按名称检索特定资源。

ResXResourceWriter rw = new ResXResourceWriter("Demo.rex");
rw.AddResource("Logo", Image.FromFile("logo.jpg");
rw.AddResource("Title", "Proce c#");
rw.Generate();
rw.Close();

二、使用ResourceManager读取项目中资源文件

资源文件调用方法
(1).txt 文件:不可以直接调用,得先将其转换成 .resources 文件才能使用。
(2).resx 文件:可以用 ResXResourceReader 来做读取,但是这种方法不直观,不推荐直接调用 .resx 文件。正确的方法是将其转换成 .resources 文件,然后用 ResourceManager 作读取工作。
注意如果是在 VS.NET 中添加的 .resx 文件,那么它们自动被设为 Embedded Resource,转成 .resources 文件后被嵌入到 Assembly 中。
(3).resources 文件分成两种情况:
1、被嵌入或编译成 Satellite Assembly:使用ResourceManager来获得在 Assembly 中的资源。
2、单独文件,没被编译或嵌入到Assembly:使用ResourceManager.CreateFileBasedResourceManager来获得资源集(ResourceSet)。

在新建的Windows项目中,一般自动生成两个资源文件:Form1.resx和Resources.resx。其中,Form1.resx附属Form1窗体,Resources.resx在项目Properties子文件夹下。

下面我们看看读取项目中资源文件

1、强类型读取项目中resx资源文件。

1、创建一个项目的默认资源文件。

image

2、在项目“Properties”目录下,可以看到Resources.resx。

image

3、添加相关的资源。

image

4、可以看到系统自动生成的强类型类。

image

使用强类型可直接使用类

logo.Image = ZS.MouldManagement.Properties.Resources._0

不仅在Properties文件夹下可以建立资源文件,也可以在任何地方创建资源文件。在建立名称为MyResource资源文件的同时,设计器会自动生成两个文件:MyResource.resx和MyResource.Designer.cs。其中后一个文件就包装了设计器自动生成的代码,以方便对资源文件的强类型访问。image

强类型访问代码:

ZS.MouldManagement.Mould._333

2、使用代码读取项目中不同文化的resx资源文件

ResourceManager 可以根据不同的 UICulture 设置返回不同的本地资源,我们只需知道调用资源用到它就可以了。

Winform使用资源文件(ZS.MouldManagement.resx;ZS.MouldManagement.en-us.rex等等)

//多语言
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-us");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");

Assembly asm = Assembly.GetExecutingAssembly();
ResourceManager rm = new ResourceManager("ZS.MouldManagement.Properties.Resources", asm);
//ZS.MouldManagement是你程序的命名空间,ZS.MouldManagement.Properties 是资源类Resources的命名空间, 资源文件名称不带扩展名
this.logo.Image = (Image)rm.GetObject("Logo");//Get**方法具有重载方法,第二个参数为CultureInfo对象
this.Title.Text = rm.GetString("Title");    //资源文件名称不带扩展名

三、Windows项目中的窗体资源文件

因为对Form1.resx的访问需要构造Syste.Resources.ResourceManager对象,而访问Resources.resx里的资源可以直接使用Properties.Resources.resName(resName是你添加的资源的名称)。
只有向窗体上添加图标、图像等资源后

image

会在窗体设计器Form1.Designer.cs自动生成下面的代码

ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));//创建ResourceManager对象
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));//根据资源的名称获取字符串资源
  
this.Item1.Image = global::ZS.MouldManagement.Properties.Resources._0; //访问项目中的资源

从代码可以看出,c#将窗体的图标文件作为资源进行保存了起来,然后利用ComponentResourceManager来获取这些资源。

它和ResourceManager用法一样,System.ComponentModel.ComponentResourceManager继承自Syste.Resources.ResourceManager。

1、使用ComponentResourceManager类进行界面多语言切换

Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");

ComponentResourceManager resources = new ComponentResourceManager(typeof(Form1));
resources.ApplyResources(this, "$this");
AppLang(form, resources);

#region AppLang for control
/// <summary>
/// 遍历窗体所有控件,针对其设置当前界面语言
/// </summary>
/// <param name="control"></param>
/// <param name="resources"></param>
private static void AppLang(Control control, System.ComponentModel.ComponentResourceManager resources)
{
    if (control is MenuStrip)
    {
        resources.ApplyResources(control, control.Name);
        MenuStrip ms = (MenuStrip)control;
        if (ms.Items.Count > 0)
        {
            foreach (ToolStripMenuItem c in ms.Items)
            {
                AppLang(c, resources);
            }
        }
    }

    foreach (Control c in control.Controls)
    {
        resources.ApplyResources(c, c.Name);
        AppLang(c, resources);
    }
}
#endregion

#region AppLang for menuitem
/// <summary>
/// 遍历菜单
/// </summary>
/// <param name="item"></param>
/// <param name="resources"></param>
private static void AppLang(ToolStripMenuItem item, System.ComponentModel.ComponentResourceManager resources)
{
    if (item is ToolStripMenuItem)
    {
        resources.ApplyResources(item, item.Name);
        ToolStripMenuItem tsmi = (ToolStripMenuItem)item;
        if (tsmi.DropDownItems.Count > 0)
        {
            foreach (ToolStripMenuItem c in tsmi.DropDownItems)
            {
                AppLang(c, resources);
            }
        }
    }
}
   #endregion

四、使用Assembly.GetManifestResourceStream()从此程序集加载指定的文件。

当直接嵌入一资源时,也就是说,不通过一个资源文件而直接将一资源(比如图片)嵌入到 Assembly 中。这可以在 VS.NET 中通过设置一文件的 Build 属性为“嵌入的资源” 实现。

在这种情况下 ResourceManager 就没有用了,因为它只能获取 .resources 资源文件。那么如何调用这类的资源呢?我们只要了解一些 System.Reflection.Assembly 这个类中的一些函数就可以了。

有三个相关函数,不过我们只需要 Assembly.GetManifestResourceStream 这个函数。这个函数将一嵌入到 Assembly 中的资源以 stream 的方式返回,而我们可以将这个 stream 转成在 .NET 中可用的对象。

比如,如果嵌入资源是一图片,那么我们可以利用 new Bitmap(Stream) 这个构造方法获得这个图片资源的 Bitmap 对象。

1、将本地要加入的资源文本(视频,图片,文本或其它)加入项目。比如我们现在加入一个up.bmp的图片到项目中,且放在文件夹Resources下面,
2、将up.bmp右键选择“属性”的“生成操作”设置为"嵌入的资源"。

注意:访问资源的名称规则为:项目命名空间.资源文件所在文件夹名.资源文件名

Assembly assm = Assembly.getGetExecutingAssembly();
Stream stream = assm.GetManifestResourceStream("CreateDatabase.Resources.aa.txt");
//读取流
//文本
System.IO.StreamReader sr = new System.IO.StreamReader(stream);
string str = sr.ReadToEnd();
//XML文件
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(stream);
//图片
Image img = Image.FromStream(stream);

posted on 2020-07-15 16:39  springsnow  阅读(5185)  评论(0编辑  收藏  举报

导航