2012-11-09 74 views
9

我有一個以.NET Framework 4爲目標的現有Windows Forms桌面應用程序,並且希望爲其添加Windows 8觸摸支持。將Windows 8觸摸支持添加到現有的WinForms應用程序

目前該程序在Windows 8中正常工作,我可能只是調整一些元素的大小,使其在觸摸設備上更加用戶友好。但是,添加手勢(例如在數據網格上捏縮放)以及滑動對其他元素的支持將大大提高應用程序在純觸摸環境中的現代感。

我投資的是Visual Studio 2012,它可以讓我定位.NET 4.5和新的Windows 8功能,但沒有人知道哪些資源可以幫助我更新我的應用程序?我特別關注以下內容:

  • 無法在我的非觸摸式開發機器上直接測試應用程序的觸摸功能。微軟的模擬器似乎只支持Metro應用程序。我聽說像Splashtop這樣的平板電腦應用程序可以幫助我(我有一個Android平板電腦),但是在這個特定場景中沒有看到具體的東西。
  • WinForms應用程序是否支持手勢。我將不得不將整個用戶界面升級到WPF才能正常工作? (如果我確實走這條路線,我相信我也可以瞄準Windows 7,因爲WPF 4支持多點觸控)
  • 在運行時檢測設備的觸摸支持並適當縮放/更改UI,類似於觸摸模式設置在微軟的Windows RT Office應用程序上。我不想只是派生的項目中添加的新功能
  • 觸摸交互的
  • 自動化測試

這不是一個詳盡的清單以任何手段,但我真的很感激那些任何意見誰可能在過去曾經進行類似的升級。

+0

如果你的目標WinRT中你將不得不做一個完全重寫,因爲WinRT中沒有的WinForms等同。 – mydogisbox

+1

@mydogisbox - 我沒有針對WinRT,只是想升級現有的WinForms桌面應用程序來支持觸控。我應該在我的問題上做得更清楚。感謝您的意見。 –

+0

