I'm making a program that will shutdown a .exe app when F1 is pressed! I did it, but I'm trying to do it without having to focus on the form! How could I do that?
You can set up low level keyboard hook, it will notify your app with key press events. Check this article, it's almost 10 years old, but should give you a hint. Basically the key thing is to import native method SetWindowsHookEx and process key presses with your callback delegate. Last time I used it was on Windows 8.1, so I believe it's still actual for Windows 10.
For this case, you can use NotifyIcon component along with the form. Add a context menu with a shortcut key (F1 is not supported I think, you need modifiers) which then finds the PID and terminates that process.
Related
Windows 10 has setting "Show the touch keyboard when not in tablet mode and there's no keyboard attached", which allows Windows to show touch keyboard whenever you touch text box.
As Windows handles this logic rather poorly (it is easily broken in WPF applications), I would like to turn off this option for my application, which I'm trying to do by changing registry value EnableDesktopModeAutoInvoke, corresponding to this option (simple Registry.SetValue method). But there is an issue - touch keyboard application TabTip.exe for some reason doesn't really "hook up" changes in registry, and keeps showing touch keyboard until it is restarted. And vice versa - once I'm restoring registry value, I need to restart application to apply change.
And this is where main issue of such approach appears - with auto-invoke option enabled, once TabTip process starts, it immediately shows keyboard. Obviously I would not like such visual side-effects for my application logic.
Another point is that while changing this setting in usual way, via Windows Settings application, TabTip or any related applications or services are not restarted. Which means Settings application somehow manages to update TabTip process. I would really like to figure how it does this, and if I can reproduce same behavior in C#, but I have no idea how.
So, my question is - how can I programmatically change either EnableDesktopModeAutoInvoke registry value or "Show the touch keyboard when not in tablet mode and there's no keyboard attached" Windows option, and make TabTip application to accept this change, without any possible visual side-effects?
UPD:
I know that it is possible to make keyboard to ignore text box by creating custom text box with specific automation peer, but this would require to replace all text boxes in entire application, and always keep in mind that we need to use new text boxes, so this is not viable solution. I've tried to remove possibility to get automation peers for children of main window as well, but that doesn't work.
So I looked at lot of different implementations of the same
https://github.com/maximcus/WPFTabTip/blob/65b58e1900d3c21c9ea684e9f882088fe821586b/WPFTabTip/TabTip.cs
https://github.com/zhangtx2812/NewClient/blob/851f6dd8bc9c6389b70c7b5cd9384617a62a274e/Client.Helpers/Utils/KeyboardHelper.cs
https://github.com/Anneliese1989/Examintion/blob/2f974312d1ce0452a018bcaecf7bda753c818d9e/WPFTabTip/TabTip.cs
https://github.com/TransposonY/GestureSign/blob/11395ba6f18ea39b86f8e0a586b10a43f3c27568/GestureSign.CorePlugins/TouchKeyboard/TouchKeyboardUI.xaml.cs
https://github.com/microdee/mp.essentials/blob/d5832dee693839d55157d287d2459760b90b1d05/windows/WindowsLaunchOSKNode.cs
and most case one kills the process using
foreach (Process tabTipProcess in Process.GetProcessesByName(TabTipProcessName))
tabTipProcess.Kill();
or close the keyboard using
void closeKeyboard()
{
uint WM_SYSCOMMAND = 274;
uint SC_CLOSE = 61536;
IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
PostMessage(KeyboardWnd.ToInt32(), WM_SYSCOMMAND, (int)SC_CLOSE, 0);
}
So, I think what you have already are the best choices known
I have a shot in the dark for you...
Here's one way that it is possible TabTip is notified of registry changes by Windows Settings but not by you: If TabTip is using something like the WMI RegistryKeyChangeEvent class internally, it's possible that the TabTip application is only monitoring the parent registry key and not monitoring the key value you're actually changing (which is why TapTip not updated when you change the value). But, the Windows Settings application could be setting the whole key (and it's corresponding valueName and value) via something like SetExpandedStringValue, which would trigger the key change that TabTip could be watching.
The way to test for this would be to set the key, valueName, and value all at once programmatically, instead of just setting the value.
Not a great solution, but you could attempt to hook up to the showing event https://learn.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.inputpane
And immediately call a TryHide in the event of a show event to suppress it.
I'm trying to write an application that can reliably send key presses to another application.
The second app has a text field which opens when 9 is pressed.
Text can then be typed and then the text field is closed when Enter is pressed.
If I use SendKeys to try to do this the field does not open if I send 9, but if the field is already open my tool can send text ok, but then it does not close if I send an Enter.
I'm guessing this is because a lower-level interaction with the keyboard driver or similar is being used.
Is there a reliable way I can simulate actual keyboard input to the application from another C# app?
I have found a few potential solutions online but these are generally incomplete with either missing references etc. or missing code elsewhere.
I will continue to search and I will post the solution here if I find it!
is it an option to invoke on screen keyboard provided by os. your app, calling app will loose or cant track the key events, however if you open your second application and invove osk.exe, then the purpose of robust keyboard sending keys to an app could be fullfilled.
I explained this here
EDIT: ignoring on screen keyboard
You can try using RegisterHotKey to open the textpad on a specific sequence of key(s) and persist the handle in a instance variable. On the sequence of second hot key(s) you can close the textpad (you already know the handle)
there is a video explaining this
Hi I'm trying to make a simple program that read keys from keyboard even if my application is running in the background.
Situation
I want make a timer to help me in a game. I already have the program with the timer, the problem is I can not start the timer without switching of the game window to my app window. So I configured the game keyboard to release the keys F11, F12. Now in game this keys do nothing.
Problem
I built a windows forms containing a listener for keydown event and a conditional for F11. But when I trigger another window (eg the game window) my application no longer hears the keyboard, cuz it's in the background.
Question
How can I build a app that hears the keyboard, even if it's not active window?
You need to install a global, low-level keyboard hook using the SetWindowHookEx API call. Using the WH_KEYBOARD_LL hook will set your application up to intercept keyboard events at all times, even when your application is not active.
This post on MSDN shows an example of how to achieve something close to what you want from C#.
I'm using the Window's API RegisterHotKey function to run a macro when the F2 key is pressed while a specific application is open and focused.
The problem is, this is stopping the F2 key from working for other applications, such as Excel.
How can I prevent RegisterHotKey from stopping the default action?
I have a system tray application that uses the HotKeyManager class from this answer to register hotkeys. When a specific key is pressed (for example, F2), I use the Windows API to check if a closed-source application is open and focused, and if so send it a series of SendKeys.
From what I understand, you want your global hotkey to work only when one or more selected apps are focused. Can't you simply SendKeys the intercepted strokes if you determine that an incompatible app is in the foreground?
For example,
if (IsSpecificWindowFocused())
{
// Do work
}
else
{
// Resend the key to whatever window is current
SendKeys.Send("{F2}");
}
RegisterHotKey is global, so it is going to trap all of those keystrokes (in other words, I don't believe it is possible to do exactly what you ask).
However, this thread
Global Keyboard Hooks (C#)
talks about creating a keyboard message filter, which is (I believe) more like what you are going for.
To clarify:
RegisterHotKey is going to be best for things like tray apps and anywhere else where you want an OS wide keyboard short cut that doesn't rely on the app being in focus.
Application.AddMessageFilter() is what you want when you want consistent handling of a particular keystroke, but only when your app already has focus.
A way to do what you're describing and still stay in .NET would be to monitor what processes are running on the OS and only enable the global hook when your app is running.
I'm working on writing an application that straddles the line between C# and C/++ on Windows Mobile 6.1/6.5. We currently have a kiosk application running on our devices, and would like to add the ability to switch back and forth to a second kiosk application.
Our goal is to establish a global hot key that switches process windows (similar to the way that alt+tab works) whenever it is pressed. We already have both applications and I've written some code that switches the processes, but am having a rough time getting the global hot key portion of the project working.
From all of the reading that I've done, my understanding is that the best way to monitor global key presses is to link into the system message pump with the SetWindowsHookEx function in coredll.dll. Unfortunately, I've also read that this function isn't technically supported on the platform.
I also found some tutorials that suggested using a message map with the ON_WM_KEYUP/ON_WM_KEYDOWN macros in the MFC framework, but couldn't find any documentation specific to Windows Mobile. When I tried to use the documentation here, my device kept crashing.
Is there an accepted best practice for setting some kind of global key hook on the platform? If not, is there something that's at least technically supported?
Thanks in advance.
ReplyQuote
Why not use a RegisterHotKey call and use that to swap applications? IIRC the hardware buttons typically map to key codes starting at 0xC1 (193).
We actually ended up polling the GetAsyncKeyState function in coredll.dll on a separate thread. The thread monitors a specific key, and throws an event whenever it is pressed.
Because the event is executed on the key polling thread, you have to be sure to use a delegate to invoke its handler on the GUI thread when the event is thrown.
I would go for a keyboard hook, but only if RegisterHotKey didn't work for your particular scenario.
From all of the reading that I've done, my understanding is that the best way to monitor global key presses is to link into the system message pump with the SetWindowsHookEx function in coredll.dll. Unfortunately, I've also read that this function isn't technically supported on the platform.
Not technically supported, is correct in theory, but I've not seen a WM 6.5.* device that hasn't supported it in reality. Keyboard hooking is such an important feature of vertical market custom rugged WM device apps that it I think it just cannot be removed, for backwards compatibilty.
The enterprise side of the WM space is too important.