First, the reason your original idea doesn't work is that the event handlers are all on the same thread. The mouseup handler cannot run until mousedown returns, and mousedown doesn't return until mouseup has run, so you're basically deadlocking yourself with only one thread! :D Depending on what you do in those handlers you may be able to do it in another thread instead. But if you want to do anything to the GUI itself, you aren't allowed to do so on any thread but the "gui thread", which is the same thread that is raising the events. So you have to use another hook... to marshal the call back to the UI thread again! Here's an example of how to do this. To run it, create a new windows forms application and replace Form1.cs with:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
long n;
MouseButtons buttons;
Label label1;
public Form1()
{
label1 = new Label();
label1.Text = "here";
Controls.Add(label1);
label1.MouseUp += new MouseEventHandler(label1\_MouseUp);
label1.MouseDown += new MouseEventHandler(label1\_MouseDown);
}
void label1\_MouseDown(object sender, MouseEventArgs e)
{
buttons = e.Button;
new Thread(run).Start();
}
void label1\_MouseUp(object sender, MouseEventArgs e)
{
buttons = MouseButtons.None;
}
void run()
{
var upd = new Action(update);
while (buttons != MouseButtons.None) label1.Invoke(upd);
}
void update()
{
n = (buttons == MouseButtons.Left ? --n : ++n);
label1.Text = n.ToString();
}
}
}