c # - Assistance ved hjælp af SystemParametersInfo

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg er blevet fast, mens jeg forsøger at bruge SystemParametersInfo. Jeg bruger Dvorak tastaturet, så jeg forsøger at lave en exe, som jeg kan dobbeltklikke, når jeg vil ændre tastaturlayoutet. Jeg bruger SystemParametersInfo med C #. Jeg kan lige hente det nuværende indgangssprog. Men når jeg forsøger at angive indgangssproget, får jeg en returværdi af falsk, og indgangssproget ændres ikke.


Tak på forhånd for enhver hjælp.


Her er koden jeg bruger:


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:


Jeg kastede i Console.WriteLine (Marshal.GetLastWin32Error ()); med resten af ​​udskriftserklæringerne og den vender tilbage 0. Før jeg læste kommentarerne forsøgte jeg også GetLastError () ved at importere Kernel32.dll, og den returnerede også 0. Tak for dine svar.


UPDATE 2: Jeg har ændret min kode for at vise min brug af GetLastWin32Error ().


Her er outputen, når jeg har Dvorak indstillet som standard indgangssprog.


>>> Current Layout <<<
0xF0020409
>>> New Layout <<<
0x4090409
Change Successful >>> True
Error Code >>> 0
>>> Final Layout <<<
0x4090409
Press any key to continue...


Her er outputen, når jeg har Qwerty angivet som standard indgangssprog.


>>> Current Layout <<<
0x4090409
>>> New Layout <<<
0xF0020409
Change Successful >>> True
Error Code >>> 0
>>> Final Layout <<<
0xF0020409
Press any key to continue...


Jeg fik hex-værdierne for layouterne at bruge SPI\_GETDEFAULTINPUTLANG, da jeg havde hvert layout indstillet som standard. Tror du, at den værdi, den returnerer, kan være anderledes end den værdi, jeg skal sende?


Jeg har gjort en del forskning på InputLanguage Class, og jeg tror ikke, det passer til denne situation, fordi Egenskaben DefaultInputLanguage ikke har en setter, og der er ingen andre metoder til at indstille standard input sprog.


OPDATERING 3:
Når jeg ændrer den fjerde parameter i SystemParametersInfo til bare SPIF\_SENDWININICHANGE, bliver det meget tættere på arbejdet. Resultatet af SET er True, og når jeg kører programmet tilbage til tilbage skifter sproget frem og tilbage. Så det betyder, at noget i Windows faktisk bliver ændret. Ændringen er imidlertid nyt, der afspejles i kontrolpanelet, og tastaturet ændrer sig ikke. Jeg har lyst til, at jeg har brug for SPIF\_UPDATEINIFILE for at skubbe ændringen igennem. Den værdi, jeg bruger, er korrekt, er det ikke? Jeg har også opdateret koden og output, så outputen er lidt mere verbose.

Bedste reference


For at informere en ansøgning om, at sproget er ændret uden at genstarte det, skal du sende ansøgningsvinduet en WM\_INPUTLANGCHANGEREQUEST efterfulgt af en WM\_INPUTLANGCHANGE besked, hvor lParam er lokalidentifikatoren.