1

我使用Vista TaskDialog Wrapper 和 Emulator for WindowsForms。

它工作正常,但我怎样才能更改按钮的语言?

4

2 回答 2

1

我有理由认为更改常用按钮的语言是不可能的。(常用按钮有特殊处理,也会返回特殊结果,请参见TASKDIALOGCONFIG 结构。没有提供语言更改的选项。)

因此,如果您谈论的是常用按钮YesNoOKCancelRetry、的语言更改Close,则其标签上的文本取自活动 Windows UI 语言的资源。MsgBox()这与从 Windows 开始就存在的对话框按钮的情况相同。(按钮是Yes, No, OK, Cancel, Abort, Retry, Ignore, Help.)我相信普通按钮的措辞没有改变,以保持同一台机器上所有基本对话框的统一程度。

您的应用程序并不孤单,大多数已经安装了不同语言的应用程序的用户只是接受这种行为并且不将其视为错误。您总是可以解释这是使用 Windows 提供的模板制作的对话框的标准行为。您非常清楚,标签的更改不是唯一的,而是TaskDialog的众多限制之一。

解决方法是创建自定义按钮,尽管随之而来的是您将失去创建链接的能力。如果您正在编写大型应用程序,请考虑为这种类型的对话框编写自己的基础,因为许多应用程序也已经实现了。

于 2013-09-18T12:40:23.850 回答
0

来自未来的问候!

实际上你可以,正如我从阅读InitMUILanguage() 与 MessageBox()中学到的那样,因为我也想改变语言。对我来说InitMUILanguage不起作用(它使用了不鼓励的语言 ID 概念,请参阅上面的“咆哮” LANG_NEUTRALwinnt.h。但是SetProcessPreferredUILanguagesSetThreadPreferredUILanguages两者都这样做。

以下是如何使用它(调整您链接的示例):

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using static TaskDialog.NativeMethods;

namespace TaskDialog
{
    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            //Remove the check if you know your parameters are in the correct format
            CheckResult(SetProcessPreferredUILanguages(MUI_LANGUAGE_NAME, MakeMultiString("ab-CD", "zh-cn"), out _));
            //Or SetThreadPreferredUILanguages(MUI_LANGUAGE_NAME, MakeMultiString("ab-CD", "zh-cn"), out _);

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

    internal static class NativeMethods
    {
        public static void CheckResult(bool success)
        {
            if (!success)
            {
                var ex = new Win32Exception();
                Debug.WriteLine($"Error 0x{ex.NativeErrorCode:X}");
                throw ex;
            }
        }

        //Generates a double null-terminated multi-string buffer (PCZZWSTR)
        public static string MakeMultiString(params string[] items) => string.Join("\0", items) + "\0";

        //WinNls.h
        public const uint MUI_LANGUAGE_NAME = 0x8; // Use ISO language (culture) name convention

        //Omitting CharSet sets it to Ansi which is not what we want
        // Even after typing this I changed this to Ansi to test it again and forgot to change it back;
        // took me quite some time to figure out what was going on
        //https://docs.microsoft.com/windows/desktop/api/winnls/nf-winnls-setprocesspreferreduilanguages
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool SetProcessPreferredUILanguages(
            uint dwFlags,
            string pwszLanguagesBuffer,
            out uint pulNumLanguages
        );

        //https://docs.microsoft.com/windows/desktop/api/winnls/nf-winnls-setthreadpreferreduilanguages#c#-signature
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool SetThreadPreferredUILanguages(
            uint dwFlags,
            string pwszLanguagesBuffer,
            out uint pulNumLanguages
        );
    }
}

pwszLanguagesBuffer接收由两个字母的ISO 639-1语言名称和一个由连字符分隔的两个字母的ISO 3166-1 alpha-2区域代码组成的语言环境列表,按优先级降序排列。在这种情况下ab-CD,不是现有的语言环境,因此zh-CN选择了(中文的变体)。仅考虑前 5 种有效语言。

请注意,pwszLanguagesBuffer列表中的每个项目都必须以 NULL 字符(\0\u0000)结尾。额外+ '\0'是因为string.Join只在项目之间插入分隔符。然后这个列表用一个额外的 NULL 终止符关闭,由 .NET 自动插入(因为它是一个字符串参数)。

结果:
中文按钮

相关:如何为多线程 .NET 进程设置 UI 语言,独立于操作系统语言?

于 2018-08-30T18:32:55.567 回答