The best way to change system language c# - c#

The application will be installed by users from different countries, and what languages ​​the keyboard layout of a specific user is unknown. We need a way with which the keyboard layout will change.

[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
public void ChangeLanguage()
{
PostMessage(GetForegroundWindow(), 0x0050, 2, 0);
}

Related

Working Global Mouse (and optionally Keyboard) Hook with .net core

I'm trying to detect the horizontal scroll wheel movement globally in .net core 3.1 (or at least movement of any mouse wheel). I want to build this application to work for both, Windows 10 x64 and arm-linux. However, I only need the hook functionality on Windows. I have tried to use the WindowsHook which includes System.Windows.Forms MouseEvents and also the normal MouseKeyHook which it is based on. Both didn't work. The same goes for my implementations of SetWindowsHookEx and the Raw Input API. Trying them in .net core applications only results in a massive input lag as soon as the listeners are in place and no events actually getting triggered. I searched for like two days now and I start to believe you need to be a wizard to get such a global hook to work in .net core. Help would be highly appreciated!
Edit: This is my first time working with hooks and doing low level stuff so I don't understand all of it 100%. I only have this code snippet here atm. For the WindowsHook and MouseKeyHook I just use the examples which you can find on corresponding linked github projects.
Here is the SetWindowsHookEx version, I just call the constructor to get it running and it doesn't even capture hscroll I believe:
using System;
using System.Runtime.InteropServices;
class Intercept_Mouse
{
private static LowLevelMouseProc _proc = HookCallback;
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr _hookID = IntPtr.Zero;
public Intercept_Mouse()
{
_hookID = SetWindowsHookEx(WH_MOUSE_LL, _proc, IntPtr.Zero, 0);
}
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam))
{
Console.WriteLine("Clicked");
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}

Memory Management of imported C++ methods in C#

I have a Windows Forms Application that imports and uses some C++ methods from user32.dll.
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(int xPoirnt, int yPoint);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr parentHandel, IntPtr childAfter, String sClassName, String windowTitle);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);
[DllImport("msvcrt.dll")]
private static extern int memcmp(IntPtr b1, IntPtr b2, long count);
I've noticed that after my app runs for an extended period of time, the memory usage can go up to 500~MB (initial 5MB).
I don't have that much C++ experience but I know that you have to manually do memory management for C++.
My questions is, do I have to do memory management for my app or will the C# garbage collector handle it.

C# Win32 Interop Crashes when Enumerating Window Handles

I have a C# wrapper for some Win32 operations involving window handles, but I am experiencing an unexpected crash, with no details, when I call a Win32 function.
Interestingly, this whole code sample works fine when the class is constructed (at application init time), but later fails when the same buildCache() method is called.
Here is the relevant code:
public delegate bool CallBack(int hWnd, int lParam);
public class Win32Interop {
private Dictionary<int, string> windowCache = new Dictionary<int, string>();
public Win32Interop() {
buildCache();
}
public void buildCache() {
windowCache.Clear();
CallBack hWndCacher = new CallBack(saveHWndHandler);
EnumWindows(hWndCacher, 0);
}
public void doThings(string title, uint message, bool rebuildCache = false) {
//Use the window title to get its handle
int hWnd = titleToHWnd(title, rebuildCache);
SendMessage(hWnd, message, 0, 0);
}
private bool saveHWndHandler(int hWnd, int lParam) {
if(IsWindow(hWnd) != 0) { / ***** CRASHES HERE ***** /
int length = GetWindowTextLength(hWnd);
StringBuilder title = new StringBuilder(length + 1);
GetWindowText(hWnd, title, title.Capacity);
string formatted = title.ToString().Trim();
windowCache.Add(hWnd, formatted);
}
return true;
}
private int titleToHWnd(string title, bool rebuildCache = false) {
if(rebuildCache)
buildCache();
if(windowCache.ContainsValue(title)) {
return windowCache.FirstOrDefault(x => x.Value.Contains(title)).Key;
} else {
throw new KeyNotFoundException(string.Format("\"{0}\" is not a window title which is available in the cache.", title));
}
}
#region Win32 API Functions
[DllImport("user32.dll")]
private static extern int EnumWindows(CallBack lpEnumFunc, int lParam);
[DllImport("user32.dll")]
private static extern int GetWindowText(int hWnd, StringBuilder lpString, int maxCount);
[DllImport("user32.dll")]
private static extern int GetWindowTextLength(int hWnd);
[DllImport("user32.dll")]
private static extern int IsWindow(int hWnd);
[DllImport("user32.lib")]
private static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
#endregion
}
Inside of the saveHWndHandler() method, I've marked the line were the debugger shows execution stops. Interestingly, there are usually ~300 window handles returned by EnumWindows(), and it always crashes on iteration number 45 or 46. The window handle it crashes on is a reasonable value, such as 12345.
According to MSDN, IsWindow() should return 0, if a window was not associated with the handle, not crash the thread.
Does anyone know why this is happening? There isn't a thrown exception, or any details in the Windows event log.
Thank you.
For those who don't want to figure out the buildCache() process works:
(1.) When buildCache() is called, the dictionary of <HWnd, Title> values is cleared.
(2.) The Win32 function EnumWindows() is called, which calls the saveHWndHandler() method for each window handle.
(3.) saveHWndHandler() will check if the current window handle still exists, the call another Win32 to function to get the window title from the handle.
(4.) The title and window handle are added to the dictionary.
I can't reproduce your issue, but a likely problem is that all of your P/Invoke signatures are wrong. HWND, LPARAM, and WPARAM data types need to at least be mapped to IntPtr in P/Invoke code.
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString,
int nMaxCount);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam,
IntPtr lParam);
You'll need to change your corresponding instance method signatures and usages to match these correct signatures.

