It's often desirable to show a progress meter during lengthy operations. Although there's currently no public API to make use of AutoCAD's progress meter from .NET, there are nevertheless a couple of approaches to doing so.
In this post I'll show how to do this using P/Invoke (using some code borrowed from Fenton Webb, from DevTech Americas) and in my next post I'll show how to use the "internal" AutoCAD managed assembly.
Here's the C# code that uses P/Invoke, which should work for AutoCAD 2007 and 2008:
using Autodesk.AutoCAD.Runtime;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ProgressMeterTest
{
public class Cmds
{
[DllImport(
"acad.exe",
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acedSetStatusBarProgressMeter@@YAHPB_WHH@Z"
//This should work for AutoCAD 2006...
//EntryPoint = "?acedSetStatusBarProgressMeter@@YAHPBDHH@Z"
)]
private static extern int
acedSetStatusBarProgressMeter(
string label,
int minPos,
int maxPos
);
[DllImport(
"acad.exe",
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acedSetStatusBarProgressMeterPos@@YAHH@Z"
)]
private static extern int
acedSetStatusBarProgressMeterPos(int pos);
[DllImport(
"acad.exe",
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "?acedRestoreStatusBar@@YAXXZ"
)]
private static extern int acedRestoreStatusBar();
[CommandMethod("PB")]
public void ProgressBar()
{
acedSetStatusBarProgressMeter("Testing Progress Bar", 0, 100);
for (int i = 0; i <= 100; i++)
{
for (int j = 0; j <= 10; j++)
{
System.Threading.Thread.Sleep(1);
acedSetStatusBarProgressMeterPos(i);
// This allows AutoCAD to repaint
Application.DoEvents();
}
}
acedRestoreStatusBar();
}
}
}
And here's what you see when it runs:
Update:
Thanks to Chris Bray for pointing out the above technique (and the one I was about to show in Part 2) is unnecessary from AutoCAD 2007 onwards. A new class was introduced in AutoCAD 2007 called Autodesk.AutoCAD.Runtime.ProgressMeter.
Here's some C# code that demonstrates the use of this class:
using Autodesk.AutoCAD.Runtime;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ProgressMeterTest
{
public class Cmds
{
[CommandMethod("PB")]
public void ProgressBarManaged()
{
ProgressMeter pm = new ProgressMeter();
pm.Start("Testing Progress Bar");
pm.SetLimit(100);
// Now our lengthy operation
for (int i = 0; i <= 100; i++)
{
System.Threading.Thread.Sleep(5);
// Increment Progress Meter...
pm.MeterProgress();
// This allows AutoCAD to repaint
Application.DoEvents();
}
pm.Stop();
}
}
}
The original code is still the technique to use for AutoCAD 2005 & 2006, although you will need to uncomment the line in the DllImport attribute for acedSetStatusBarProgressMeter(), to make sure it uses the EntryPoint with the non-Unicode string argument ("?acedSetStatusBarProgressMeter@@YAHPBDHH@Z"). You'll clearly also need to comment out the current EntryPoint assignment, of course.
I'll forego the Part 2 post (and rename this one from Part 1), as there's really no need to look any other technique for this, at this stage.

Leave a Reply to Fernando Malard Cancel reply