TaskDialog 更改按钮语言

Posted

技术标签:

【中文标题】TaskDialog 更改按钮语言【英文标题】:TaskDialog change button language 【发布时间】:2013-06-12 07:59:38 【问题描述】:

我将Vista TaskDialog Wrapper and Emulator 用于WindowsForms。

它工作正常,但如何更改按钮的语言?

【问题讨论】:

【参考方案1】:

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

因此,如果您谈论更改常用按钮 YesNoOKCancelRetryClose 的语言,则其标签上的文本取自活动资源Windows 用户界面语言。这与从 Windows 开始就存在的 MsgBox() 对话框按钮的情况相同。 (按钮为YesNoOKCancelAbortRetryIgnoreHelp。)同一台机器上所有基本对话框的一致性。

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

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

【讨论】:

【参考方案2】:

来自未来的问候!

实际上你可以,正如我从阅读InitMUILanguage() vs MessageBox() 中了解到的那样,因为我也想更改语言。对我来说InitMUILanguage 不起作用(它使用了不鼓励的语言 ID 概念,请参阅LANG_NEUTRAL 上方的“咆哮”winnt.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 0xex.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 自动插入(因为它是一个字符串参数)。

结果:

相关:How do I set the UI language for a multi-threaded .NET process, independent of the OS language?

【讨论】:

以上是关于TaskDialog 更改按钮语言的主要内容,如果未能解决你的问题,请参考以下文章

Revit二次开发 任务对话框TaskDialog

在 C# 中使用 TaskDialog 时出现 EntryPointNotFoundException

TaskDialog 引发异常:需要版本 6 中的 comctl32.dll

TaskDialog 在 Visual C++ 中始终位于顶部

TaskDialog 在我的 Delphi 程序中不起作用

指定图标时,TaskDialog 窗口高度不正确