Помощь с использованием SystemParametersInfo - PullRequest
3 голосов
/ 12 марта 2012

Я застрял при попытке использовать SystemParametersInfo.Я использую клавиатуру Dvorak, поэтому я пытаюсь создать исполняемый файл, который я могу дважды щелкнуть, когда захочу изменить раскладку клавиатуры.Я использую SystemParametersInfo с C #.Я могу получить текущий язык ввода просто отлично.Но когда я пытаюсь установить язык ввода, я получаю возвращаемое значение false, и язык ввода не меняется.

Заранее спасибо за любую помощь.

Вот код, который яЯ использую:

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);
    }
}

ОБНОВЛЕНИЕ:

Я бросил в Console.WriteLine (Marshal.GetLastWin32Error ());с остальными операторами print и он возвращает 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не имеет установщика, и нет других методов для установки языка ввода по умолчанию.

ОБНОВЛЕНИЕ 3: Когда я изменяю четвертый параметр SystemParametersInfo на SPIF_SENDWININICHANGE, он становится намного ближе к работе.Результатом SET является True, и когда я запускаю программу обратно, она переключает язык назад и вперед.Так что это означает, что что-то в Windows действительно меняется.Тем не менее, изменение является новым отражением в панели управления, и клавиатура фактически не меняется.Я чувствую, что мне нужно SPIF_UPDATEINIFILE, чтобы протолкнуть изменения.Значение, которое я использую, является правильным, не так ли?Я также обновил код и вывод, чтобы вывод был более подробным.

1 Ответ

1 голос
/ 14 мая 2012

Чтобы сообщить приложению, что язык изменился, не перезапуская его, вам необходимо отправить окну приложения WM_INPUTLANGCHANGEREQUEST, за которым следует сообщение WM_INPUTLANGCHANGE, где lParam - идентификатор языкового стандарта.

...