Disable touch visual feedback on windows 8.1 (programmatically) [Desktop App] - c#

I have a C# WPF application intended specifically for Win8.1 (a desktop app, NOT metro).
I want users to be able to use touch injections but I'm trying to disable the visualization feedback that windows creates for a Tap gesture Press Hold and Drag (like selecting multiple files on desktop) and other gestures (zooming scrolling etc).
After Searching the web for a long time I've found this post:
How do I disable Windows 8 touch contact visualizations for my application?
So I tried to do the same...
I tried this (Will put my Win32 class at the end)
public void DisableGestureVisualization()
{
const int SPI_SETCONTACTVISUALIZATION = 0x2019;
const int SPI_SETGESTUREVISUALIZATION = 0x201B;
ulong gv = 0;
Logger.Debug(!Win32.SystemParametersInfo(SPI_SETGESTUREVISUALIZATION, 0, ref gv, 0)
? #"Failed SystemParametersInfo SPI_SETGESTUREVISUALIZATION"
: #"Successfuly returned from SystemParametersInfo SPI_SETGESTUREVISUALIZATION");
Logger.Debug(!Win32.SystemParametersInfo(SPI_SETCONTACTVISUALIZATION, 0, ref gv, 0)
? #"Failed SystemParametersInfo SPI_SETCONTACTVISUALIZATION"
: #"Successfuly returned from SystemParametersInfo SPI_SETCONTACTVISUALIZATION");
}
And also this:
public void TryDisableWindowsVisualFeedback(IntPtr hWnd)
{
bool enable = false;
foreach (Win32.FEEDBACK_TYPE type in Enum.GetValues(typeof(Win32.FEEDBACK_TYPE)))
{
if (type == Win32.FEEDBACK_TYPE.FEEDBACK_MAX)
{
continue;
}
Logger.Debug(!Win32.SetWindowFeedbackSetting(hWnd, type, 0, 4, ref enable)
? #"Failed to SetWindowFeedbackSetting for " + type
: #"Successfuly returned from SetWindowFeedbackSetting for " + type);
}
}
And I call this from my WPF app like this:
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Window window = Window.GetWindow(this);
var wih = new WindowInteropHelper(window);
IntPtr hWnd = wih.Handle;
TryDisableWindowsVisualFeedback(hWnd);
}
This is my auxiliary Win32 class:
internal class Win32
{
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfo(
uint uiAction,
uint uiParam,
ref ulong pvParam,
uint fWinIni
);
public enum FEEDBACK_TYPE : uint
{
FEEDBACK_TOUCH_CONTACTVISUALIZATION = 1,
FEEDBACK_PEN_BARRELVISUALIZATION = 2,
FEEDBACK_PEN_TAP = 3,
FEEDBACK_PEN_DOUBLETAP = 4,
FEEDBACK_PEN_PRESSANDHOLD = 5,
FEEDBACK_PEN_RIGHTTAP = 6,
FEEDBACK_TOUCH_TAP = 7,
FEEDBACK_TOUCH_DOUBLETAP = 8,
FEEDBACK_TOUCH_PRESSANDHOLD = 9,
FEEDBACK_TOUCH_RIGHTTAP = 10,
FEEDBACK_GESTURE_PRESSANDTAP = 11,
FEEDBACK_MAX = 0xFFFFFFFF
}
[DllImport("user32.dll")]
public static extern bool SetWindowFeedbackSetting(
IntPtr hwnd,
FEEDBACK_TYPE feedback,
uint dwFlags,
uint size,
[In] ref bool configuration
);
}
Non of the above disabled the round gray tap visual feedback nor did it disable the small white circle that appears when holding and dragging.
I even tried using the C# example in the blog:
Windows.UI.Input.PointerVisualizationSettings.
GetForCurrentView().
IsContactFeedbackEnabled = false;
This code works for a metro app, so I tried This SO post and got the Windows namespace but when running the code I get
"An unhandled exception of type 'System.Exception' occurred in MyProg.exe
WinRT information: Element not found.
Additional information: Element not found."
From what I could figure out, the PointerVisualizationSettings is not supported from a desktop application so this way is doomed...
If anyone can help me with this issue, please do.
Thanks

I had a similar problem and I was able to remove my tap gesture feedback by adding
Stylus.IsTapFeedbackEnabled = "False" to my root window.

Your TryDisableWindowsVisualFeedback method looks like it has the wrong pinvoke signature so you may be setting the visual feedback instead of clearing it. The configuration argument is a BOOL* not a bool*, and BOOL is a 4 byte integer. You can fix this with the MarshalAs attribute:
[In , MarshalAs(UnmanagedType.Bool)] ref bool configuration
You can call GetWindowFeedbackSetting to confirm that it was set correctly.
With the right pinvoke and hWnd, SetWindowFeedbackSetting should work. I confirmed that it does for me in a native app. WPF handles touch a bit oddly. I wouldn't expect it to affect this, but I haven't looked at WPF in depth for several years.
For your other methods, the Windows.UI.Input classes are documented to work only in Windows Store apps, so errors calling them from a desktop app are expected. Under the covers they'll make the same changes as SetWindowFeedbackSetting.
Using SystemParametersInfo to affect global UI is overkill: you don't want to solve a local problem by causing a global one. That said, it would probably work if you fire change notifications. Using SetWindowFeedbackSetting to target just your window is a much better solution though.

I don't know if this would resolve the OP's original issue (or even makes a difference), but I can confirm that I have successfully disabled all touch related visual feedback for my own Control-derived class selectively with the following method (almost like the one suggested by the OP) - at least on my Windows 10 machine:
public class MyTouchControl: Control
{
// ...a lot of other touch related stuff going on...
enum FEEDBACK_TYPE
{
TOUCH_CONTACTVISUALIZATION = 1,
PEN_BARRELVISUALIZATION = 2,
PEN_TAP = 3,
PEN_DOUBLETAP = 4,
PEN_PRESSANDHOLD = 5,
PEN_RIGHTTAP = 6,
TOUCH_TAP = 7,
TOUCH_DOUBLETAP = 8,
TOUCH_PRESSANDHOLD = 9,
TOUCH_RIGHTTAP = 10,
GESTURE_PRESSANDTAP = 11
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWindowFeedbackSetting(IntPtr hWnd, FEEDBACK_TYPE feedback, int dwFlags, int size, ref int config);
void disableAllTouchVisualFeedback()
{
int enable = 0;
foreach (FEEDBACK_TYPE type in Enum.GetValues(typeof(FEEDBACK_TYPE)))
{
SetWindowFeedbackSetting(Handle, type, 0, 4, ref enable);
}
}
protected override void OnHandleCreated(EventArgs e)
{
disableAllTouchVisualFeedback();
base.OnHandleCreated(e);
}
}

Related

C# force register/overwrite hotkeys

I want to force register/overwrite hotkeys...so this code is working fine but it fail's when that hotkey already register for the other application...
so I want to overwrite hotkey is it possible?
[DllImport("user32", SetLastError=true)]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
[DllImport("user32", SetLastError = true)]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
enum KeyModifier
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
WinKey = 8
}
public ExampleForm()
{
InitializeComponent();
int id = 0; // The id of the hotkey.
RegisterHotKey(this.Handle, id, (int)KeyModifier.Shift, Keys.A.GetHashCode()); // Register Shift + A as global hotkey.
}
I agree with IInspectable (and obviously Raymond). You should avoid this. But if you absolutely must do this, I believe Windows Hooks using SetWindowHookEx is the way to go.
System level hooks are serious stuff, and care should be taken when implementing them, since they affect system's performance..
For details and working code look here and here.
Do note again: Its an overkill, and its like using a sledgehammer (or I would say Demolition hammer) to crack a nut. But sometimes you gotta do what you gotta do!

Determine if Windows 10 Touch Keyboard is Visible or Hidden

I am trying to find out if the windows 10 virtual touch keyboard is visible or not to know whether to open it or not from my application. THe following code has worked fine up until the latest Windows 10 update 15063 or possible the one right before it. Seems like Microsoft changed something with the window styles possibly but I can't figure it out.
public static bool IsKeyboardVisible()
{
IntPtr keyboardHandle = GetKeyboardWindowHandle();
// Specifies we wish to retrieve window styles.
int GWL_STYLE = -16;
//The window is disabled. See http://msdn.microsoft.com/en-gb/library/windows/desktop/ms632600(v=vs.85).aspx.
UInt32 WS_VISIBLE = 0x10000000;
UInt32 WS_DISABLED = 0x08000000;
UInt32 WS_POPUP = 0x80000000;
bool visible = false;
bool disabled = false;
if (keyboardHandle != IntPtr.Zero)
{
UInt32 style = GetWindowLong(keyboardHandle, GWL_STYLE);
visible = ((style & WS_VISIBLE) == WS_VISIBLE);
disabled = ((style & WS_DISABLED) == WS_DISABLED); // ref https://stackoverflow.com/questions/11065026/get-window-state-of-another-process
log.InfoFormat("style:{0:X4} visible:{1} disabled:{2}", style, visible, disabled);
}
return visible && !disabled ;
}
This is related to: Show touch keyboard (TabTip.exe) in Windows 10 Anniversary edition
I've done some research with Spy++ . Looks like the new keyboard in Fall Creators Update (ver. 1709) is hosted by another window. This window has Windows.UI.Core.CoreWindow class and Microsoft Text Input Application as its title.
The following code works for all Windows 10 versions including the new 1803 and older Windows versions as well (starting with Windows 8, I believe).
static class TouchKeyboard
{
public static bool GetIsOpen()
{
return GetIsOpen1709() ?? GetIsOpenLegacy();
}
private static bool? GetIsOpen1709()
{
var parent = IntPtr.Zero;
for (;;)
{
parent = FindWindowEx(IntPtr.Zero, parent, WindowParentClass1709);
if (parent == IntPtr.Zero)
return null; // no more windows, keyboard state is unknown
// if it's a child of a WindowParentClass1709 window - the keyboard is open
var wnd = FindWindowEx(parent, IntPtr.Zero, WindowClass1709, WindowCaption1709);
if (wnd != IntPtr.Zero)
return true;
}
}
private static bool GetIsOpenLegacy()
{
var wnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, WindowClass);
if (wnd == IntPtr.Zero)
return false;
var style = GetWindowStyle(wnd);
return style.HasFlag(WindowStyle.Visible)
&& !style.HasFlag(WindowStyle.Disabled);
}
private const string WindowClass = "IPTip_Main_Window";
private const string WindowParentClass1709 = "ApplicationFrameWindow";
private const string WindowClass1709 = "Windows.UI.Core.CoreWindow";
private const string WindowCaption1709 = "Microsoft Text Input Application";
private enum WindowStyle : uint
{
Disabled = 0x08000000,
Visible = 0x10000000,
}
private static WindowStyle GetWindowStyle(IntPtr wnd)
{
return (WindowStyle)GetWindowLong(wnd, -16);
}
[DllImport("user32.dll", SetLastError = false)]
private static extern IntPtr FindWindowEx(IntPtr parent, IntPtr after, string className, string title = null);
[DllImport("user32.dll", SetLastError = false)]
private static extern uint GetWindowLong(IntPtr wnd, int index);
}
Update: I updated the answer and the code to be compatible with Redstone 4 (v1803) as well.
I'm using this solution, and it is working on Windows 1607, 1709 and 1803 (check the Main method below on the code):
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
[ComImport, Guid("D5120AA3-46BA-44C5-822D-CA8092C1FC72")]
public class FrameworkInputPane
{
}
[ComImport, System.Security.SuppressUnmanagedCodeSecurity,
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("5752238B-24F0-495A-82F1-2FD593056796")]
public interface IFrameworkInputPane
{
[PreserveSig]
int Advise(
[MarshalAs(UnmanagedType.IUnknown)] object pWindow,
[MarshalAs(UnmanagedType.IUnknown)] object pHandler,
out int pdwCookie
);
[PreserveSig]
int AdviseWithHWND(
IntPtr hwnd,
[MarshalAs(UnmanagedType.IUnknown)] object pHandler,
out int pdwCookie
);
[PreserveSig]
int Unadvise(
int pdwCookie
);
[PreserveSig]
int Location(
out Rectangle prcInputPaneScreenLocation
);
}
static void Main(string[] args)
{
var inputPane = (IFrameworkInputPane)new FrameworkInputPane();
inputPane.Location(out var rect);
Console.WriteLine((rect.Width == 0 && rect.Height == 0) ? "Keyboard not visible" : "Keyboard visible");
}
}
}
It uses the IFrameworkInputPane interface (https://learn.microsoft.com/en-us/windows/desktop/api/shobjidl_core/nn-shobjidl_core-iframeworkinputpane)
I discovered yet another undocumented COM API that returns the position of the touch keyboard. It returns the bounds of the keyboard window or zeroes if the keyboard is hidden. I tested it in Windows 8.1, Windows 10 and Windows 10 Fall Creators Update and it works fine.
Now some bad news: in all versions prior to Fall Creators Update it only reports accurate results if the active window and the touch keyboard are located on the same monitor. If this is not the case - the API just returns the previous cached value. I'm guessing it has something to do with the fact that this API was meant to be used to calculate occlusion of the touch keyboard and your app's window. (It's called inside Windows::UI::ViewManagement::InputPane.get_OccludedRect() UWP API).
So if you don't care about supporting older versions or multi-monitor scenarios - use it. Otherwise I would suggest checking the Windows version and falling back to the previous method (GetIsOpenLegacy() from my other answer).
The API:
[ComImport, Guid("228826af-02e1-4226-a9e0-99a855e455a6")]
class ImmersiveShellBroker
{
}
[ComImport, Guid("9767060c-9476-42e2-8f7b-2f10fd13765c")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IImmersiveShellBroker
{
void Dummy();
IInputHostManagerBroker GetInputHostManagerBroker();
}
[ComImport, Guid("2166ee67-71df-4476-8394-0ced2ed05274")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IInputHostManagerBroker
{
void GetIhmLocation(out Rect rect, out DisplayMode mode);
}
[StructLayout(LayoutKind.Sequential)]
struct Rect
{
public int Left, Top, Right, Bottom;
}
enum DisplayMode
{
NotSupported = 0,
Floating = 2,
Docked = 3,
}
Usage example:
// do this once:
var brokerClass = new ImmersiveShellBroker();
var broker = (IImmersiveShellBroker)brokerClass;
var ihm = broker.GetInputHostManagerBroker();
Marshal.ReleaseComObject(broker);
// now ihm reference can be cached and used later:
Rect rect;
DisplayMode mode;
ihm.GetIhmLocation(out rect, out mode);
Note: looks like GetIhmLocation() always returns DisplayMode.NotSupported instead of the actual mode prior to Windows 10.

Lost Focus Windows Mobile

I created an application in C # to address some needs of an existing application in the enterprise. Recently we had to buy another application to support billing. These applications running is as follows:
1st Application-> 2 Application -> 3 Application
When I do "Process.Start" for the third application "it opens but after a few seconds it loses focus for the 1st Application. Anybody know how can I avoid this?
You need to know the window class and/or title and then can use FindWindow to get a window handle for the window:
[DllImport("coredll.dll", EntryPoint="FindWindowW", SetLastError=true)]
private static extern IntPtr FindWindowCE(string lpClassName, string lpWindowName);
Using the window handle you can change the window back to normal display using SetWindowPos:
[DllImport("user32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
In example, if the window has a class name of "App 3"
...
IntPtr handle;
try
{
// Find the handle to the window with class name x
handle = FindWindowCE("App 3", null);
// If the handle is found then show the window
if (handle != IntPtr.Zero)
{
// show the window
SetWindowPos(handle, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE);
}
}
catch
{
MessageBox.Show("Could not find window.");
}
To find the window's class and title, start the CE remote tool "CE Spy" (part of VS installation) when app 3 is started. Then browse thru the window list and look the app 3 window. Double click the entry in the list and you will get the class name and title of app 3.
Instead of the extra SetWindowPos you can also use the simple ShowWindow API:
[DllImport("coredll.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
enum ShowWindowCommands
{
Hide = 0,
Normal = 1,
ShowMinimized = 2,
Maximize = 3, // is this the right value?
ShowMaximized = 3,
ShowNoActivate = 4,
Show = 5,
Minimize = 6,
ShowMinNoActive = 7,
ShowNA = 8,
Restore = 9,
ShowDefault = 10,
ForceMinimize = 11
}
...
IntPtr handle;
try
{
// Find the handle to the window with class name x
handle = FindWindowCE("App 3", null);
// If the handle is found then show the window
if (handle != IntPtr.Zero)
{
// show the window
ShowWindow(handle, ShowWindowCommands.Normal);
}
}
catch
{
MessageBox.Show("Could not find window.");
}
For details about pinvoke of FindWindow and SetWindowPos see pinvoke.net and MSDN. Best book about Win32 programming is Charles Petzold's Programming Windows.
When you started the process you need the OS give some time to settle the app (let's say 1-3 seconds), before you change the window.

Use Chrome or Firefox in Winforms application ?

Is there a way to use Firefox or Chrome (whichever is installed) in a .NET application? I am not thinking about putting gecko or webkit engine in my application but using the browser installed on the system instead (just like the WebBrowser control uses IE). I heard that it is possible via ActiveX controls but didn't find any more info about it.
Well you could use user32.dll to set the parent window of the specified child window (here firefox or chrome).
This is what the result look likes:
First of all I have two small problems and 1 bigger one:
As you can see firefox is not maximized, therefore some content is missing (still looking for a way to fix that [help appriciated])
Because you have to start the process first and then set the parent of the window, Firefox is running outside of your application for a small amount of time.
The biggest problem: The program your are trying to "bind" to your application mustn't run when running your application, because it cannot set the parent of firefox to your program
MSDN for explanation of the methods: http://msdn.microsoft.com/en-us/library/windows/desktop/ff468919(v=vs.85).aspx
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, bool repaint);
//hwnd: A handle to the window | x: The new position of the left side of the window. | y: The new position of the top of the window.
//nWidth: The new width of the window. | nHeight: The new height of the window.
//repaint: Indicates whether the window is to be repainted. If this parameter is TRUE, the window receives a message. If the parameter is FALSE, no repainting of any kind occurs.
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
Process ffprocess = new Process();
private void openProgramAndSetParent()
{
string str = #"C:\Program Files\Mozilla Firefox\firefox.exe"; //Enter full path to Firefox or Chrome
ffprocess.StartInfo.FileName = str;
ffprocess.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
ffprocess.Start();
IntPtr ptr = IntPtr.Zero;
while ((ptr = ffprocess.MainWindowHandle) == IntPtr.Zero)
{
Application.DoEvents();
}
Thread.Sleep(1000);
SetParent(ffprocess.MainWindowHandle, panel1.Handle);
MoveWindow(ffprocess.MainWindowHandle, 0, 0, this.Width, this.Height -100, true);
}
private void Form1_Resize(object sender, EventArgs e)
{
try
{
MoveWindow(ffprocess.MainWindowHandle, 0, 0, this.Width, this.Height, true);
}
catch (Exception)
{}
}

Spell checking library for Windows Mobile 6.x

We are looking into how we can check the spelling of text entered by the user in an app we have developed.
Is there any standard APIs and libraries/dictionaries included in the Windows Mobile 6.x OS that can be used for this? Please point me in the rigth direction if there is.
Thank you in advance!
Windows Mobile 6 has Auto Correction and Auto Suggestion built in. You can enable and disable these from your app with the following PInvoke call.
public static class InputContext
{
private enum SHIC_FEATURE : uint
{
RESTOREDEFAULT = 0,
AUTOCORRECT = 1,
AUTOSUGGEST = 2,
HAVETRAILER = 3,
CLASS = 4
}
[DllImport("aygshell.dll")]
private static extern int SHSetInputContext(IntPtr hwnd, SHIC_FEATURE dwFeature, ref bool lpValue);
public static void SetAutoSuggestion(IntPtr handle, bool enable)
{
SHSetInputContext(handle, SHIC_FEATURE.AUTOSUGGEST, ref enable);
SHSetInputContext(handle, SHIC_FEATURE.AUTOCORRECT, ref enable);
}
}

Categories