Wednesday, February 3, 2010

Enabling and disabling Press and Hold behavior in tabletPCs using WPF

The default behavior of tablet PCs when Pressing the stylus and holding it, is to show a circular animation after a short period which stays visible as a ring for another short period then disappears. If the stylus is lifted during the period the ring is visible, windows will send a right button up event.
It is possible to enable and disable this behavior in WPF by calling three older functions using the PInvoke API.
The three functions involved are
- GlobalAddAtom
- SetProp
- GetProp

This is part of a class that disables the right click behavior for the main application window

//Include these name spaces
using System.Runtime.InteropServices;
using System.Windows.Interop;

public partial class Window1 : Window
{
[DllImport("Kernel32.dll")]
static extern ushort GlobalAddAtom(string lpString);
//ATOM GlobalAddAtom(LPCTSTR lpString);

[DllImport("Kernel32.dll")]
static extern ushort GlobalDeleteAtom(ushort nAtom);
//ATOM GlobalDeleteAtom(ATOM nAtom);

[DllImport("user32.dll")]
static extern int SetProp(IntPtr hWnd, string lpString, int hData);
//BOOL SetProp(HWND hWnd, LPCTSTR lpString, HANDLE hData);

[DllImport("user32.dll")]
static extern int RemoveProp(IntPtr hWnd, string lpString);
//HANDLE RemoveProp(HWND hWnd, LPCTSTR lpString);

ushort pressAndHoldAtomID;
string pressAndHoldAtomStr = "MicrosoftTabletPenServiceProperty";
IntPtr mainWindowHandle;

private void Window_ContentRendered(object sender, EventArgs e) {
// Get the Tablet PC atom ID
pressAndHoldAtomID = GlobalAddAtom(pressAndHoldAtomStr);
if (pressAndHoldAtomID == 0)
MessageBox.Show("GlobalAddAtom failed");
else {
//the next function must be called after the window has
// been rendered, otherwise it returns 0
mainWindowHandle =new
WindowInteropHelper(Application.Current.MainWindow).Handle;
int result = SetProp(
mainWindowHandle, pressAndHoldAtomStr, 1);
}
}

private void Window_Closing(
object sender, System.ComponentModel.CancelEventArgs e)
{
if (pressAndHoldAtomID != 0) {
int result = RemoveProp(
mainWindowHandle, pressAndHoldAtomStr);
GlobalDeleteAtom(pressAndHoldAtomID);
}
}