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

Я использую Vista TaskDialog Wrapper and Emulator для WindowsForms.

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


person David    schedule 12.06.2013    source источник


Ответы (2)


У меня есть основания полагать, что изменить язык общих кнопок НЕВОЗМОЖНО. (Обычные кнопки обрабатываются особым образом и также возвращают специальные результаты, см. структура TASKDIALOGCONFIG. Параметр для смены языка не предусмотрен.)

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

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

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

person miroxlav    schedule 18.09.2013

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

На самом деле вы можете, как я узнал из чтения InitMUILanguage() vs 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 независимо от языка ОС?

person SWdV    schedule 30.08.2018