以项目实战讲解CAD的二次开发(二)

  • 基础库
  • 数据层
  • 自定义实体
  • 工程量数据
  • 数据提供者
  • 网络
  • 本地加密文件
  • 外观
  • Ribbon菜单
  • 停靠面板
  • 交互UI
  • CAD预览控件
  • 总结



网上关于cad的开发项目几乎是没有,相关技术文章也少得可怜。一方面是因为cad的开发基本是和工程项目或者企业产品深度结合的一个路线,所以源码就是整个企业的核心根本,在很多企业中都已经是使用物理锁把开发电脑锁住,以防泄露。另一方面cad开发的发展方向太窄,看看现如今互联网人潮汹涌,前赴后继,薪资也是相差甚大。


当然“开发只是一种手段,语言只是一门工具”,这句话很多人都说过,也的确正确。但我认为这句话只有你足够优秀,真的有能力在各种语言中驾轻就熟才显得不那么虚。因此每个人初期还是踏踏实实走好自己的每一步。基础扎实之后,无论走什么路线,都是比较轻松地。

基础库

一个软件公司里面都有自己的通用库,它主要分为全产品通用和类似产品通用。
  • base
  • acad
  • project
    base可以定义为全产品通用的api,主要接口有string、file、thread、database、md5等等基础api,要尽量保证平台无关性。
    acad顾名思义只cad相关的库,可依据功能性进行分类和封装api。譬如xdata、layer、dbentity、sysvar、acgs、acge、acui等等。
    project是本项目中的通用接口,比如命令的统一注册、数据的统一获取设置等等。

数据层

数据当然是项目或产品的重中之重,总体而言cad的数据中可分为外观、工程量。

自定义实体

java 提供二次开发的包 java cad二次开发_.net


自定义实体主要是为了数据安全、更为复杂的交互等而设计。通常我们都会以继承AcDbEntity而设计。在一个产品中,我们必须做个产品虚基类实体。比如DaveEntity,然后从该实体继承我们其他有意义的实体。它主要用来记录一些通用数据和方便我们做程序处理的。

OMF的设计上BricsCAD在sdk上提供了C++的类,而AutoCAD还是主要以COM的形式提供。有时感慨AutoDesk不思进取,估计力量都投到Revit或其他产品上面去了。从这里看一看出BricsCAD非常适合C++开发,从Ribbon、OMF都提供了接口。

工程量数据

这和具体业务相关,也较为简单,总之一切要以生成报表预算为准则去设计。

数据提供者

包括用户、工程量、权限、单价等各种数据的提供通常是数据库,由于这里不考虑直连,之前也分析过要离线设计,所以分为网络、和本地加密文件(或加密狗)两种方式。在设计框架的时候就要考虑数据提供的问题。

template<IProvider::ModelType type,typename TProvider = IProvider>
class DataProviderBase
{
public:
DataProviderBase() : type_(type), provider_(nullptr) {
static_assert(std::is_base_of<IProvider, TProvider>::value, "provider type error");
}
virtual ~DataProviderBase() = default;
public:
	virtual IProvider::ModelType GetModelType() const {
		return type_;
	}
	virtual IProvider* GetProvider()
	{
		if (provider_== nullptr)
		{
			provider_= dynamic_cast<TProvider *>(CreateProvider());
			if (provider_!= nullptr)
				provider_->SetPlugin(this);
		}				
		return provider_;
	}
protected:
	virtual CContainerUI* CreateProvider() = 0;
protected:
 IProvider::ModelType type_;
 TProvider* provider_;
};

网络

数据提供者网络部分的实现,大概如下:

class UserCloudProvider : public IProvider
{
public:
UserCloudProvider() : type_(kDataFromCloud){
}
~UserCloudProvider() = default;
protected:
ModelType type_;
}

本地加密文件

数据提供者本地部分的实现,大概如下:

class UserLocalProvider : public IProvider
{
public:
UserLocalProvider () : type_(kDataFromLocal){
}
~UserLocalProvider () = default;
protected:
ModelType type_;
}

这些源码只 进行思路分析。另外本地文件加密要慎之又慎,需要多重加密以确保安全。

