Change system default language programmatically with c# - c#

We have a virtual keyboard (for touch screen) which its language layout is configured via the windows default language.
I have seen numerous answers which involves InputLanguageManager and CultureInfo.
They're not useful to me, didn't do the job.
There is this one method - SystemParametersInfo function with the SPI_SETDEFAULTINPUTLANG flag that i'm trying to check.
So far, didn't find any useful usage examples besides this one here, but it changes the keyboard layout from Dvorak to Marshal.
Can you give me an example (hopefully with the SystemParametersInfo) that converts the default system language to en-US?
Edit
A brief clarification.
This program replaces the explorer as windows shell, hence all keyboard settings such as setting default keyboard layout should be handled from my program.
Moreover, my wish is to replace between different installed languages such as English, Swedish, Portuguese and so on..
I don't want to change between Dvorak and Qwerty layout of the keyboard.
The purpose of this post is to ask for examples for changing between different languages and not for layout of English symbols on keyboard.
Thanks!

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref uint pvParam, uint fWinIni);
public void Foo()
{
uint localeUS = 0x00000409;
uint localeNL = 0x00000403;
SetSystemDefaultInputLanguage(localeUS);
}
public bool SetSystemDefaultInputLanguage(uint locale)
{
return SystemParametersInfo(SPI_SETDEFAULTINPUTLANG, 0, ref locale, 0);
}
public uint GetSystemDefaultInputLanguage()
{
uint result = uint.MinValue;
bool retVal = SystemParametersInfo(SPI_GETDEFAULTINPUTLANG, 0, ref result, 0);
return result;
}
This seems to work fine for me.
Sources:
SystemParametersInfo API
SystemParametersInfo Parameter Definition
Input Locales List MSDN

Related

Switch between multiple keyboard types within a language in C#

I am using Hindi Indic Input 3 Language Pack for Hindi language. I need to provide multiple layout options for this language but when I check the installed language types it shows same Layout Id for all the layouts within this language pack. My objective is to allow users to switch between Mangal - CBI and Mangal - GAIL input from my WinForms application. Below is the code:
void ChangeCulture(string culture)
{
original = InputLanguage.CurrentInputLanguage;
var _culture = System.Globalization.CultureInfo.GetCultureInfo(culture);
var _language = InputLanguage.FromCulture(_culture);
if (InputLanguage.InstalledInputLanguages.IndexOf(_language) >= 0)
InputLanguage.CurrentInputLanguage = _language;
else
InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage;
}
I also used this native method for changing the keyboard layout using the layout id. But the problem is the layout id is same for all Hindi Indic Input 3 layout types.
[DllImport("user32.dll")]
private static extern IntPtr LoadKeyboardLayout(string pwszKLID, uint Flags);
LoadKeyboardLayout("hi-IN", 0xf0c00439);
I am unable to find any documentation on this language pack. Below is how it is selected from language bar. I need to select these two GAIL and CBI types from C# code. Please help.
Looks like you need to check an input locale identifier (formerly called the keyboard layout, HKL) instead of InputLanguage. That's why your language stays the same (Hindi) when you have different layouts. You don't need the pack docs because installed 'language' is a part of the system.
OS Windows has a wider definition for 'InputLanguage' than just a 'keyboard layout'. It has ALL input channels, including 'speech-to-text', an Input Method Editor (IME). When the keyboard layout sets, it sets InputLanguage.CurrentInputLanguage also.
So, yes, user32.dll is the right way to call Window's C++ functions:
HKL GetKeyboardLayout(
[in] DWORD idThread
);
HKL ActivateKeyboardLayout(
[in] HKL hkl,
[in] UINT Flags
);
Just try other functions from this DLL. Such as GetKeyboardLayout (get current layout for a thread), GetKeyboardLayoutList (get all system layouts), ActivateKeyboardLayout (set HKL as active).
Please, check the gist below from https://github.com/vurdalakov to play with layouts, not languages:
https://gist.github.com/vurdalakov/9cea795e82109fdacb7062dcb122b42e
Hope, this will help.

How to get the IME layout in C# Winform specially in Wndproc?

I have a winform application, I want to get the information of current typing language in C#. I have windows 10 machine, I have selected Korean language. There is one toggle button in taskbar to change input language as English or Korean once I select Korean language.
Following code always gives Korean language, but it should give English when I select input in English.
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hwnd, IntPtr proccess);
[DllImport("user32.dll")]
static extern IntPtr GetKeyboardLayout(uint thread);
public Form1()
{
InitializeComponent();
IntPtr foregroundWindow = GetForegroundWindow();
uint foregroundProcess = GetWindowThreadProcessId(foregroundWindow, IntPtr.Zero);
int keyboardLayout = GetKeyboardLayout(foregroundProcess).ToInt32() & 0xFFFF;
CultureInfo info = new CultureInfo(keyboardLayout);
int keyboardLayoutId = info.KeyboardLayoutId;
string name = info.Name;
}
Is there any other way to get the input language information.
You can find the attached image for the same. I have highlighted A as english input.
I want this information in WndProc method.
Problem Summry:
So I want to handle the case when User switched language to type by toggle button, I want any wndproc message or window side event to get the language information, when User switches language by toggle button.
Your question is a result of a confusion of IME mode and the input layout. Your input layout is Korean in both cases - what changes is your IME mode.
You can find the IME mode of an input control using Control.ImeMode (and check for a change using Control.ImeModeChanged). This will tell you that you're either in Korean - Hangul, or Korean - Alpha. EDIT: Actually, this only allows you to force a given setting, not read the user-specified IME mode, and apparently shouldn't be used.
Further complication is if you have global input enabled (available since Windows 8), where the input configuration is no longer stored per-thread, but rather is global. In that case ImeMode doesn't work, and is completely ignored. I don't think there's anything you can do about it from the application side - the setting is no longer yours to see or change. According to MSDN, the proper replacement would be the ImmGetConversionStatus function, though only for desktop applications.