[對於任何需要更新舊WinForms應用程序以充分利用Windows 10觸摸屏的人],請參閱[Sheng Jiang的回答](https://stackoverflow.com/a/25070182/199364)中的我的評論以獲取當前鏈接Windows 7 SDK獲取手勢示例('pinch-zoom'和'rotate')。確認C#解決方案適用於運行Windows 10 Pro的Microsoft Surface Pro(2017)。 – ToolmakerSteve

回答

6

檢測在運行時設備的觸摸支持是有問題的,因爲用戶可以連接觸摸設備隨時隨地。如果您在檢測到觸摸設備連接並且設備連接不穩定之後重新調整表格大小,您最終可能會自動調整大小。最好有一個穩定的接口用於所有輸入(例如使用功能區而不是小菜單欄)。如果您確實想要檢測觸摸設備,則可以使用SM_DIGITIZER調用GetSystemMetrics。

Windows窗體不支持手勢(2005年凍結功能)。但是,由於默認觸摸處理程序翻譯涉及鼠標點擊,因此表單控件仍然可以使用觸摸輸入。如果您想擁有自己的觸摸處理程序,由於觸摸輸入以Windows消息的形式發送,因此您可以覆蓋表單或控件的WndProc函數來處理手勢消息。有關示例代碼,請在Windows 7 SDK中檢查Windows Touch Samples

要編寫觸摸功能的測試代碼,您可以調用InjectTouchInput來模擬觸摸輸入。完整的樣本可在Input: Touch injection sample找到。

+0

如何給winforms添加觸摸__since已被回答_購買LIEW HON CHIN的論文:http://portal.fke.utm.my/libraryfke/files/1387_LIEWHONCHIN2011.pdf,請參閱下面的答案。 – FastAl

+0

@FastAl - 謝謝,但論文作者使用了上面提到的相同的Windows API。我認爲上面鏈接的MSDN頁面提供了更好的背景和示例。 –

+1

@Daver,謝謝,但任何人都可以提供鏈接的例子?請注意,在鏈接的頁面底部有5個用戶評論,抱怨缺少完整的示例!我真的想讓那個頁面爲C#示例提供一個完整的可下載.sln文件 - _soooo_很多東西只是缺失,我知道微軟可能必須有一個 - 甚至有截圖!我只希望我錯過了它。 (一個用戶評論提到的note-download?id = 6450已經死了)。缺乏這一點,Liew的complete.Net代碼很好(C#用戶可以在telerik.com上轉換)。 – FastAl

2

觸摸應該或多或少的「只是工作」,但當然,按鈕將需要更大等。另請參閱here更復雜的手勢,而不僅僅是觸摸。

6

您可以使用組件1中的TouchToolkit for WinForms。不過,我認爲你必須重寫你的應用程序才能使用這些組件。

enter image description here

+0

獲得賞金,因爲這是最好的答案。謝謝! – SSS

+0

TouchToolkit鏈接現在導致「404未找到」。 – ToolmakerSteve

5

關於對評論。「無力直接測試我的非接觸式的開發機器上的應用程序的觸摸功能的Microsoft模擬器似乎只支持城域應用」 - 我能夠運行模擬器,轉到在模擬器中運行桌面,並在模擬觸摸輸入時運行任何應用程序 - 這包括WinForms應用程序。

因爲WinForms只是WinAPI原生UI API的一個包裝 - 您可以使用p/Invoke來使用我認爲在Vista/Windows 7時間框架中添加的touch API。主要是WM_TOUCHWM_GESTURE消息。有很多p/invoking和使用protected override void WndProc(ref Message m)的例子,這些是你需要處理觸摸的主要事情。除此之外 - 默認情況下,觸摸輸入在不作爲觸摸處理時會自動提升爲鼠標事件,因此很多事情都可以使用。

1

到的WinForms添加手勢支持 - 在這裏解決:

http://portal.fke.utm.my/libraryfke/files/1387_LIEWHONCHIN2011.pdf

'Imports System.Security.Permissions 
'Imports System.Runtime.InteropServices 


    Private first_point As New Point() 
    Private second_point As New Point() 
    Private iArguments As Integer = 0 
    Private Const ULL_ARGUMENTS_BIT_MASK As Int64 = &HFFFFFFFFL 
    Private Const WM_GESTURENOTIFY As Integer = &H11A 
    Private Const WM_GESTURE As Integer = &H119 
    Private Const GC_ALLGESTURES As Integer = &H1 
    Private Const GID_BEGIN As Integer = 1 
    Private Const GID_END As Integer = 2 
    Private Const GID_ZOOM As Integer = 3 
    Private Const GID_PAN As Integer = 4 
    Private Const GID_ROTATE As Integer = 5 
    Private Const GID_TWOFINGERTAP As Integer = 6 
    Private Const GID_PRESSANDTAP As Integer = 7 
    Private Const GF_BEGIN As Integer = &H1 
    Private Const GF_INERTIA As Integer = &H2 
    Private Const GF_END As Integer = &H4 
    Private Structure GESTURECONFIG 
    Public dwID As Integer 
    Public dwWant As Integer 
    Public dwBlock As Integer 
    End Structure 
    Private Structure POINTS 
    Public x As Short 
    Public y As Short 
    End Structure 
    Private Structure GESTUREINFO 
    Public cbSize As Integer 
    Public dwFlags As Integer 
    Public dwID As Integer 
    Public hwndTarget As IntPtr 
    <MarshalAs(UnmanagedType.Struct)> 
    Friend ptsLocation As POINTS 
    Public dwInstanceID As Integer 
    Public dwSequenceID As Integer 
    Public ullArguments As Int64 
    Public cbExtraArgs As Integer 
    End Structure 
    <DllImport("user32")> _ 
    Private Shared Function SetGestureConfig(ByVal hWnd As IntPtr, ByVal dwReserved As Integer, ByVal cIDs As Integer, ByRef pGestureConfig As GESTURECONFIG, ByVal cbSize As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean 
    End Function 
    <DllImport("user32")> 
    Private Shared Function GetGestureInfo(ByVal hGestureInfo As IntPtr, ByRef pGestureInfo As GESTUREINFO) As <MarshalAs(UnmanagedType.Bool)> Boolean 
    End Function 
    Private _gestureConfigSize As Integer 
    Private _gestureInfoSize As Integer 
    <SecurityPermission(SecurityAction.Demand)> 
    Private Sub SetupStructSizes() 
    _gestureConfigSize = Marshal.SizeOf(New GESTURECONFIG()) 
    _gestureInfoSize = Marshal.SizeOf(New GESTUREINFO()) 
    End Sub 
    <PermissionSet(SecurityAction.Demand, Name:="FullTrust")> 
    Protected Overrides Sub WndProc(ByRef m As Message) 
    Dim handled As Boolean 
    Select Case m.Msg 
     Case WM_GESTURENOTIFY 
     Dim gc As New GESTURECONFIG() 
     gc.dwID = 0 
     gc.dwWant = GC_ALLGESTURES 
     gc.dwBlock = 0 
     Dim bResult As Boolean = SetGestureConfig(Handle, 0, 1, gc, _gestureConfigSize) 
     If Not bResult Then 
      Throw New Exception("Error in execution of SetGestureConfig") 
     End If 
     handled = True 
     Case WM_GESTURE 
     handled = DecodeGesture(m) 
     Case Else 
     handled = False 
    End Select 
    MyBase.WndProc(m) 
    If handled Then 
     Try 
     m.Result = New IntPtr(1) 
     Catch excep As Exception 
     Debug.Print("Could not allocate result ptr") 
     Debug.Print(excep.ToString()) 
     End Try 
    End If 
    End Sub 
    Private Function DecodeGesture(ByRef m As Message) As Boolean 
    Dim gi As GESTUREINFO 
    Try 
     gi = New GESTUREINFO() 
    Catch excep As Exception 
     Debug.Print("Could not allocate resources to decode gesture") 
     Debug.Print(excep.ToString()) 
     Return False 
    End Try 
    gi.cbSize = _gestureInfoSize 
    If Not GetGestureInfo(m.LParam, gi) Then 
     Return False 
    End If 
    Select Case gi.dwID 
     Case GID_BEGIN, GID_END 
     Case GID_TWOFINGERTAP 
     'Receipt.Show() 
     'Invalidate() 
     Case GID_ZOOM 
     Select Case gi.dwFlags 
      Case GF_BEGIN 
      iArguments = CInt(Fix(gi.ullArguments And 
      ULL_ARGUMENTS_BIT_MASK)) 
      first_point.X = gi.ptsLocation.x 
      first_point.Y = gi.ptsLocation.y 
      first_point = PointToClient(first_point) 
      Case Else 
      second_point.X = gi.ptsLocation.x 
      second_point.Y = gi.ptsLocation.y 
      second_point = PointToClient(second_point) 
      RaiseEvent GestureHappened(Me, New GestureEventArgs With {.Operation = Gestures.Pan, .FirstPoint = first_point, .SecondPoint = second_point}) 
      'Invalidate() 
      'MsgBox("zoom") 
     End Select 
     Case GID_PAN 
     Select Case gi.dwFlags 
      Case GF_BEGIN 
      first_point.X = gi.ptsLocation.x 
      first_point.Y = gi.ptsLocation.y 
      first_point = PointToClient(first_point) 
      Case Else 
      second_point.X = gi.ptsLocation.x 
      second_point.Y = gi.ptsLocation.y 
      second_point = PointToClient(second_point) 
      RaiseEvent GestureHappened(Me, New GestureEventArgs With {.Operation = Gestures.Pan, .FirstPoint = first_point, .SecondPoint = second_point}) 
      'Invalidate() 
      'MsgBox("pan") 
     End Select 
     Case GID_PRESSANDTAP 
     'If gi.dwFlags = GF_BEGIN Then 
     ' Invalidate() 
     'End If 
     Case GID_ROTATE 
     'Select Case gi.dwFlags 
     ' Case GF_BEGIN 
     ' iArguments = 0 
     ' Case Else 
     ' first_point.X = gi.ptsLocation.x 
     ' first_point.Y = gi.ptsLocation.y 
     ' first_point = PointToClient(first_point) 
     ' Invalidate() 
     'End Select 
    End Select 
    Return True 
    End Function 


    Public Enum Gestures 
    Pan 
    Zoom 
    End Enum 

    Public Class GestureEventArgs 
    Inherits EventArgs 
    Public Property Operation As Gestures 
    Public Property FirstPoint As Point 
    Public Property SecondPoint As Point 
    End Class 

    Public Event GestureHappened(sender As Object, e As GestureEventArgs) 
+0

不幸的是,pdf鏈接已經死亡。你如何使用上面的代碼?我的第一個猜測是將所有這些行放入類定義中。那又怎麼樣? [我正在嘗試添加一箇舊的WinForms應用程序的捏放大。] – ToolmakerSteve

+0

沒關係。在[Sheng Jiang的回答](https:// stackoverflow。com/a/25070182/199364) - Windows 7 SDK Touch Samples包含完整的C#解決方案,實現捏放大和旋轉手勢。該示例原樣運行在運行Windows 10的Microsoft Surface Pro(2017)上,因此我需要更新舊的WinForms應用程序:) – ToolmakerSteve

相關問題