Showing AutoCAD's hatch dialog from a .NET application
This question was posted by csharpbird:
How to get the Hatch dialog using .NET? It seems that there is no such class in the .NET API?
It's true there is no public class - or even a published function - to show the hatch dialog inside AutoCAD. It is, however, possible to P/Invoke an unpublished (and therefore unsupported and liable to change without warning) function exported from acad.exe.
Here's some C# code that shows how. The code works for AutoCAD 2007, but will be different for AutoCAD 2006: the function takes and outputs strings, so the change to Unicode in 2007 will have modified the function signature.
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using System.Reflection;
using System.Runtime.InteropServices;
namespace HatchDialogTest
{
public class Commands
{
[DllImport(
"acad.exe",
EntryPoint =
"?acedHatchPalletteDialog@@YA_NPB_W_NAAPA_W@Z",
CharSet = CharSet.Auto
)
]
static extern bool acedHatchPalletteDialog(
string currentPattern,
bool showcustom,
out string newpattern
);
[CommandMethod("SHD")]
static public void ShowHatchDialog()
{
string sHatchType;
string sNewHatchType;
bool bRet;
sHatchType = "ANGLE";
bRet =
acedHatchPalletteDialog(
sHatchType,
true,
out sNewHatchType
);
if (bRet)
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage(
"\nHatch type selected: " + sNewHatchType
);
}
}
}
}
Here's what happens when you run the code:
Command: SHD
Hatch type selected: SWAMP
Update
Someone asked me for the VB.NET code for this one (it was quite tricky to marshall the new string being returned). As I'd put it together, I thought I'd post it here:
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.EditorInput
Imports System.Text
Namespace HatchDialogTest
Public Class Commands
Private Declare Auto Function acedHatchPalletteDialog _
Lib "acad.exe" _
Alias "?acedHatchPalletteDialog@@YA_NPB_W_NAAPA_W@Z" _
(ByVal currentPattern As String, _
ByVal showcustom As Boolean, _
ByRef newpattern As StringBuilder) As Boolean
<CommandMethod("SHD")> _
Public Sub ShowHatchDialog()
Dim sHatchType As String = "ANGLE"
Dim sNewHatchType As New StringBuilder
Dim bRet As Boolean = _
acedHatchPalletteDialog(sHatchType, _
True, sNewHatchType)
If bRet And sNewHatchType.ToString.Length > 0 Then
Dim ed As Editor
ed = _
Application.DocumentManager.MdiActiveDocument.Editor
ed.WriteMessage( _
vbLf + "Hatch type selected: " + _
sNewHatchType.ToString)
End If
End Sub
End Class
End Namespace
Update 2
I've recently come back to this post at the prompting of a colleague who was struggling to get it working with AutoCAD 2010. Sure enough, the dialog would appear but the marshalling back of the return string to AutoCAD is now causing a problem, for some unknown reason (at least it's unknown to me :-).
Anyway - to address the issue I've updated the code to perform the string marshalling a little more explicitly, and it now works. This may also address the issue one of the people commenting on this post experienced trying to get the code to work with AutoCAD 2009 (although I do remember testing it there and having no issues, which has me scratching my head somewhat).
Here's the updated C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using System.Runtime.InteropServices;
using System;
namespace HatchDialogTest
{
public class Commands
{
[DllImport(
"acad.exe",
EntryPoint =
"?acedHatchPalletteDialog@@YA_NPB_W_NAAPA_W@Z",
CharSet = CharSet.Auto
)
]
static extern bool acedHatchPalletteDialog(
string currentPattern,
bool showcustom,
out IntPtr newpattern
);
[CommandMethod("SHD")]
static public void ShowHatchDialog()
{
string sHatchType = "ANGLE";
IntPtr ptr;
bool bRet =
acedHatchPalletteDialog(
sHatchType,
true,
out ptr
);
if (bRet)
{
string sNewHatchType = Marshal.PtrToStringAuto(ptr);
if (sNewHatchType.Length > 0)
{
Editor ed =
Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage(
"\nHatch type selected: " + sNewHatchType
);
}
}
}
}
}
And here's the updated VB code:
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.EditorInput
Imports System.Runtime.InteropServices
Imports System
Namespace HatchDialogTest
Public Class Commands
Private Declare Auto Function acedHatchPalletteDialog _
Lib "acad.exe" _
Alias "?acedHatchPalletteDialog@@YA_NPB_W_NAAPA_W@Z" _
(ByVal currentPattern As String, _
ByVal showcustom As Boolean, _
ByRef newpattern As IntPtr) As Boolean
<CommandMethod("SHD")> _
Public Sub ShowHatchDialog()
Dim sHatchType As String = "ANGLE"
Dim ptr As IntPtr
Dim bRet As Boolean = _
acedHatchPalletteDialog(sHatchType, _
True, ptr)
If bRet Then
Dim sNewHatchType As String = _
Marshal.PtrToStringAuto(ptr)
If sNewHatchType.ToString.Length > 0 Then
Dim ed As Editor
ed = _
Application.DocumentManager.MdiActiveDocument.Editor
ed.WriteMessage( _
vbLf + "Hatch type selected: " + sNewHatchType)
End If
End If
End Sub
End Class
End Namespace