#眉標=特別報導
#副標=Windows 7 Multi Touch程式開發
#大標=C# & WinForm開發觸控應用程式
#作者=文/圖 蔡宗翰


==<box>===========
程式1

const int SM_DIGITIZER = 94;
[DllImport("user32")]
static extern int GetSystemMetrics(int n);
bool SupportMultiTouch()
{
  int r = GetSystemMetrics(SM_DIGITIZER);
  if ((r & 0x40) != 0)
    return true;
  else
    return false;
}
==<end>==============






==<box>===========
程式2

override void WndProc(ref Message m)
{
  bool handled = true;
  switch (m.Msg)
  {
    case WM_GESTURENOTIFY:
      // 可在此呼叫SetGestureConfig
      break;
    case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
      // 可在此決定是否停用Flicks或其他功能
      break;
    case WM_GESTURE:
      handled = DecodeGesture(ref m);
      break;
    default:
      handled = false;
      break;
  }
  if (handled)
    m.Result = new IntPtr(1);
  else
    base.WndProc(ref m);
}
==<end>==============





==<box>===========
程式3

GESTURECONFIG gc = new GESTURECONFIG();
gc.dwID = 0;
gc.dwWant = GC_ALLGESTURES;
gc.dwBlock = 0; 
SetGestureConfig(this.Handle, 0, 1,
  ref gc, _gestureConfigSize);
==<end>==============






==<box>===========
程式4

[StructLayout(LayoutKind.Sequential)]
struct GESTUREINFO
{
  public int cbSize;
  public int dwFlags;	// GF_*
  public int dwID;	// GID_*
  public IntPtr hwndTarget;
  [MarshalAs(UnmanagedType.Struct)]
  internal POINTS ptsLocation;
  public int dwInstanceID;
  public int dwSequenceID;
  public Int64 ullArguments;
  public int cbExtraArgs;
}
==<end>==============





==<box>===========
程式5

const uint MOUSEEVENTF_FROMTOUCH
  = 0xff515700;
[DllImport("user32")]
static extern IntPtr GetMessageExtraInfo();
bool IsFromTouch()
{
  IntPtr p = GetMessageExtraInfo();
  return MOUSEEVENTF_FROMTOUCH ==
    ((uint)p & MOUSEEVENTF_FROMTOUCH);
}
==<end>==============





==<box>===========
程式6

[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetGestureInfo(
  IntPtr hGestureInfo,
  ref GESTUREINFO pGestureInfo);
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseGestureInfoHandle(
  IntPtr hGestureInfo);

bool DecodeGesture(ref Message m)
{
  bool handled = true;
  GESTUREINFO gi;
  gi = new GESTUREINFO();
  gi.cbSize = _gestureInfoSize;
  GetGestureInfo(m.LParam, ref gi);
  switch (gi.dwID)
  {
    case GID_ZOOM: //處理縮放
      break;
    case GID_PAN: //處理平移
      break;
    case GID_ROTATE: //處理旋轉
      break;
    case GID_TWOFINGERTAP: //處理兩指點擊
      break;
    case GID_PRESSANDTAP: //處理press & tap
      break;
    default:
      handled = false;
      break;
  }
  if (handled)
    CloseGestureInfoHandle(m.LParam);
  return handled;
}
==<end>==============







==<box>===========
程式7

[DllImport("user32")]
static extern bool SetProp(IntPtr hWnd,
  string lpString, IntPtr hData);
SetProp(this.Handle,
  "MicrosoftTabletPenServiceProperty",
  new IntPtr(0x10000));
==<end>==============




==<box>===========
程式8

const int TABLET_DISABLE_FLICKS
  = 0x00010000;
case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
  m.Result =
    (IntPtr)TABLET_DISABLE_FLICKS;
  break;
==<end>==============





==<box>===========
備註

前端使用者介面開發者關心的觸控技術與Silverlight 3.0的關係,可參考本期[技術專欄]中的「Silverlight 3多點觸控開發」文章,或是下一期開始在RUN!PC技術專欄中更多的探討。
==<end>==============