TaskDialog изменить язык кнопок

Я использую Vista TaskDialog Wrapper и эмулятор для WindowsForms.

Работает нормально, но как поменять язык кнопок?

2 ответа

Решение

У меня есть причины думать, что изменить язык общих кнопок НЕ возможно. (Общие кнопки обрабатываются особым образом, а также возвращают особые результаты, см. Структуру TASKDIALOGCONFIG. Для изменения языка не предусмотрено никакой опции.)

Так что, если вы говорите об изменении языка общих кнопок Yes, No, OK, Cancel, Retry, Closeзатем текст на их ярлыках берется из ресурсов активного языка интерфейса Windows. Это тот же случай, что и с кнопками MsgBox() диалог, который был там с самого начала Windows. (Кнопки Yes, No, OK, Cancel, Abort, Retry, Ignore, Help.) Я считаю, что формулировка общих кнопок не была изменяемой, чтобы сохранить степень однородности во всех основных диалоговых окнах на одном компьютере.

Ваше приложение не одиноко с этой проблемой, и большинство пользователей, которые уже установили приложения на другом языке, просто принимают это поведение и не рассматривают его как ошибку. Вы всегда можете объяснить, что это стандартное поведение для диалоговых окон, созданных с использованием шаблона, предоставленного Windows. Вы очень хорошо знаете, что смена меток - не единственное, а одно из многих ограничений TaskDialog.

Обходной путь заключается в создании пользовательских кнопок, хотя наряду с этим вы теряете возможность создавать ссылки. Если вы пишете большое приложение, подумайте о том, чтобы написать собственный фундамент для диалоговых окон этого типа, которые уже реализованы во многих приложениях.

Привет из будущего!

На самом деле вы можете, как я узнал из чтения InitMUILanguage() против MessageBox (), потому что я тоже хотел изменить язык. Для меня InitMUILanguage не работает (и он использует обескураженную концепцию идентификатора языка, см. "напыщенная речь" выше LANG_NEUTRAL в winnt.h). Но SetProcessPreferredUILanguages а также SetThreadPreferredUILanguages оба делают.

Вот как это использовать (настраивая приведенный вами пример):

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-процесса, независимого от языка ОС?

Другие вопросы по тегам