#眉標=特別報導 #副標=Windows 7 Multi Touch程式開發(2) #大標=觸控應用程式範例實作 #作者=文/圖 蔡宗翰 ============= 程式1 [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool RegisterTouchWindow( IntPtr hWnd, ulong ulFlags); [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool UnregisterTouchWindow( IntPtr hWnd); [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool IsTouchWindow( IntPtr hWnd, IntPtr pulFlags); void OnLoadHandler(Object sender, EventArgs e) { try { if (!RegisterTouchWindow(this.Handle, 0)) { // 無法註冊視窗以取得 WM_TOUCH 訊息 } } catch (Exception exception) { // RegisterTouchWindow API 不存在 } } ================ ============= 程式2 [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetTouchInputInfo( IntPtr hTouchInput, int cInputs, [In, Out] TOUCHINPUT[] pInputs, int cbSize); [DllImport("user32")] [return: MarshalAs(UnmanagedType.Bool)] static extern void CloseTouchInputHandle( IntPtr lParam); override void WndProc(ref Message m) { bool handled; switch (m.Msg) { case WM_TOUCH: handled = DecodeTouch(ref m); break; default: handled = false; break; } // 下略 } bool DecodeTouch(ref Message m) { int inputCount = LoWord(m.WParam.ToInt32()); TOUCHINPUT[] inputs; inputs = new TOUCHINPUT[inputCount]; if (!GetTouchInputInfo(m.LParam, inputCount, inputs, touchInputSize)) { return false; } // 中略 CloseTouchInputHandle(m.LParam); return handled; } ================ ============= 程式3 [StructLayout(LayoutKind.Sequential)] struct TOUCHINPUT { public int x; public int y; public System.IntPtr hSource; public int dwID; public int dwFlags; public int dwMask; public int dwTime; public System.IntPtr dwExtraInfo; public int cxContact; public int cyContact; } ================ ============= 表1:dwFlags對應表 Flag Value TOUCHEVENTF_MOVE 0x0001 TOUCHEVENTF_DOWN 0x0002 TOUCHEVENTF_UP 0x0004 TOUCHEVENTF_INRANGE 0x0008 TOUCHEVENTF_PRIMARY 0x0010 TOUCHEVENTF_NOCOALESCE 0x0020 TOUCHEVENTF_PALM 0x0080 (資料來源:http://msdn.microsoft.com/library/dd317334.aspx)================ ============= 程式4 event EventHandler Touchdown; event EventHandler Touchup; event EventHandler TouchMove; bool DecodeTouch(ref Message m) { // 上略 for (int i = 0; i < inputCount; i++) { TOUCHINPUT ti = inputs[i]; EventHandler handler=null; if ((ti.dwFlags & TOUCHEVENTF_DOWN)!=0) handler = Touchdown; else if ((ti.dwFlags & TOUCHEVENTF_UP)!=0) handler = Touchup; else if ((ti.dwFlags & TOUCHEVENTF_MOVE)!=0) handler = TouchMove; if (handler != null) { WMTouchEventArgs te = new WMTouchEventArgs(); // 中略,將TOUCHINFO 轉換為 WMTouchEventArgs handler(this, te); handled = true; } } CloseTouchInputHandle(m.LParam); return handled; } ================ ============= 程式5 void OnTouchDownHandler(object sender, WMTouchEventArgs e) { Debug.Assert(ActiveStrokes.Get(e.Id) == null); Stroke newStroke = new Stroke (); newStroke.Color = touchColor.GetColor( e.IsPrimaryContact); newStroke.Id = e.Id; ActiveStrokes.Add(newStroke); } ================ ============= 程式6 void OnTouchMoveHandler(object sender, WMTouchEventArgs e) { Stroke stroke = ActiveStrokes.Get(e.Id); Debug.Assert(stroke != null); stroke.Add(new Point(e.LocationX, e.LocationY)); Graphics g = this.CreateGraphics(); stroke.DrawLast(g); } ================ ============= 程式7 void OnTouchUpHandler(object sender, WMTouchEventArgs e) { Stroke stroke = ActiveStrokes.Remove(e.Id); Debug.Assert(stroke != null); FinishedStrokes.Add(stroke); Invalidate(); } ================