我在 Windows CE 5.0 上运行的 .NET CF 2.0 应用程序中遇到了一些奇怪的行为。
我有一个定期更新控件的计时器,该控件还可以接收来自用户的点击并按住手势(在鼠标按下处理程序中)。我发现,当 TAH 开始(但在它退出之前)时,一个计时器事件可以开始处理,该事件在执行中途抢占鼠标按下处理程序。
据我的研究告诉我,这不是正常行为,我只是误解了计时器/事件吗?难道仅仅是 SHRecognizeGesture 正在调用 Application.DoEvents 的等价物吗?
无论如何,有没有人有一个“好”的方法来修复这个例子,这样当应用程序检查 TAH 时,计时器委托不会“滴答”。
请参阅下面的示例程序来说明此问题(点击并按住列表框下方的空白区域以生成日志消息)。
提前致谢。
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace DeviceApplication1
{
public class BugExample : Control
{
[Flags]
internal enum SHRGFLags
{
SHRG_RETURNCMD = 0x00000001,
SHRG_NOTIFYPARENT = 0x00000002,
SHRG_LONGDELAY = 0x00000008,
SHRG_NOANIMATION = 0x00000010,
}
[DllImport("aygshell.dll")]
private extern static int SHRecognizeGesture(ref SHRGINFO shrg);
private struct SHRGINFO
{
public int cbSize;
public IntPtr hwndClient;
public int ptDownx;
public int ptDowny;
public int dwFlags;
}
public bool TapAndHold(int x, int y)
{
SHRGINFO shrgi;
shrgi.cbSize = 20;
shrgi.hwndClient = this.Handle;
shrgi.dwFlags = (int)(SHRGFLags.SHRG_RETURNCMD );
shrgi.ptDownx = x;
shrgi.ptDowny = y;
return (SHRecognizeGesture(ref shrgi) > 0);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
BugExampleForm parent = (BugExampleForm)this.Parent;
//The problem is that the parent tick event will fire whilst TapAndHold is running
//Does TapAndHold perform an equivelant to Application.DoEvents?
parent.AddLog("Tap Hold - Enter");
parent.AddLog(String.Format("Tap Hold - Exit - {0}", TapAndHold(e.X, e.Y)));
}
}
public class BugExampleForm : Form
{
Timer _timer;
BugExample _example;
ListBox _logBox;
public BugExampleForm()
{
_example = new BugExample();
_example.Dock = DockStyle.Fill;
_logBox = new ListBox();
_logBox.Dock = DockStyle.Top;
_timer = new Timer();
_timer.Interval = 1000;
_timer.Enabled = true;
_timer.Tick += new EventHandler(_timer_Tick);
this.SuspendLayout();
this.Text = "Example";
this.Size = new System.Drawing.Size(200, 300);
this.Controls.Add(_example);
this.Controls.Add(_logBox);
this.ResumeLayout();
}
void _timer_Tick(object sender, EventArgs e)
{
AddLog("Tick");
}
public void AddLog(string s)
{
_logBox.Items.Add(s);
_logBox.SelectedIndex = _logBox.Items.Count - 1;
}
}
}
我无法内联链接图像,所以这里是一个截图的链接,说明了这种行为
编辑:在我的实际应用程序中,计时器滴答正在更新控件。所以我仅限于在一个线程中工作。(我也无法通过事件处理程序真正完成我所需要的)。