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.
Related
I'm trying to create an application that will process selected text when a keyboard shortcut is pressed. I used part of this method to get the currently selected text (and there seems to be no other way to get the selected text from any application:
string GetSelectedText()
{
var oldClip = Clipboard.GetText();
SendKeys.SendWait("^c");
string selection = Clipboard.GetText();
Clipboard.SetText(oldClip); // preserve clipboard
return selection;
}
My first thought was to use a system tray icon. When clicked, the icon would use the above method to get the current selection, and process it. However, using the clipboard like that requires the application to be in focus, whereas clicking a system tray icon brings the icon into focus before the method can run.
My next thought was to use a global keyboard shortcut. I came across this article about getting a global hotkey, and it could in fact listen to keyboard combinations, but only within one app, which is not what I want - I want to listen to the keyboard shortcut across any app.
I have already read this article (which came from this answer) which does manage to listen for keys across any app but only manages to listen to one key at a time (e.g. a single LControl, or Shift, or C, etc).
My question here is: How can I listen for a certain combination of keys, no matter what application is in focus, and execute the method above to get the current selection?
If there is a better way to retrieve the current selection, or if it can be done when the application is not in focus, answers explaning how it is possible are also appreciated; the main focus, however, is listening for a keyboard combination across all applications.
I ended up using the library that Chris Dunaway mentioned, MouseKeyboardLibrary.
As you may have seen in the comment thread where he brought it up, it initially didn't work for me. It turned out that the library didn't work for me because of an invalid module IntPtr, so I changed the library to use IntPtr.Zero where it previously used Marshal to get the module pointer, which made it work as expected.
I have a WPF application that, due to hardware constraints, has to run on Windows 7 Standard Embedded. The device is touch enabled and I am taking advantage of that in the way that I am building the application.
One of the problems that I have is that whenever the user touches the screen, a small "pointer" appears showing where the user has touched. This can apparently be turned on and off at a system level (http://windows.microsoft.com/en-US/windows-vista/Turn-the-touch-pointer-on-or-off) however ideally I want to turn it off at a WPF application/form level so that the user is not having to disable and enable the cursor each time they go in and out of the application.
Does anybody have any ideas as to how this can be achieved? I have tried searching various combinations of Windows 7, Touch, Pointer etc. but bar the above article I only ever seem to come back with how to enable touch events.
I should also point out that the hardware constraints currently rule out any option of upgrading to Windows 8, 8.1 or 10 so please do not consider this in any answer you may have.
Thanks.
Set the following properties of the Window to false...
Stylus.IsTapFeedbackEnabled
Stylus.IsTouchFeedbackEnabled
Stylus.IsPressAndHoldEnabled
Stylus.IsFlicksEnabled
They are probably not all required; but this worked for me.
How can I create a window which is fully apparent to the user but is not visible in screenshots. I know that this is possible since Neo SafeKeys (an onscreen keyboard to defeat keyloggers) does not appear in the screenshots taken by keylogging software I installed.
To give you an idea, the window is fully visible to the user, however when a screenshot is taken, the Neo SafeKeys window does not appear at all (as if it does not even exist).
Neo SafeKeys states that it uses an invisible protection layer above the window to protect against screenshots. I have searched all over the internet to see how can I reproduce this, to no avail. Does anybody know how this can be performed (windows which is visible to user but invisible in screenshots)?
What you can do is you can prevent the PrtScn key from doing anything when pressed. Take a look at this article while shows you how to do this.
What this article is doing is clearing out the clipboard. What you can do instead is capture the screen image and digitally remove your application, then put the revised image on the clipboard, thus giving the "Effect" of making your window transparent.
Also, you might want to look at this SO question which gives an alternative way to make your window just appear "blue", though its not easy to do.
Does anybody know how this can be performed (windows which is visible to user but invisible in screenshots)?
Use DirectX to render directly to the device.
In your C# application you can set up a global hook to monitor keyboard events. Then your application becomes the global handler for print screens. Now if another application managed screen prints natively, can't stop that, but anything running through windows, you can get at.
The WM_KEYBOARD_LL hook is one of the few global hooks that can be used in managed code because it doesn't require a DLL to be injected into every target.
For some code you can visit here:
Adam's Blog
Keep in mind that these are global hooks so you want to make sure nothing else (other applications) are effected. I've used these in the past as we hosted showing a power point in an application we worked on. Basically we didn't want the user to invoke any powerpoint menus or keyboard short cuts so we used a global hook. We always checked to see whether the users was in a certain area (screen) and in our application, otherwise we would effect other applications functionality (including our own!)
Microsoft Information:
Hooks Overview
There's this.....
visual cryptography
live example here
But this could be easily coded against by taking multiple screenshots and laying them overeachother and such...
If you are using Windows, and you can avoid that screenlogging happens, you can implement a nice solution like a virtual desktop to embed your process into it. When a process is running inside a virtual desktop it is possible to bypass an screenlogger tool that runs over win32 Api.
Check out this article so you can sneak a peek how to implement a nice solution to scape from screen and keyboard monitoring.
http://www.codeproject.com/Articles/7392/Lock-Windows-Desktop?fid=62485&select=3139662&fr=101#xx0xx
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 have what seems to be a common problem. I am running Windows 7 Home Premium on one of the most awesomest computers (when it was bought last year) and certain visual effects just automatically turn themselves off.
My average user experience rating is high, so it doesn't explain why this happens. The only feature that ever gets turned off is the 'Show window contents while dragging' option. And it really annoys me.
There are currently no working solutions to this problem online. Other than to "there must be a conflict with another app installed on your machine."
And yes, I do know what app is causing this conflict. It's my bloody Internet Provider's software - you know... that app that you absolutely MUST have open at all times when you're connected to the net.
So, I had a thought. What if I could subscribe to an event so that my app that runs in the background will detect when this 'show window contents while dragging' option is turned off - and then my app will simply turn it back on again.
When I do this manually, it seems to stay in effect for about an hour or two, then it gets switched off again.
Is it possible to handle these types of events, and re-start certain visual effect features? If so, are there any resources on this?
I have not been able to find anything on this sibject yet.
Yes the WM_SETTINGSCHANGE message is sent to all windows when a system setting is changed. Then you can call SystemParametersInfo with SPI_GETDRAGFULLWINDOWS to determine if the "Show window contents while dragging" is disabled and use SPI_SETDRAGFULLWINDOWS to enable it.
So all that you will need to do is create an application with a form (that can even stay hidden) and override the forms WndProc and handle the WM_SETTINGSCHANGE message and call SystemParametersInfo using p/Invoke. The p/Invoke definition for SystemParamtersInfo is available at pinvoke.net
Altough what may be easier is change security on the HKCU\Control Panel\Desktop\DragFullWindows registry value so that it can't be changed.