The bulk of this code was donated by Virupaksha Aithal, a member of our DevTech team in India.
It's fairly common for developers to want to check for user input from time to time during long operations, especially to see whether the user wants to cancel the current activity. In VB you'd use DoEvents() to enable messages to be processed by the application's message loop and in ObjectARX you'd use acedUsrBrk().
So how to do this in .NET?
The answer is to use a message filter. This allows us to check on user-input events... we still call DoEvents, as with previous versions of VB, which allows user input events (such as keystrokes) to flow into our message filter function. We can then detect the events we care about, and filter them out, if necessary.
This C# code filters all keystrokes during a loop operation, and allows the application to respond in its own way to the user hitting the Escape key:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Windows.Forms;
namespace LoopTest
{
public class LoopCommands
{
[CommandMethod("loop")]
static public void Loop()
{
DocumentCollection dm =
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
Editor ed =
dm.MdiActiveDocument.Editor;
// Create and add our message filter
MyMessageFilter filter = new MyMessageFilter();
System.Windows.Forms.Application.AddMessageFilter(filter);
// Start the loop
while (true)
{
// Check for user input events
System.Windows.Forms.Application.DoEvents();
// Check whether the filter has set the flag
if (filter.bCanceled == true)
{
ed.WriteMessage("\nLoop cancelled.");
break;
}
ed.WriteMessage("\nInside while loop...");
}
// We're done - remove the message filter
System.Windows.Forms.Application.RemoveMessageFilter(filter);
}
// Our message filter class
public class MyMessageFilter : IMessageFilter
{
public const int WM_KEYDOWN = 0x0100;
public bool bCanceled = false;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_KEYDOWN)
{
// Check for the Escape keypress
Keys kc = (Keys)(int)m.WParam & Keys.KeyCode;
if (m.Msg == WM_KEYDOWN && kc == Keys.Escape)
{
bCanceled = true;
}
// Return true to filter all keypresses
return true;
}
// Return false to let other messages through
return false;
}
}
}
}