如何让VC在编译ARX项目时自动通知AutoCAD卸载ARX程序,并在编译完成后自动加载新编译的ARX程序

在编写ARX程序时,一个比较麻烦的地方在于,每次重新编译ARX项目时,需要先手动的卸载此前加载调试的ARX程序,然后编译,最后再加载新生成的程序,虽然过程不算复杂,但经常这样做会让人感到厌烦。有没有办法使VC在启动编译前,自动通知AutoCAD卸载此插件(即旧版本的ARX程序),然后开始编译,编译完成后,再自动通知AutoCAD加载此新生成的ARX插件呢?

 

我在查看了QQ群里一些朋友的讨论之后,结合他们给出的一些思路,经过一番摸索,终于找到一种可行的方案。这个方案包括如下几个部分:

1.添加两个自定义命令,分别用于加载和卸载ARX程序

AutoCAD自带几个命令,如APPLOAD, ARX等,可用于ARX程序的加载和卸载,但都是基于GUI的操作,无法完全通过命令行的方式实现ARX的加载和卸载。因此,需要我们自己编写两个命令来分别实现通过命令行加载,卸载ARX程序。这个容易实现:

新建一个叫做ArxLoader的ARX项目,添加两个命令ArxLoad, ArxUnload,分别用于加载和卸载通过路径指定的ARX程序

	static void wdArxLoader_ARXLOAD(void)
	{
		ACHAR arxPath[134];
		acedGetString(1,NULL,arxPath);
		AcRxDynamicLinker* pLinker = acrxDynamicLinker;

#ifdef NDEBUG		// release version
		pLinker->loadModule(arxPath,false);
#else			// debug version
		acedPrompt(arxPath);
		pLinker->loadModule(arxPath,true);
#endif
	}

	static void wdArxLoader_ARXUNLOAD(void)
	{
		ACHAR arxPath[134];
		acedGetString(1,NULL,arxPath);
		AcRxDynamicLinker* pLinker = acrxDynamicLinker;

#ifdef NDEBUG		// release version
		pLinker->unloadModule(arxPath);
#else			// debug version
		acedPrompt(arxPath);
		pLinker->unloadModule(arxPath);
#endif
	}

这个项目会生成一个名为wdArxLoader.arx的插件,其中包含ArxLoad和ArxUnload命令,备用。

2.实现外部程序向AutoCAD主程序发送AutoCAD命令

这一步比较关键,实现方法也比较“古怪”。这里有篇文章讲述如何通过各种方式向AutoCAD发送命令:

Techniques for calling AutoCAD commands programmatically

我采用了这篇文章中所介绍的方式来实现从我们自己的外部程序向AutoCAD发送Ansys命令。

新建一个win32控制台项目,添加如下代码:

#include <string>
#include <cassert>

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
	COPYDATASTRUCT* pCmdMsg = (COPYDATASTRUCT*)lParam;

	const int MAX_LEN = 256;
	TCHAR caption[MAX_LEN];
	assert(hwnd!=NULL);
	::GetWindowText(hwnd,caption,MAX_LEN);
	std::wstring captionStr(caption);
	if (captionStr.substr(0,12)==_T("AutoCAD 2008"))
	{
		::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)pCmdMsg);
	}
	return TRUE;
}

void SendCmdToAcad(LPCTSTR cmd)
{
	COPYDATASTRUCT cmdMsg;
	cmdMsg.dwData = (DWORD)1;
	cmdMsg.cbData = (DWORD)(_tcslen(cmd) + 1) * sizeof(TCHAR);
	cmdMsg.lpData = (PVOID)cmd;
	::EnumDesktopWindows(NULL,EnumWindowsProc,(LPARAM)&cmdMsg);
}

int _tmain(int argc, TCHAR* argv[])
{
	if (argc>1)
	{
		std::wstring unloadCmd(argv[1]);
		unloadCmd += _T("\r");
		SendCmdToAcad(unloadCmd.c_str());
	}

	return 0;
}

这里向AutoCAD主窗口发送消息的代码与参考文献的类似,只是获取AutoCAD主窗口的句柄的方式不一样,原文中adsw_acadMainWnd()函数只能用于从ARX插件内部获取主窗口句柄,而不能用于“外部独立程序”中,因此只能采取其他间接的方法获取,比如我这里使用的枚举所有顶级窗口的方式。

这个项目会生成一个名为SendCmdToAcad.exe的命令行小工具,备用。

3.设置我们自己所要编译的ARX项目

在项目的属性页对话框中,在“All Configuration”配置下,选择”Build Events>>Pre-build Event”,然后在”Command line”中输入:

D:\Cpp\ObjectArx\AcadToAnsys\Release\SendCmdToAcad.exe "arxunload $(TargetPath)"

其中,”D:\Cpp\ObjectArx\AcadToAnsys\Release\SendCmdToAcad.exe”是我们前面第2步准备的命令行小工具的完整路径,”arxunload $(TargetPath) ”是要发送给AutoCAD执行的命令,用于通知AutoCAD卸载我们所要重新编译生成的ARX程序。

ScreenShot00171

选择”Build Events>>Pre-build Event”,然后在”Command line”中输入:

D:\Cpp\ObjectArx\AcadToAnsys\Release\SendCmdToAcad.exe "arxload $(TargetPath)"

其中,”D:\Cpp\ObjectArx\AcadToAnsys\Release\SendCmdToAcad.exe”是我们前面第2步准备的命令行小工具的完整路径,”arxload $(TargetPath) ”是要发送给AutoCAD执行的命令,用于通知AutoCAD加载我们刚重新编译生成的ARX程序。

ScreenShot00172

4.使用方法

在AutoCAD中输入APPLOAD手动加载第1步中准备好的wdArxLoader.arx,此后,就不再需要在重新编译我们的ARX项目时,手动的加载卸载ARX程序了,这一过程会由VC自动通知AutoCAD帮我们完成,我们要做的就是简单重现编译下就可以了,眨眼

posted on 2011-04-11 01:41  wudong  阅读(2878)  评论(0编辑  收藏  举报

导航