FindWindow return 0 in Windows 7

I have a C# program. The program creates an Adobe Reader process and prints a PDF document. It works fine in Windows XP, but does not work in Windows 7. I have checked that the AcroRd32.exe path is correct in Windows 7. The FindWindow method always returns 0 in Windows 7.
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("User32.dll")]
public static extern IntPtr FindWindow(string ClassN, string WindN);
[DllImport("user32.dll", EntryPoint = "SendMessageA")]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("shell32.dll ")]
public static extern int ShellExecute(IntPtr hwnd, string lpszOp, string lpszFile, string lpszParams, string lpszDir, int FsShowCmd);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint WinExec(string lpCmdLine, uint uCmdShow);
public bool isAcrobatExsists(string acrobatLoc)
{
IntPtr currentHandle = getWindowHandlerByClass("AcrobatSDIWindow");
if (currentHandle != IntPtr.Zero)
{
return true;
}
return false;
}
private static IntPtr getWindowHandlerByClass(string className)
{
IntPtr currentHandle = FindWindow(className, null);
return currentHandle;
}
private static IntPtr getWindowHandlerByName(string appName)
{
IntPtr currentHandle = FindWindow(null, appName);
return currentHandle;
}
Findwindow can depend a great deal on how you are running the application. It sounds like you might be running it as a scheduled task or a windows service. These run in a different session than what the user's desktop window is in, so it won't see or be able to interact with them.
They introduced this change in Windows Vista, so applications that do this will work just fine in XP but fail in Windows Vista or later.
Here's a link from msdn about it: Application Compatibility: Session 0 isolation

How to show modeless owned dialog in .NET 1.1

I need to show a modeless dialog in .NET 1.1. The following code works in .NET 2.0 or higher:
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetActiveWindow();
private void ShowModelessOwnedDialog()
{
IntPtr wHnd = GetActiveWindow();
NativeWindow parent = NativeWindow.FromHandle(wHnd);
MyForm f = new MyForm();
f.Show(parent);
}
The call Show(IWin32Window) was introduced in .NET 2.0. Do you know how to trick this code to work in .NET 1.1? Maybe any unmanaged call?
Here is an article from way back in 1999, showing how you call SetWindowLong to accomplish this. My condolences to you for having to use .NET version 1.
This is the way to assign an owner to a managed form in .NET 1.1. I extracted the following code from #Dave Markle answer and the Show(IWin32Window) implemantation of .NET 2.0.
private void AssignOwner()
{
AssignOwner(this, GetActiveWindow());
}
private void AssignOwner(Form f, IntPtr ownerHandle)
{
if (ownerHandle == IntPtr.Zero) return;
NativeWindow parent = NativeWindow.FromHandle(ownerHandle);
GetWindowLong(new HandleRef(f, f.Handle), -8);
SetWindowLong(new HandleRef(f, f.Handle), -8, new HandleRef(parent, ownerHandle));
}
public static IntPtr GetWindowLong(HandleRef hWnd, int nIndex)
{
if (IntPtr.Size == 4)
{
return GetWindowLong32(hWnd, nIndex);
}
return GetWindowLongPtr64(hWnd, nIndex);
}
public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, HandleRef dwNewLong)
{
if (IntPtr.Size == 4)
{
return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
}
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]
public static extern IntPtr GetWindowLong32(HandleRef hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Auto)]
public static extern IntPtr GetWindowLongPtr64(HandleRef hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLongPtr32(HandleRef hWnd, int nIndex, HandleRef dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, HandleRef dwNewLong);
MSDN states that after creating the window ownership cannot be transferred.
Because creating the window occurs in Form constructor, this poses a problem for you.
However Raymond Chen says:
Ownership is a concept that relates top-level windows. A top-level window can optionally have an owner, which is also specified when you call CreateWindowEx, and which you can change by a complicated mechanism described in my talk.
I assume the talk in question is from PDC 05 but I can't be certain.
Did you give SetParent a try?
static extern void SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
There is a MessageBox.Show overload taking and IWin32Window in .net 1.1
http://msdn.microsoft.com/en-us/library/aa335416(v=VS.71).aspx
public static DialogResult Show(
IWin32Window owner,
string text,
string caption,
MessageBoxButtons buttons,
MessageBoxIcon icon,
MessageBoxDefaultButton defaultButton
);
And this and example of getting an IWin2Window here

Categories