我必须开发一个C#应用程序,该应用程序需要利用高级手势来改善用户体验。为此,我需要获取信息
当用户调用某个手势时。
因为WndProc是.NET CE中的忌讳,所以我使用OpenNETCE的Application2和IMessageFilter类接收WM流量。
在我的MessageFilter中,我寻找WM_GESTURE消息,这就是
我被卡住了。
通过调用此函数,我只是没有得到任何有意义的结果:
https://msdn.microsoft.com/en-us/library/ee503217.aspx
BOOL GetGestureInfo(
HGESTUREINFO hGestureInfo
PGESTUREINFO pGestureInfo
);
以下是相关代码:
public class TestMessageFilter : IMessageFilter
{
[DllImport("coredll", SetLastError = true)]
public static extern bool GetGestureInfo(IntPtr hGesture, ref GESTUREINFO lGesture);
public static uint WM_GESTURE = 0x0119;
public bool PreFilterMessage(ref Microsoft.WindowsCE.Forms.Message m)
{
// ...
if (m.Msg == WM_GESTURE)
{
GESTUREINFO gi = new GESTUREINFO() {
cbSize = (uint)Marshal.SizeOf(typeof(GESTUREINFO))
};
bool success = GetGestureInfo(m.LParam, ref gi);
if (success)
{
// ...
}
else
{
int x = Marshal.GetLastWin32Error(); // => 87
}
}
// ...
}
[StructLayout(LayoutKind.Sequential)]
public struct POINTS
{
public short x;
public short y;
}
[StructLayout(LayoutKind.Sequential)]
public struct GESTUREINFO
{
public UInt32 cbSize;
public UInt32 dwFlags;
public UInt32 dwID;
public IntPtr hwndTarget;
public POINTS ptsLocation;
public UInt32 dwInstanceID;
public UInt32 dwSequenceID;
public UInt64 ullArguments;
public UInt32 cbExtraArguments;
}
}
它总是给我错误代码87。
ERROR_INVALID_PARAMETER
为什么不起作用?
什么无效
真让我发疯...
非常感谢。
编辑:
我发现这篇文章on the msdn forums使用IntPtr而不是
引用GestureInfo作为第二个参数。
[DllImport("coredll.dll")]
static extern int GetGestureInfo(IntPtr hGestureInfo, [In, Out] IntPtr pGestureInfo);
// ...
GESTUREINFO gi = new GESTUREINFO();
gi.cbSize = 48;
IntPtr outGI = Marshal.AllocHGlobal(48);
Marshal.StructureToPtr(gi, outGI, false);
bool bResult = (GetGestureInfo(lParam, outGI) == 1);
bool bHandled = false;
Marshal.FreeHGlobal(outGI);
Marshal.PtrToStructure(outGI, gi);
// ...
但这对我来说会导致相同的ERROR_INVALID_PARAMETER错误。
没有人有解决方案或其他方法来从C#获取GestureInfo吗?
最佳答案
我只有Windows Embedded Compact 7的经验,但与2013年的差别应该不大-您是否首先启用手势? (您可能是因为收到WM_GESTURE才这样做的,但无论如何这是代码):
[DllImport(User32Library)]
public static extern bool EnableGestures(IntPtr hWnd, GestureMask flags, uint scope);
[Flags]
public enum GestureMask : ulong
{
TGF_GID_PAN = 0x10,
TGF_GID_SCROLL = 0x100,
TGF_GID_HOLD = 0x200,
TGF_GID_SELECT = 0x400,
TGF_GID_DOUBLESELECT = 0x800,
TGF_GID_DIRECTMANIPULATION = 0x1000,
TGF_GID_ALL = TGF_GID_PAN | TGF_GID_SCROLL | TGF_GID_HOLD | TGF_GID_SELECT | TGF_GID_DOUBLESELECT,// | TGF_GID_DIRECTMANIPULATION,
}
我选择复制粘贴我们的工作示例;不记得是为了方便起见还是因为存在问题而将TGF_GID_DIRECTMANIPULATION排除在TGF_GID_ALL外
bool enabled = EnableGestures(Handle, Native.GestureMask.TGF_GID_ALL, 0);
GetGestureInfo的以下签名适用于我们的设备:
[DllImport("coredll.dll")]
public static extern bool GetGestureInfo(IntPtr hGestureInfo, ref GestureInfo pGestureInfo);
使用GestureInfo结构:
[StructLayout(LayoutKind.Sequential)]
public struct GestureInfo
{
/// <summary>
/// Specifies the size of the structure in bytes. This must be set to Marshal.SizeOf(typeof(GESTUREINFO))
/// </summary>
public uint Size;
/// <summary>
/// Gesture Flags
/// </summary>
public GestureState State;
/// <summary>
/// Gesture Id
/// </summary>
public GestureKind Kind;
/// <summary>
/// HWND of the target winndow
/// </summary>
public IntPtr TargetWindow;
/// <summary>
/// Coordinates of start of gesture
/// </summary>
public short LocationX;
/// <summary>
/// Coordinates of start of gesture
/// </summary>
public short LocationY;
/// <summary>
/// Gesture Instance Id
/// </summary>
public uint InstanceId;
/// <summary>
/// Gesture Sequence Id
/// </summary>
public uint SequenceId;
/// <summary>
/// Arguments specific to gesture
/// </summary>
public ulong Arguments;
/// <summary>
/// Size of extra arguments in bytes
/// </summary>
public uint ExtraArguments;
}
手势状态:
[Flags]
public enum GestureState : uint
{
/// <summary>
/// The gesture has no associated state
/// </summary>
None = 0,
/// <summary>
/// The gesture is the beginning of pan gesture
/// </summary>
Begin = 1,
/// <summary>
/// The gesture is the end of a pan gesture that will transition into a scroll gesture
/// </summary>
Inertia = 2,
/// <summary>
/// The gesture is the end of a pan gesture
/// </summary>
End = 4
}
和GestureKind:
/// <summary>
/// The kind of gesture.
/// </summary>
public enum GestureKind : uint
{
/// <summary>
/// The beginning of a gesture operation.
/// </summary>
Begin = 1,
/// <summary>
/// The end of a gesture operation.
/// </summary>
End = 2,
/// <summary>
/// A pan gesture.
/// </summary>
Pan = 4,
/// <summary>
/// A scroll gesture.
/// </summary>
Scroll = 8,
/// <summary>
/// A hold gesture.
/// </summary>
Hold = 9,
/// <summary>
/// A select gesture.
/// </summary>
Select = 10,
/// <summary>
/// A double-select gesture.
/// </summary>
DoubleSelect = 11,
/// <summary>
/// Direct manipulation.
/// </summary>
DirectManipulation = 12,
}
调用该方法的代码:
GestureInfo gesture = new GestureInfo();
gesture.Size = (uint)Marshal.SizeOf(typeof(GestureInfo));
bool result = GetGestureInfo(lParam, ref gesture);
我认为这与您的第一次尝试没有太大区别。而在MSDN示例中唯一与众不同的是48的硬编码大小(可能意味着读取任何ExtraArguments)。
我们确实选择了设置自定义窗口过程-但是我不明白为什么这种区别很重要。