C++ 下实现 SmartSketch 命令插件
SmartSketch 的开放文档及示例,只有针对 VB 的示例及介绍。而 C++ 下,并不是简单的按 Visual Studio 上的向导一步步创建就可以了的,为此走了一些弯路,在此记录下。
按 Visual Studio 的向导,创建 ATL Project,再创建 ATL Simple Object。创建 ATL Simple Object 时,要注意给定 ProgID;如果没有给定 ProgID,会导致 SmartSketch 加载插件失败。
添加以下接口。该接口是命令插件的入口,当执行加载命令时,会调用该接口。
HRESULT Command_Initialize([in] IDispatch* basicCmd);
命令的执行涉及到 I2DCmCtl.ocx 的 I2DComndLib::igCommand。igCommand 反馈命令事件,以及设置什么时候命令结束;命令什么时候结束插件自身可以控制的,应该告诉 SmartSketch 我现在已经执行完了。
igCommand 是 ActiveX 控件,不能直接用 CreateInstance 创建,需要用 CAxWindow2。示例如下:
CAxWindow2 wnd; wnd.Create(nullptr, 0, L"Intergraph.CommandCtrl2D.1"); IUnknownPtr pUnk; AtlAxGetControl(wnd.m_hWnd, &pUnk); m_igCommand = pUnk;
igCommand 创建后,将 basicCmd 赋值给igCommand 的 Command 属性。
m_igCommand->Command = basicCmd;
我们还需要响应命令事件,使用 IDispEventImpl 可以方便的处理事件。示例如下,要注意版本号,要和 I2DCmCtl.ocx 中的一致。
#define IDC_CMD2D_CTL (WM_USER + 1) class ATL_NO_VTABLE CDialogBarTest5Simple : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CDialogBarTest5Simple, &CLSID_DialogBarTest5Simple>, public IDispatchImpl<IDialogBarTest5Simple, &IID_IDialogBarTest5Simple, &LIBID_DialogBarTest5Lib, /*wMajor =*/ 1, /*wMinor =*/ 0>, public IDispEventImpl<IDC_CMD2D_CTL, CDialogBarTest5Simple, &__uuidof(I2DComndLib::_DCommandEvents), &__uuidof(I2DComndLib::__I2DComndLib), 2, 5>
添加消息响应。其中 5 是对应 Initialize 事件的 dispid。
BEGIN_SINK_MAP(CDialogBarTest5Simple) SINK_ENTRY_EX(IDC_CMD2D_CTL, __uuidof(I2DComndLib::_DCommandEvents), 5, igCommand_Initialize) END_SINK_MAP()
再进行消息关联。
DispEventAdvise(pUnk, &__uuidof(I2DComndLib::_DCommandEvents));
命令完成时,记得设置结束标识。
m_igCommand->Done = VARIANT_TRUE;
至此,代码有关部分结束。编译好后,用 regsvr32 进行注册,注册时不需要加参数。注册成功后,打开 SmartSketch, Tools -> Custom Command…,选择编译好的 dll,SmartSketch 会自动加载 dll,并执行里面的命令。
完整示例代码下载: