AutoCAD 自動管理字體插件[使用ObjectARX C++]


概述:

使用AutoCAD的過程中,我們常常因為缺失字體而煩惱,本插件就是為了解決這個問題。

插件采用WEB服務器 + CAD插件方式。WEB服務器使用Python編寫,部署在百度BAE上;CAD插件使用C++開發,在AutoCAD中使用命令“APPLOAD”加載該插件。

在CAD中打開新的DWG文檔后,插件會自動比較DWG文檔所需字體以及CAD的Font目錄下的字體,如果有缺失字體,則自動到WEB服務器下載;如果有服務器上沒有的字體,就悄悄上傳到服務器。

下載:

源代碼:

https://github.com/Xiongpq/FontCenter

編譯源代碼需要ObjectARX,請自行下載。

客戶端:

http://pan.baidu.com/s/1pJPk6mR

下載客戶端后,可以在AutoCAD中,輸入“APPLOAD”命令加載相應的Warrentech.FontCenter.Client.arx文件即可加載該插件。請注意AutoCAD不同版本應該加載不同的DLL,例如:AutoCAD 2008 32位,應加載2008_X86文件夾下的DLL。

主要代碼:

一、在LoadDwg時添加處理字體代碼

客戶端使用C++編寫,調用AutoCAD的ObjectARX C++ API,在AutoCAD的On_kLoadDwgMsg事件中使用多線程做字體的下載及上傳,下面是主要的代碼:

    virtual AcRx::AppRetCode On_kLoadDwgMsg(void *pkt){
        AcRx::AppRetCode retCode = AcRxArxApp::On_kLoadDwgMsg(pkt);

        try {
            acutPrintf(_T("正在檢測該文件字體設置,若有缺失將自動下載...\n"));

            HANDLE   hth1;
            unsigned  threadID;
            FontBLL *fontBLL = new FontBLL();
            hth1 = (HANDLE)_beginthreadex(NULL, 0, FontBLL::run, fontBLL, CREATE_SUSPENDED, &threadID);

            if (hth1 != 0) {
                ResumeThread(hth1);
            }
        }
        catch (...) {}

        return (retCode);
    }

二、獲取當前DWG文檔需要的字體名稱

使用ObjectARX接口獲取AcDbTextStyleTableIterator,循環這個迭代器,將字體文檔的字體名稱、大字體名稱都加入一個vector<wstring>中,以便后面和Font文件夾中的字體名稱進行比較。

注意要對字體名稱做一些處理,以及重復性檢查,詳見源代碼。

    Acad::ErrorStatus es;
    AcApDocument* pDoc;
    AcDbDatabase* pDb;
    pDoc = acDocManager->curDocument();
    pDb = pDoc->database();

    AcDbTextStyleTable* pTextTbl;
    AcDbTextStyleTableIterator *pTextIterator;
    es = pDb->getTextStyleTable(pTextTbl, AcDb::kForRead);
    pTextTbl->newIterator(pTextIterator);        //獲取迭代器

    vector<wstring> fontList;
    for (pTextIterator->start(); !pTextIterator->done(); pTextIterator->step()) {
        AcDbTextStyleTableRecord *pTextRecord;
        es = pTextIterator->getRecord(pTextRecord, AcDb::kForRead);

        TCHAR* pFontName = NULL;
        es = pTextRecord->fileName(pFontName);   //獲取字體名稱
        if (es == Acad::eOk) {
            AddToFontList(pFontName, fontList);
        }

        es = pTextRecord->bigFontFileName(pFontName);   //獲取大字體名稱
        if (es == Acad::eOk) {
            AddToFontList(pFontName, fontList);
        }
    }
    pTextTbl->close();

三、獲取本地字體列表

獲取本地AutoCAD安裝目錄下Font文件夾下已存在的字體列表。

    vector<wstring> result;
    _tfinddata64_t c_file;
    intptr_t hFile;
    wstring root;
    root.append(path);        //路徑
    root.append(L"\\*");
    root.append(ext);         //擴展名

    hFile = _tfindfirst64(root.c_str(), &c_file);
    if (hFile == -1)
        return result;

    do {
        if (_tcslen(c_file.name) == 1 && c_file.name[0] == _T('.')
            || _tcslen(c_file.name) == 2 && c_file.name[0] == _T('.') && c_file.name[1] == _T('.'))
            continue;

        result.push_back(c_file.name);

    } while (_tfindnext64(hFile, &c_file) == 0);
    _findclose(hFile);

四、下載缺失字體

插件使用curl類庫做HTTP請求,到WEB服務器下載需要的文件。服務器上的字體文件全都是ZIP文件,所以下載下來后,需要解壓。另外,如果沒有下載到需要的字體,則會通過WEB服務器的report_missing_cad_font這個API,報告服務器。

    CURL *curl;
    CURLcode res;
    FILE *fp;
    wstring fullPath = FontBasicPath + L"\\" + fontName + L".zip";
    _wfopen_s(&fp, fullPath.c_str(), L"wb");   //創建ZIP文件
    if (fp == NULL) {
        return false;
    }
    transform(fontName.begin(), fontName.end(), fontName.begin(), towlower);
    bool result = false;
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, (DownloadCadFontUrl + "/" + WStringToUTF8(fontName.c_str()) + ".zip").c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        res = curl_easy_perform(curl);      //請求服務器
        if (CURLE_OK == res) {
            fclose(fp);

            char *ct;
            res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
            if ((CURLE_OK == res) && ct) {
                std::string contentType(ct);
                curl_easy_cleanup(curl);
                if (contentType == "application/zip") {    //判斷下載文件的類型
                    result = true;                           //如果不是"application/zip"類型,就說明服務器上也沒有這個字體
                }
                else {
                    CURL *reportCurl;
                    reportCurl = curl_easy_init();
                    curl_easy_setopt(reportCurl, CURLOPT_URL, ReportMissingCadFontUrl.c_str());
                    string postData = "keyword=" + WStringToUTF8(fontName.c_str());
                    curl_easy_setopt(reportCurl, CURLOPT_POSTFIELDS, postData.c_str());
                    res = curl_easy_perform(reportCurl);
                    curl_easy_cleanup(reportCurl);
                }
            }
        }
    }

五、上傳客戶端字體到服務器

服務器端雖然預置了2000多種AutoCAD字體,但仍然不是最全面的,所以如果客戶端存在服務器端沒有的字體,插件就會上傳該字體到服務器。

首先,將本地字體名稱列表POST到服務器,服務器會比較服務器上的字體列表,並將需要上傳的字體列表通過JSON數據返回。

然后,客戶端收到字體列表后,將需要上傳的字體壓縮打包,通過WEB API上傳到服務器端。

bool upload_file(const wstring path)
{
    CURL *curl;
    CURLcode res;
    struct curl_httppost *formpost = NULL;
    struct curl_httppost *lastptr = NULL;

    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_PTRNAME, "file",
                 CURLFORM_FILE, WStringToString(path).c_str(),
                 CURLFORM_END);
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, UploadCadFontUrl.c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);

        _wremove(path.c_str());
        return true;
    }

    _wremove(path.c_str());
    return false;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM