Hey,
Ive encountered some strange behaviour in my .NET CF 2.0 application running on Windows CE 5.0.
I have a timer updating a control periodically, that control can also receive Tap and Hold gestures from the user (in the mouse down handler). What I am finding is that when a TAH begins (but before it exits) a timer event can begin processing which is pre-empting the mouse down handler halfway through execution.
As far as my research has told me, this isn't normal behaviour, am I simply misunderstanding timers / events? Could it just be that SHRecognizeGesture is calling an equivalent to Application.DoEvents?
In any event, does anyone have a "nice" way of fixing this example so that when the app is checking for TAH, the timer delegate doesn't "tick".
See below for a sample program which illustrates this problem (Tap and hold in the empty space below the listbox to generate the log messages).
Thanks in advance.
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;
}
}
}
I can't link images inline, so here is a link to a screenshot illustrating the behaviour
Edit: In my actual application, the timer tick is updating the control. So I'm limited to working within the one thread. (I can't really accomplish what I need with event handlers either).