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,并执行里面的命令。

完整示例代码下载:


  1. 动态添加 ActiveX 控件添加到 ATL 复合控件
  2. Using IDispEventImpl

发表回复

您的电子邮箱地址不会被公开。