中望3D二次开发 控制台命令转PDF

news/2024/11/24 12:05:56/

中望3D的外部开发模式命令非常少,没有办法使用远程办法打开文件,将图纸转换为PDF(听说以后的版本会有,但是在2022版本上是没有的);
ps:远程方式,意思就是远程电脑必须开启中望3D软件,也可以是本机;
以下就是中望3D远程的函数

/*
** (C) Copyright 2016, ZWCAD Software Co., Proprietary and Trade Secret
*/
#pragma once#ifndef ZW3D_RPC_API_H
#define ZW3D_RPC_API_H#ifndef ZS_RPC_API
#	ifdef ZS_RPC_BUILD
#		define ZS_RPC_API __declspec(dllexport)
#	else
#		define ZS_RPC_API __declspec(dllimport)
#	endif
#endif#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */typedef struct ZwRpcExportDWG{char     file[256];char     part[256];double   x_axis[3];double   y_axis[3];char     isFirstAngle;char     isExportToDXF;char     isShowDim;        /* show dimensions from part(1) or not(0) */} ZwRpcExportDWG;ZS_RPC_API void ZwRpcInitialize(const char *host, int port);
ZS_RPC_API int ZwRpcIsAvailable(int wait);
ZS_RPC_API int ZwRpcPartExportToDWG(ZwRpcExportDWG *data);
ZS_RPC_API int ZwRpcPartConvert(const char from[256], const char part[256], const char to[256]);
ZS_RPC_API int ZwRpcPartRegen(const char file[256], const char part[256]);
ZS_RPC_API int ZwRpcCmdSend(const char cmd[256]);
ZS_RPC_API int ZwRpcCmdMacro(const char file[256]);#ifdef __cplusplus
}
#endif /* __cplusplus */#endif

那么只有想其它的办法了,我看到它可以发送命令,想到在中望3D上做一个插件,然后远程发送一个命令就可以了,当然是没有办法传递参数的,只能使用数据库读写想要的数据了,数据库就选择本地sqlite数据库;

中望3D的插件,主要负责读取数据库里需要转换的文件,然后打开,转换为PDF后,再关闭文档,这里再开发时遇到几个问题:
1,打开一个绝对路径的文档,再关闭文档,会发现并没有关闭干净;
2,如果是多个图纸页,转换是一个个的PDF,需要合并;
解决办法是:
1,使用方法不对,需要先添加路径,再打开文档,则可以正常关闭;
2,没有找到好的C++库 合并PDF,调用C#写的控制台应用程序;
以下是主要代码