外观

“芙蓉不及美人妆,水殿风来珠翠香”。外观就是把各种数据展示给客户,精确且惊艳为最佳。

Ribbon菜单

java 提供二次开发的包 java cad二次开发_c++_02


Ribbon的实现在AutoCAD例子中基本都是.Net源码,而在BricsCAD的官方例子中则是使用了C++接口。我们可以统一成.Net功能,但BricsCAD中可能加载较慢,影响体验,所以还是统一成C++。有关Ribbon的C#核心代码(网上例子超多,这里还是要充分考虑别用明确的AutoDesk.AutoCAD命名空间,因为我们还要支持其他CAD呢):

// 声明需要添加的Ribbon Tab页
_AcWnd1.RibbonControl ribbonControl = _AcWnd1.ComponentManager.Ribbon;
_AcWnd1.RibbonTab Tab = new _AcWnd1.RibbonTab();
Tab.Title = "蚺城疯子软件";
Tab.Id = "RibbonTest_ID";
ribbonControl.Tabs.Add(Tab);
// 创建新的Panel
var panel1Panel = new _AcWnd1.RibbonPanelSource();
panel1Panel.Title = "图层管理";
var Panel1 = new _AcWnd1.RibbonPanel();
Panel1.Source = panel1Panel;
Tab.Panels.Add(Panel1);
// 添加按钮到Panel中
string ribbon_path = MyMgd.Utils.GetStartPath() + @"skin\image\ribbon\";
Bitmap img1_16 = new Bitmap(ribbon_path + "button1_16.png"),
	img1_32 = new Bitmap(ribbon_path + "button1_32.png"),
    img2_16 = new Bitmap(ribbon_path + "button2_16.png"),
    img2_32 = new Bitmap(ribbon_path + "button2_32.png");
var pan1btnAddLayers = NewRibbonButton("添加图层", "AddLayer ", img1_16, img1_32);
var pan1btnEraseLayers = NewRibbonButton("允许导出", "Export ", img2_16, img2_32);

var pan1row1 = new _AcWnd1.RibbonRowPanel();
pan1row1.Items.Add(pan1btnEraseLayers);
pan1row1.Items.Add(new _AcWnd1.RibbonRowBreak());

panel1Panel.Items.Add(pan1btnAddLayers);
panel1Panel.Items.Add(new _AcWnd1.RibbonSeparator());
panel1Panel.Items.Add(pan1row1);

停靠面板

java 提供二次开发的包 java cad二次开发_java 提供二次开发的包_03


一般是停靠在左侧,如天正系列的设计软件。在开发过程中还需要考虑高DPI的支持,由于我屏幕是2.5K,所以天正的字体在我这里会显得很小,或许客户的屏幕是4K,那估计就小得没法正常操作了。之后的交互UI同样要注意高分辨率屏幕的问题。

交互UI

一个项目中,使用到的界面会非常的多,我们要事先考虑那些是共有的,提出来,我们事先做好UI的拆分。譬如列表格式、表格样式、属性界面等等。

CAD预览控件

java 提供二次开发的包 java cad二次开发_c++_04


预览控件其实也是交互UI的一种,但实现方式多种多样,可简可繁,下一章将会详细讨论。复杂功能应当有如下:

  • 左右键、双击事件
  • 可支持图纸、块、实体、临时实体等预览
  • 可缩放、拖拽等cad简易操作,以实现用户仔细确认。
  • 分页

总结

  1. 部分功能在AutoCAD和BricsCAD上的实现方式不同,应尽量统一——OMF,Ribbon
  2. 界面需要注意高DPI的问题
  3. 数据和ui耦合性尽量要降低,另外本地加密问题

基础库或者基础框架总是要有人使用才会丰富、进化而变得更为实用,本章只提供大概思路。一个好的通用库可以大大的提升团队的开发 效率。
这些框架的东西没怎么细讲,否则每个环节都要花大篇幅的设计和源码,那就失去了重点。
之后就是每个具体功能的详细记录、分析、探讨——预览控件,从C++和C#、AutoCAD和BricsCAD多个方面来讨论。