Changing windows settings with a script

I have a problem that every once in a while the amount of lines or w\e that moves when I turn the mouse wheel goes from 3 to 30 and my brother sometimes sees it changes to 100.
What I'm talking about is when you go to "Control Panel" -> "Mouse" -> and then the mouse-wheel tab, it has 2 number-scrollers, and I need to change the value of the first one with a script or .exe or whatever way you know how to change it with.
For whoever might encounter that problem and wants the solution, here's the code:
[DllImport("user32.dll", SetLastError = true)]
static extern bool SystemParametersInfo(int uiAction, int uiParam, IntPtr pvParam, int fWinIni);
static void Main(string[] args)
{
const int SPI_SETWHEELSCROLLLINES = 0x0069;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDCHANGE = 0x02;
SystemParametersInfo(SPI_SETWHEELSCROLLLINES, 3, IntPtr.Zero,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
Thanks for helping!
System parameters are not to be changed via registry keys, because (1) that's an implementation detail, that may change in future versions of Windows or even depending on other user profile settings and (2) because you are updating just the saved value, not the one that is currently active.
The correct way to go is to use the SystemParametersInfo API specifying the correct parameter constant (in your case, SPI_SETWHEELSCROLLLINES) and SPIF_UPDATEINIFILE | SPIF_SENDCHANGE as last parameter to both activate it right now and save it for the next sessions.
With regedit you can setup a script that sets the mouse wheeel scrolling speed, property is here:
HKEY_CURRENT_USER\Control Panel\Desktop\WheelScrollLines
just browse regedit (win+R regedit) look at the WeelScrollLines value, then create a reg file as specified by microsoft : https://support.microsoft.com/en-us/kb/310516#bookmark-syntax

C# Memory Access Violation Windows 7

I'm using advanced installer 8.3 and trying to impliment trial licensing for my application, the target OS is Windows 7 x32 & x64.
The following code is taken from an example supplied by advanced installer.
[DllImport("Trial.dll", EntryPoint = "ReadSettingsStr", CharSet = CharSet.Auto)]
private static extern uint InitTrial(String aKeyCode, IntPtr aHWnd);
[DllImport("Trial.dll", EntryPoint = "ReadSettingsRetStr", CharSet = CharSet.Auto)]
private static extern uint InitTrialReturn(String aKeyCode, IntPtr aHWnd);
[DllImport("Trial.dll", EntryPoint = "DisplayRegistrationStr", CharSet = CharSet.Auto)]
private static extern uint DisplayRegistration(String aKeyCode);
[DllImport("Trial.dll", EntryPoint = "GetPropertyValue", CharSet = CharSet.Auto)]
private static extern uint GetPropertyValue(String aPropName, StringBuilder aResult, ref UInt32 aResultLen);
private void registerToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
Process process = Process.GetCurrentProcess();
DisplayRegistration(kLibraryKey, process.MainWindowHandle);
}
catch(Exception ex1)
{
MessageBox.Show(ex1.ToString());
}
}
The type signature set in advanced installer is 32bit unicode DEP Aware.
The problem is everytime i select register i get an Access Violation. It appears i cannot use the switch on my app to turn off DEP as it is required for my application.
Does anyone have any ideas how to get round this, as i have checked on the advanced installer forum and theres not much other than similar issues.
Many Thanks
OK quick update.
I tried all the combinations of the sig type this is what i found.
Setting the type to 32bit Ansi (Supports Win9x or higher) and set the CharSet to Ansi/Unicode or Auto result = CRASH.
Setting the type to 32bit Unicode (DEP Aware) and set the CharSet to Unicode or Auto result = Access Violation.
Setting the type to 32bit Unicode (DEP Aware) and set the CharSet to Ansi result = success.
So although it is working there's obviously a bug in Advanced Installer.
Based on your last comment (using CharSet.None fixes the problem), I would guess the following:
Specifying CharSet.None, which is the deprecated synonym for CharSet.Ansi, really causes P/Invoke to marshal the strings as ANSI, not Unicode (which would be used with CharSet.Auto on Windows NT platforms).
Looking at "6. Integrate the Licensing Library within application" it looks like VB.NET (so maybe also C#) should use the "ANSI" version of the Trial.dll (APIs).
Or maybe there is a different version of Trial.dll that supports unicode, but is not the one that is in your PATH (and thus is not found by P/Invoke).
I don't know the product, so it's hard to tell.

Disabling Screen Saver and Power Options in C#

I am writing an application in C# that plays a movie. I need to figure out how to disable the screen saver and power options using C#.
I know the Windows SDK API has a function called SetThreadExecutionState() which can be used to do this, however, I do not know if there is a better way to do it. If not, how do I incorporate this function into C#?
Not sure if there is a better .NET solution but here is how you could use that API:
The required usings:
using System.Runtime.InteropServices;
The P/Invoke:
public const uint ES_CONTINUOUS = 0x80000000;
public const uint ES_SYSTEM_REQUIRED = 0x00000001;
public const uint ES_DISPLAY_REQUIRED = 0x00000002;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SetThreadExecutionState([In] uint esFlags);
And then disable screensaver by:
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
Finnaly enable screensaver by reseting the execution state back to original value:
SetThreadExecutionState(ES_CONTINUOUS);
Note that I just picked one of the flags at random in my example. You'd need to combine the correct flags to get the specific behavior you desire. You will find the description of flags on MSDN.

Categories

Resources