std::string TCHAR2STRING(TCHAR* str)
{std::string strstr;try{int iLen = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);char* chRtn = new char[iLen * sizeof(char)];WideCharToMultiByte(CP_ACP, 0, str, -1, chRtn, iLen, NULL, NULL);strstr = chRtn;}catch (std::exception e){}return strstr;
}
//获得自生DLL句柄
HMODULE GetSelfModuleHandle()
{MEMORY_BASIC_INFORMATION mbi;return ((::VirtualQuery(GetSelfModuleHandle, &mbi, sizeof(mbi)) != 0)? (HMODULE)mbi.AllocationBase : NULL);
}std::string GetExecFilePath()
{TCHAR szBuffer[MAX_PATH] = { 0 };DWORD dwError = GetModuleFileName(GetSelfModuleHandle(), szBuffer, ARRAYSIZE(szBuffer));if (dwError > 0){//char msg[256];//TcharToChar(szBuffer, msg);std::string ExecFile = TCHAR2STRING(szBuffer);int pos = ExecFile.find_last_of('\\');if (pos > 0){ExecFile = ExecFile.substr(0,pos);//pos = ExecFile.ReverseFind('\\');//if (pos > 0)//	ExecFile = ExecFile.Left(pos);}return ExecFile;}return std::string("");
}std::wstring Utf82Unicode(const std::string& utf8string)
{int widesize = ::MultiByteToWideChar(CP_UTF8, 0, utf8string.c_str(), -1, NULL, 0);if (widesize == ERROR_NO_UNICODE_TRANSLATION){throw std::exception("Invalid UTF-8 sequence.");}if (widesize == 0){throw std::exception("Error in conversion.");}std::vector<wchar_t> resultstring(widesize);int convresult = ::MultiByteToWideChar(CP_UTF8, 0, utf8string.c_str(), -1, &resultstring[0], widesize);if (convresult != widesize){throw std::exception("La falla!");}return std::wstring(&resultstring[0]);
}
std::string WString2String(const std::wstring& ws)
{std::string strLocale = setlocale(LC_ALL, "");const wchar_t* wchSrc = ws.c_str();size_t nDestSize = wcstombs(NULL, wchSrc, 0) + 1;char *chDest = new char[nDestSize];memset(chDest, 0, nDestSize);wcstombs(chDest, wchSrc, nDestSize);std::string strResult = chDest;delete[]chDest;setlocale(LC_ALL, strLocale.c_str());return strResult;
}std::string Unicode2Utf8(const std::wstring& widestring) {using namespace std;int utf8size = ::WideCharToMultiByte(CP_UTF8, 0, widestring.c_str(), -1, NULL, 0, NULL, NULL);if (utf8size == 0){throw std::exception("Error in conversion.");}std::vector<char> resultstring(utf8size);int convresult = ::WideCharToMultiByte(CP_UTF8, 0, widestring.c_str(), -1, &resultstring[0], utf8size, NULL, NULL);if (convresult != utf8size){throw std::exception("La falla!");}return std::string(&resultstring[0]);
}// std::string 转 wstring
std::wstring str2wstr(const std::string& s)
{int len;int slength = (int)s.length() + 1;len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);wchar_t* buf = new wchar_t[len];MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);std::wstring r(buf);delete[] buf;return r;
}
// std:wstring 转 LPWSTR
LPWSTR ws2LPWSTR(const std::wstring& ws) {return const_cast<LPWSTR>(ws.c_str());
}int ExportPdf(vxPath DrawFile, vxPath PdfPath, vxPath error)
{int iRet = 0;vxPath OldFilePath;cvxFileInqActive(OldFilePath, sizeof(OldFilePath));char path_buffer[128];char drive[10];char dir[128];char filename[128];char ext[10];_splitpath_s(DrawFile, drive, dir, filename, ext);vxLongName cname;strcpy(cname, drive);strcat(cname, dir);cvxPathAdd(cname);strcpy(cname, filename);strcat(cname, ext);//打开文件iRet = cvxFileOpen(cname);if (iRet == 1){sprintf(error, "文件打开失败!");return iRet;}//iRet = cvxPartRegenIsActive();iRet = cvxFileActivate(cname);char Name[256];cvxRootInqActive(Name, sizeof(Name));if (Name == NULL){sprintf(error, "文件打开失败!");return 1;}int idRoot;evxRootType Type;iRet = cvxRootId(Name, &idRoot, &Type);if (iRet == 1){sprintf(error, "无法获得根节点标识!");return iRet;}int count;int*  idDrawings;cvxMemZero((void*)&idDrawings, sizeof(int));iRet = cvxDwgInqList(idRoot, &count, &idDrawings);if (iRet == 1){sprintf(error, "文件可能不是图档!");return iRet;}if (count == 0){sprintf(error, "文件没有包含图档!");return 1;}char filename2[128];_splitpath_s(PdfPath, drive, dir, filename2, ext);if (filename2==NULL||strcmp(filename2,"")==0){strcpy(filename2, filename);}_makepath_s(path_buffer, drive, dir, filename2, ".pdf");SQLite::Database    db("C:\\Users\\Administrator\\Documents\\DrawDb.db");  // std::string ReadPdfExe;bool bExists = db.tableExists("sys_config");if (bExists){const const std::string value = db.execAndGet("select value from sys_config where key = 'MergePDFPath'");ReadPdfExe = WString2String(Utf82Unicode(value));} else{ReadPdfExe = GetExecFilePath() + "\\MergePDF.exe";}//std::string std::string szCommandLine = ReadPdfExe +" \"" + std::string(path_buffer) + "\"";for (int i = 0; i < count; i++){vxName dwg_name;cvxDwgInqName(idDrawings[i], dwg_name, sizeof(vxName));iRet = cvxDwgActivate(dwg_name);svxDrawingAt dwg_attribute;cvxDwgAtGet(idDrawings[i], &dwg_attribute);svxPdfData data;cvxMemZero((void*)&data, sizeof(svxPdfData));data.Type = evxPdfType::VX_EXPORT_PDF_TYPE_VECTOR;data.Color = 1;data.Dpi = 72;//- 这里文档描述有误,实际测试 1 = 多段线 0 = text//data.TextOutStyle = 1;//data.LineWidthScale = 0.5;data.PaperWidth = dwg_attribute.width;data.PaperHeight = dwg_attribute.height;data.Rect.X = { 0,420 };data.Rect.Y = { 0,297 };data.Rect.Z = { 0,0 };data.RangeMode = evxPdfRangeMode::VX_EXPORT_PDF_RANGE_MODE_CUSTOM;//data.ExportMultiSheet = 1;char path[128];sprintf(path, "%s-%d", filename2, i + 1);_makepath_s(path_buffer, drive, dir, path, ".pdf");szCommandLine += " \"" + std::string(path_buffer) + "\"";iRet = cvxFileExport(evxExportType::VX_EXPORT_TYPE_PDF, path_buffer, &data);if (iRet == 1){break;}}STARTUPINFO si;PROCESS_INFORMATION pi;ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);ZeroMemory(&pi, sizeof(pi));si.dwFlags = STARTF_USESHOWWINDOW;     //设置隐藏执行窗口 si.wShowWindow = SW_HIDE;if (CreateProcess(NULL,//_T("/c ") + ReadPdfPath,ws2LPWSTR(str2wstr(szCommandLine)),//LPWSTR(szCommandLine.GetString()),   // Command line.   There should be a space at the beginning NULL, // Process handle not inheritable.  NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. 0, // No creation flags. NULL, // Use parent's environment block. NULL, // Use parent's starting directory.  &si, // Pointer to STARTUPINFO structure. &pi) // Pointer to PROCESS_INFORMATION structure. ){WaitForSingleObject(pi.hProcess, INFINITE);CloseHandle(pi.hProcess);CloseHandle(pi.hThread);}cvxMemFree((void**)&idDrawings);if (OldFilePath!=NULL){cvxFileActivate(OldFilePath);//}cvxFileClose2(cname, 2);//cvxFileClose2(NULL, 2);//cvxFileClose();if (iRet == 1){sprintf(error, "转换PDF失败!");}return iRet;}int ExportPdfApi(void)
{try{SQLite::Database    db("C:\\Users\\Administrator\\Documents\\DrawDb.db", SQLite::OPEN_READWRITE);  // SQLite::OPEN_READONLYbool bExists = db.tableExists("nvt_draw");if (bExists){SQLite::Statement   query(db, "SELECT id,DrawFile,PdfFile FROM nvt_draw where status = 0");std::vector<std::string>lstSql;while (query.executeStep()){char draw[254];strcpy(draw, WString2String(Utf82Unicode(query.getColumn("DrawFile").getString())).c_str()); char pdf[254]; strcpy(pdf, WString2String(Utf82Unicode(query.getColumn("PdfFile").getString())).c_str());vxPath error="";bool isExc = ExportPdf(draw, pdf, error) == 0;std::string update = "UPDATE nvt_draw SET update_date=datetime('now','localtime'),status="+ std::string(isExc ?"1":"0")+",info = '" + std::string(error) + "'  WHERE status= 0 and id = " + query.getColumn("id").getString();lstSql.push_back(update);}query.reset();for (int i=0;i<lstSql.size();++i){std::string update = lstSql.at(i);int nb = db.exec(Unicode2Utf8(std::wstring(update.begin(), update.end())));}}return 1;}catch (std::exception& e){}return 0;
}

sqlite数据库是使用SQLiteCpp,已经封装好,地址:https://gitee.com/aubo-robotics/SQLiteCpp?_from=gitee_search
//下面是c#写的合并PDF的主要代码
//传递第一个参数是合并之后的PDF,后面的参数是要合并的PDF

        static void Main(string[] args){if (args == null || args.Length < 2){Console.WriteLine("没有输入参数 或 参数不正确");return;}string pdfPath = string.Empty;List<string> ls_pdfs = new List<string>();foreach(string item in args){if (string.IsNullOrEmpty(item))continue;System.IO.FileInfo file = new System.IO.FileInfo(item);if(file==null||!file.Extension.Equals(".pdf"))continue;if(string.IsNullOrEmpty(pdfPath)){pdfPath = item;}else{ls_pdfs.Add(item);}Console.WriteLine("传递参数:"+ item);}if (ls_pdfs.Count <= 0){Console.WriteLine("pdf数量为0,无法转换!");return;}//合并输出PdfDocumentBase pdfDoc = PdfDocument.MergeFiles(ls_pdfs.ToArray());pdfDoc.Save(pdfPath, FileFormat.PDF);foreach (string _file in ls_pdfs){Console.WriteLine("删除文件:"+ _file);File.Delete(_file);}}

//下面是外部程序的远程方法主要代码

            //插入数据nvt_draw draw = new nvt_draw{DrawFile = @"C:\Users\Administrator\Documents\ZW3D\工程图001.Z3DRW",PdfFile = @"C:\Users\Administrator\Documents\ZW3D\工程图001.pdf",};db.Insert<nvt_draw>(draw);string server = "local";IntPtr serverPtr = Marshal.StringToHGlobalAnsi(server);string cmd = "~ExportPdfApi";IntPtr cmdPtr = Marshal.StringToHGlobalAnsi(cmd);int res = ZW3DCmd_Pub(serverPtr, cmdPtr);
    [Table("nvt_draw")]public class nvt_draw{[Key]public int id { set; get; }public string DrawFile { set; get; }public string PdfFile { set; get; }public int status { set; get; }public string info { set; get; }public string update_date { set; get; }}

数据库的设计是:

最终效果是:
在这里插入图片描述


http://www.ppmy.cn/news/5031.html

相关文章

driftingblues3靶机(auth.log日志、命令执行)

环境准备 靶机链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;yc07 虚拟机网络链接模式&#xff1a;桥接模式 攻击机系统&#xff1a;kali linux 2021.1 信息收集 1.探测目标靶机开放端口和服务情况 2.用dirsearch扫描出目录 dirsearch -u 192.168.1.101 漏洞…

雪花算法原理

SnowFlake算法生成id的结果是一个64bit大小的整数&#xff0c;它的结构如下图&#xff1a;1bit&#xff0c;不用&#xff0c;因为二进制中最高位是符号位&#xff0c;1表示负数&#xff0c;0表示正数。生成的id一般都是用整数&#xff0c;所以最高位固定为0。41bit时间戳&#…

认识微服务

服务架构演变&#xff1a; 1.单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 优点&#xff1a;架构简单&#xff0c;部署成本低 缺点&#xff1a;耦合度高 2.分布式架构&#xff1a;根据业务功能对系统进行拆分&#xff0c;每个业务…

Linux----paste命令使用详解

【原文链接】Linux----paste命令使用详解 文章目录一、paste命令使用方法1.1 paste命令作用1.2 paste命令选项二、paste命令使用实例2.1 将两个文件&#xff0c;按照行合并2.2 将两个文件按照行合并&#xff0c;同时指定间隔符2.3 将两个文件串行合并一、paste命令使用方法 1.…

C语言源程序的基本单位是( )。

A&#xff0e; 过程 B&#xff0e; 函数 C&#xff0e; 子程序 D&#xff0e; 标识符 正确答案&#xff1a;B 解释&#xff1a;显而易见&#xff08;doge&#xff09; 补充&#xff1a; 三、C程序的基本组成 1、C语言源程序的基本单位是函数。 C程序是由若干…

Allegro关闭线段显示不连续效果操作指导

Allegro关闭线段显示不连续效果操作指导 用Allegro进行PCB设计的时候偶尔会出现线段不连续的情况,尤其是在线段拐弯处,实际上并不是线段没有连接上,只是一个显示效果而已,如下图 如何去关闭这个显示效果,具体操作如下 选择Setup-Design Parameter 选择Display 取消勾…

PyTorch Module类构造模型

继承Module类来构造模型&#xff0c;Module类是nn模块里提供的一个模型构造类&#xff0c;是所有神经网络模块的基类&#xff1a; __init__函数&#xff1a;创建模型参数 forward函数&#xff1a;定义前向计算 backward函数&#xff1a;反向传播 注意&#xff0c;这里并没有将…

mysql主从复制

1.服务器环境准备 我这里是在两台centos系统的虚拟机中进行的ip地址分别是192.168.168.100&#xff08;主&#xff09;和192.168.168.101&#xff08;从&#xff09; 系统为&#xff1a;CentOS Linux release 7.5.1804 (Core) 在两台服务器上都安装mysql&#xff0c;可以按照…