我有一个针对.NET Framework 4的现有Windows窗体桌面应用程序,并希望为其添加Windows 8触摸支持。
目前该程序在Windows 8中运行良好,我可能只是调整一些元素的大小,使其在触摸设备上更加用户友好。但是,添加手势(例如数据网格上的双指缩放)以及滑动对其他元素的支持将大大有助于在纯触摸环境中使应用程序更加现代化。
我正在投资Visual Studio 2012,这将让我以.NET 4.5和新的Windows 8功能为目标,但有没有人知道任何可以帮助我更新我的应用程序的资源?我特别关注以下内容:
这绝不是一个详尽无遗的清单,但我真的很感谢那些可能在过去接触过类似升级的人的建议。
答案 0 :(得分:6)
您可以使用组件1中的TouchToolkit for WinForms。但是我认为您必须重写您的应用程序才能使用这些组件。
答案 1 :(得分:6)
在运行时检测设备的触摸支持是有问题的,因为用户可以随时连接触摸设备。如果在检测到触摸设备连接后调整表单大小并且设备的连接不稳定,则最终可能会出现一个不断调整自身大小的表单。最好为所有输入设置一个稳定的接口(例如,使用功能区而不是小菜单栏)。如果您确实想要检测触摸设备,可以使用SM_DIGITIZER调用GetSystemMetrics。
Windows窗体不支持手势(2005年冻结的功能)。但是,表单控件仍然可以使用触摸输入,因为默认触摸处理程序转换触摸鼠标单击。如果您想拥有自己的触摸处理程序,因为触摸输入是以Windows消息的形式发送的,您可以覆盖表单或控件的WndProc函数来处理手势消息。有关Windows 7 SDK中的示例代码检查Windows Touch Samples。
要编写触摸功能的测试代码,可以调用InjectTouchInput来模拟触摸输入。可以在Input: Touch injection sample找到完整的样本。
答案 2 :(得分:5)
关于&#34的评论;无法在我的非触摸式开发机器上直接测试应用程序的触摸功能。微软的模拟器似乎只支持Metro应用程序" - 我能够运行模拟器,在模拟器中转到桌面并在模拟触摸输入的同时运行任何应用程序 - 包括WinForms应用程序。
由于WinForms只是WinAPI本机UI API的包装器 - 您可以使用p / Invoke来使用我认为是在Vista / Windows 7时间范围内添加的触摸API。主要是WM_TOUCH和WM_GESTURE消息。 p / Invoking和使用protected override void WndProc(ref Message m)
有很多例子,这些是你需要处理触摸的主要内容。除此之外 - 触摸输入默认情况下会自动提升为鼠标事件,而不是触摸处理,所以很多事情都可以正常工作。
答案 3 :(得分:2)
触摸应该或多或少“正常工作”,但当然,按钮需要更大等。另请参阅here了解更复杂的手势,而不仅仅是触摸。
答案 4 :(得分: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)