Я застрял при попытке использовать SystemParametersInfo. Я использую клавиатуру Dvorak, поэтому я пытаюсь сделать exe, чтобы дважды щелкнуть каждый раз, когда хочу изменить раскладку клавиатуры. Я использую SystemParametersInfo с C#. Я могу получить текущий язык ввода просто отлично. Но когда я пытаюсь установить язык ввода, я получаю возвращаемое значение false, и язык ввода не изменяется.Помощь с использованием SystemParametersInfo
Заранее благодарю за любую помощь.
Вот код, я использую:
class KeyboardSwitcher
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref uint pvParam, uint fWinIni);
private const uint SPI_GETDEFAULTINPUTLANG = 0x0059;
private const uint SPI_SETDEFAULTINPUTLANG = 0x005A;
private const uint SPIF_UPDATEINIFILE = 0x01;
private const uint SPIF_SENDWININICHANGE = 0x02;
private const uint DVORAK = 0xF0020409;
private const uint QWERTY = 0x04090409;
static void Main(string[] args)
{
uint currentLayout = 0;
uint newLayout = 0;
bool result = false;
int error = 0;
SystemParametersInfo(SPI_GETDEFAULTINPUTLANG, 0, ref currentLayout, 0);
if(currentLayout != DVORAK) {
newLayout = DVORAK;
/*result = SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, ref newLayout, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);*/
result = SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, ref newLayout, SPIF_SENDWININICHANGE);
error = Marshal.GetLastWin32Error();
}
else {
newLayout = QWERTY;
/*result = SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, ref newLayout, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);*/
result = SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, ref newLayout, SPIF_SENDWININICHANGE);
error = Marshal.GetLastWin32Error();
}
Console.WriteLine(">>> Current Layout <<<");
Console.WriteLine("0x" +currentLayout.ToString("X"));
Console.WriteLine(">>> New Layout <<<");
Console.WriteLine("0x" +newLayout.ToString("X"));
Console.WriteLine("Change Successful >>> " +result);
Console.WriteLine(error);
Console.WriteLine(">>> Final Layout <<<");
uint finalLayout = 0;
SystemParametersInfo(SPI_GETDEFAULTINPUTLANG, 0, ref finalLayout, 0);
Console.WriteLine("0x" +finalLayout.ToString("X"));
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
}
}
UPDATE:
Я бросил в Console.WriteLine (Marshal.GetLastWin32Error()); с остальными операциями печати и возвращается 0. Перед чтением комментариев я также попробовал GetLastError(), импортировав Kernel32.dll, и он также вернулся 0. Спасибо за ваши ответы.
ОБНОВЛЕНИЕ 2: Я изменил свой код, чтобы показать использование GetLastWin32Error().
Вот результат, когда у меня установлен Dvorak в качестве языка ввода по умолчанию.
>>> Current Layout <<<
0xF0020409
>>> New Layout <<<
0x4090409
Change Successful >>> True
Error Code >>> 0
>>> Final Layout <<<
0x4090409
Press any key to continue...
Вот результат, когда у меня есть Qwerty в качестве языка ввода по умолчанию.
>>> Current Layout <<<
0x4090409
>>> New Layout <<<
0xF0020409
Change Successful >>> True
Error Code >>> 0
>>> Final Layout <<<
0xF0020409
Press any key to continue...
Я получил шестигранные значения для макетов использовать SPI_GETDEFAULTINPUTLANG, когда я был каждый макет установлен по умолчанию. Как вы думаете, значение, которое оно возвращает, может отличаться от значения, которое мне нужно отправить?
Я провел некоторое исследование по классу InputLanguage, и я не считаю, что он подходит для этой ситуации, потому что свойство DefaultInputLanguage не имеет сеттера, и нет других методов для установки языка ввода по умолчанию.
UPDATE 3: Когда я изменяю четвертый параметр SystemParametersInfo только на SPIF_SENDWININICHANGE, он становится намного ближе к работе. Результат SET - True, и когда я запускаю программу обратно, она переключает язык взад и вперед. Таким образом, это означает, что что-то в Windows действительно меняется. Тем не менее, изменение нового отражается в панели управления, и клавиатура фактически не изменяется. Я чувствую, что мне нужен SPIF_UPDATEINIFILE, чтобы продвинуть изменение. Значение, которое я использую, правильно, не так ли? Я также обновил код и вывод, чтобы результат был немного более подробным.
Что говорит GetLastError? –
@Carey Вы имеете в виду Marshal.GetLastWin32Error. Никогда не вызывайте 'GetLastError' из управляемого кода. –
К сожалению, не заметил тег. Так что да, сделайте это GetLastWin32Error. –