小众知识

如何让VC在编译ARX项目时自动通知AutoCAD卸载ARX程序
2016-06-30 10:34:21   来源:   评论:0 点击:

如何让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程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    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控制台项目,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#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帮我们完成,我们要做的就是简单重现编译下就可以了

相关热词搜索:ARX AutoCAD

上一篇:Arx2010的调试与编译
下一篇:获取ARX文件路径

分享到: 收藏
评论排行
最新发布