【问题标题】:Assistance using SystemParametersInfo协助使用 SystemParametersInfo
【发布时间】:2012-03-12 14:52:16
【问题描述】:

我在尝试使用 SystemParametersInfo 时卡住了。我使用 Dvorak 键盘,所以我正在尝试制作一个 exe,只要我想更改键盘布局,我就可以双击它。我将 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());其余的打印语句返回 0。在阅读 cmets 之前,我还通过导入 Kernel32.dll 尝试了 GetLastError(),它也返回 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 来推动更改。我使用的值是正确的,不是吗?我还更新了代码和输出,使输出更加详细。

【问题讨论】:

  • @Carey 你的意思是 Marshal.GetLastWin32Error。永远不要从托管代码调用GetLastError
  • 糟糕,没有注意到标签。所以,是的,让 GetLastWin32Error。
  • 我已经用错误结果更新了我的问题。不幸的是,事实证明它们并没有太大帮助。
  • 您从哪里获得您的 HKL 值?另外,为什么将输出代码添加到您的应用程序但不显示给我们?如果您向我们展示了这一切,那么我们就不必猜测和提问。你如何显示输出。此外,您如何包括对 GetLastWin32Error 的调用并显示这些。真的,永远不要从托管代码中调用 GetLastError。如果您想知道为什么不这样做,请阅读 GetLastWin32Error 的文档。
  • .NET InputLanguage 类就是为此而设计的,比起 pinvoke 更喜欢它。

标签: c# .net windows winapi pinvoke


【解决方案1】:

要通知应用程序语言已更改而无需重新启动,您需要向应用程序窗口发送 WM_INPUTLANGCHANGEREQUEST 后跟 WM_INPUTLANGCHANGE 消息,其中 lParam 是区域设置标识符。

【讨论】:

    猜你喜欢
    • 2011-04-09
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多