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 (потому что это строковый параметр).