E-Form++可视化组件库图形元件的创建与使用方法探讨?
作为全球领先的VC++可视化图形源码组件库,E-Form++在国内国外数百家企业得到了广泛的使用,为那些想要创建工业监管应用用户界面的开发者们提供了包含设计工具和软件开发工具包(SDK Source Code)的一整套服务。这些显示功能提供了高度可自定义的且与潜在实际数据相连接的图表对象。其产品基础架构完全采用VC++开发而成,无论在产品稳定性或者扩展性上都处于全球领先地位,是开发高性能的业务流程、矢量图形处理、工业控制、仿真、监控、可变打印、电子表单等软件产品的首选。使用和扩展E-Form++提供的图形元件是一个非常重要的工作,本文将探讨如何如何创建和使用这些图形元件:
一、最基本的图形元件创建方法:
直接通过鼠标绘制元件:
E-Form++提供了一个绘图工具条,见示例VisioApp, 该工具条显示在画布的右边,选中其中的绘图按钮,然后通过交互操作即可完成绘图。
通过工具盒拖拉元件:
E-Form++提供了一个类似于Microsoft Visio的工具盒,该工具盒中容纳了系统提供的缺省图形元件或者复合图形元件,直接通过鼠标拖拉的方式即可添加到画布中。
通过代码直接将图形增加到画布中,并支持Undo/Redo:
这种调用方法比较简单,基本代码如下:void CUserDefineView::OnCreateLine() { // TODO: Add your command handler code here CArray<CPoint,CPoint> ptArray; ptArray.Add(CPoint(30,40)); ptArray.Add(CPoint(120,90)); ptArray.Add(CPoint(200,120)); CFOLineShape *pReturn = new CFOLineShape; pReturn->AddRef(); pReturn->Create(&ptArray); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; } void CUserDefineView::OnCreateRect() { // TODO: Add your command handler code here CRect rcTest; rcTest = CRect(100,100,200,250); CFORectShape *pReturn = new CFORectShape; pReturn->AddRef(); pReturn->Create(rcTest,""); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); pReturn->RemoveAllPorts(); pReturn->CreateDefaultPort(0.5,0.5); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; } void CUserDefineView::OnCreateButton() { // TODO: Add your command handler code here #ifdef _FOP_E_SOLUTION { CRect rcTest; rcTest = CRect(100,100,200,125); CFOButtonShape *pReturn = new CFOButtonShape; pReturn->AddRef(); pReturn->Create(rcTest,""); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); pReturn->RemoveAllPorts(); pReturn->CreateDefaultPort(0.5,0.5); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; } #endif CRect rcTest; rcTest = CRect(100,100,200,125); CFOHyLinkShape *pReturn = new CFOHyLinkShape; pReturn->AddRef(); pReturn->Create(rcTest,""); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); pReturn->RemoveAllPorts(); pReturn->CreateDefaultPort(0.5,0.5); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; } void CUserDefineView::OnCreateIcon() { // TODO: Add your command handler code here CRect rcTest; rcTest = CRect(100,100,200,125); CFOImageShape *pReturn = new CFOImageShape; pReturn->AddRef(); pReturn->Create(rcTest,""); pReturn->LoadImage(IDR_MAINFRAME,_T(""),FO_IMAGE_ICO); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); pReturn->RemoveAllPorts(); pReturn->CreateDefaultPort(0.5,0.5); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; } void CUserDefineView::OnCreatePolygon() { // TODO: Add your command handler code here CArray<CPoint,CPoint> ptArray; ptArray.Add(CPoint(30,40)); ptArray.Add(CPoint(120,90)); ptArray.Add(CPoint(200,120)); ptArray.Add(CPoint(200,200)); ptArray.Add(CPoint(300,200)); ptArray.Add(CPoint(400,200)); ptArray.Add(CPoint(600,400)); CFOPolygonShape *pReturn = new CFOPolygonShape; pReturn->AddRef(); pReturn->Create(&ptArray); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; } void CUserDefineView::OnCreateMenubutton() { // TODO: Add your command handler code here CRect rcTest; rcTest = CRect(125,125,260,150); CMyDropMenuButtonShape *pReturn = new CMyDropMenuButtonShape; pReturn->AddRef(); pReturn->Create(rcTest,""); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); pReturn->RemoveAllPorts(); pReturn->CreateDefaultPort(0.5,0.5); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; } void CUserDefineView::OnCreateLink() { // TODO: Add your command handler code here // Create the link start shape. CRect rc = CRect(100,100,200,200); CFORectShape *pReturn = new CFORectShape; pReturn->AddRef(); pReturn->Create(rc,""); pReturn->RemoveAllPorts(); CFOPortShape *pStart = pReturn->CreateDefaultPort(0.5,0.5); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; // Create the link end shape. rc = CRect(400,100,500,200); pReturn = new CFORectShape; pReturn->AddRef(); pReturn->Create(rc,""); pReturn->RemoveAllPorts(); CFOPortShape *pEnd = pReturn->CreateDefaultPort(0.5,0.5); strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; // Create a link between two shape. CFOLinkShape* pLinkComp = new CFOLinkShape; pLinkComp->AddRef(); CPoint ptPoints[2]; ptPoints[0] = pStart->GetLinkPoint(); ptPoints[1] = pEnd->GetLinkPoint(); pLinkComp->Create(ptPoints,2); strCaption = GetCurrentModel()->GetUniqueCaption(FO_COMP_LINK); strName = GetCurrentModel()->GetUniqueName(FO_COMP_LINK); pLinkComp->SetObjectCaption(strCaption); pLinkComp->SetObjectName(strName); // Set arrow type. int nType = 3; pLinkComp->SetEndArrowType(nType); CFOAddLinkAction* pCmd = new CFOAddLinkAction(GetCurrentModel(), pLinkComp); pCmd->SetToPort(pEnd); pCmd->SetFromPort(pStart); GetCurrentModel()->Do(pCmd,TRUE); pLinkComp->Release(); pLinkComp = NULL; } void CUserDefineView::OnCreateComposite() { // TODO: Add your command handler code here CRect rc = CRect(50,50,250,300); CFOCompositeShape *pReturn = new CFOCompositeShape; pReturn->AddRef(); pReturn->Create(rc,""); CFOStaticShape *pText = pReturn->AddText("My home","My Home",CRect(0,0,200,50)); pText->SetBrushType(1); pText->SetBkColor(RGB(255,0,0)); pText->SetPenStyle(PS_SOLID); pText->SetNullPen(FALSE); CFOStaticShape *pText1 = pReturn->AddText("Father","Steven",CRect(0,50,200,100)); pText1->SetBrushType(1); pText1->SetBkColor(RGB(255,255,255)); pText1->SetPenStyle(PS_SOLID); pText1->SetNullPen(FALSE); CFOStaticShape *pText2 = pReturn->AddText("Mather","Cindy",CRect(0,100,200,150)); pText2->SetBrushType(1); pText2->SetBkColor(RGB(255,255,255)); pText2->SetPenStyle(PS_SOLID); pText2->SetNullPen(FALSE); CFOStaticShape *pText3 = pReturn->AddText("Brother0","John",CRect(0,150,200,200)); pText3->SetBrushType(1); pText3->SetBkColor(RGB(255,255,255)); pText3->SetPenStyle(PS_SOLID); pText3->SetNullPen(FALSE); CFOStaticShape *pText4 = pReturn->AddText("Brother1","Jack",CRect(0,200,200,250)); pText4->SetBrushType(1); pText4->SetBkColor(RGB(255,255,255)); pText4->SetPenStyle(PS_SOLID); pText4->SetNullPen(FALSE); pReturn->RemoveAllPorts(); pReturn->CreateDefaultPort(0.5,0.5); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); pReturn->PositionShape(&rc); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; } void CUserDefineView::OnCreateText() { // TODO: Add your command handler code here CRect rcTest; rcTest = CRect(100,100,200,125); CFOStaticShape *pReturn = new CFOStaticShape; pReturn->AddRef(); pReturn->Create(rcTest,""); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); pReturn->RemoveAllPorts(); pReturn->CreateDefaultPort(1,0.5); GetCurrentModel()->InsertShape(pReturn); pReturn->Release(); pReturn = NULL; }
通过代码创建,并不支持Undo/Redo:
有的时候,需要同时创建很多图形,不需要支持Undo/Redo, 这种情况下,只需要将上面的支持Undo/Redo的方式中的:GetCurrentModel()->InsertShape(...); 修改为GetCurrentModel()->GetShapes()->AddTail(...);即可。如下:
void CUserDefineView::OnCreateLine() { // TODO: Add your command handler code here CArray<CPoint,CPoint> ptArray; ptArray.Add(CPoint(30,40)); ptArray.Add(CPoint(120,90)); ptArray.Add(CPoint(200,120)); CFOLineShape *pReturn = new CFOLineShape; pReturn->AddRef(); pReturn->Create(&ptArray); CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType()); CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType()); pReturn->SetObjectCaption(strCaption); pReturn->SetObjectName(strName); GetCurrentModel()->GetShapes()->AddTail(pReturn); pReturn->Release(); }
此种情况中, 需要自行刷新新加入的图形。具体做法如下:
1)、创建一个CFODrawShapeList m_lstUpdate; 2)、将需要刷新的元件的指针加入到该列表中: m_listUpdate.AddTail(pReturn); 3)、调用UpdateShapes(&m_lstUpdate);来一次刷新所有的图形。考虑到效率问题,我们建议尽可能的减少刷新次数,能够集中起来一次刷新的就尽可能一次刷新。
二、为创建画布上的图形预留的虚函数:
当新图形增加到画布前,往往我们需要对其进行一些特别的初始化,例如设定新的属性数据,确定新的坐标等等。覆盖这些虚函数的基本方式是将该虚函数的缺省源代码从E-Form++库中复制出来,然后根据需要进行适当的修改。下面是E-Form++可视化组件库预留的虚函数:
-
virtual void DoInitCreateShape(CFODrawShape *pShape); -- 定义类CFODataModel
当所有元件增加到画布之前,此虚函数都会被调用,pShape是该图形的指针,通过该指针可以对图形的所有数据进行初始化。覆盖此虚函数的时候一定要保留系统的缺省调用 即调用CFODataModel::DoInitCreateShape(pShape);代码。
-
virtual void DoShapeDrop(
// List of shapes.
const CFODrawShapeList& listShapes,
// Toolbox Item drop value.
COleDataObject* pDataObject
);
定义于类CFOPCanvasCore中,此虚函数在将图形元件从左边的工具盒中拖拉放入画布的时候被调用, 通过覆盖该虚函数可以在图形在图形拖入画布时做些定制工作。
-
virtual void DoCreateCustomDragShape(COleDataObject* pDataObject,CPoint point);
定义于类CFOPCanvasCore中,此虚函数为从工具盒拖拉自定义的数据预留,如果拖拉的不是E-Form++直接支持的数据格式,通过覆盖此虚函数,将pDataObject中的数据转换为相应的元件,加入到m_pCurDropShapesList列表中即可支持该数据的拖拉。
-
virtual void DoInitCompositeShape(CFOCompositeShape *pShape,int nType);
定义于类CFOPCanvasCore中,当从左边的工具盒拖入的是复合图形元件的时候,通过覆盖此虚函数可以初始化该复合图形元件,例如设置缺省的停靠点的数目和位置等等。
-
virtual void DoSplitCompositeShape(CFODrawShapeList *pList,CFOCompositeShape *pShape);
定义于类CFOPCanvasCore中,当从左边的工具盒拖入复合图形元件的时候,有一个选项(工具盒选中元件,单击右键选择“改变类型和名称”对话框的最下面的检查框设定)是允许用户切分复合图形为单个的子图形元件,覆盖此虚函数可以定义新的切分方式。
-
virtual CFODrawShape *GetOleDataObject(COleDataObject* pData);
定义于类CFOPCanvasCore中,当从左边的工具盒拖入任何一个图形元件的时候,此函数处理拖入的数据,并通过对拖入的数据的分析来创建新的图形元件。覆盖此函数,可以重新定义拖入的数据分析方式。
三、 小结
得益与C++开发代码的高度灵活性,E-Form++通过大量虚函数的使用,为用户自由控制程序中的任何细节提供了最恰当的方式。本文只是在一些基本层面对E-Form++的图形元件的使用进行了剖析,后面我们还会有专门的文章针对如何创建高级的控制元件进行介绍。
原文:http://www.ucancode.com/VC_Draw_Tool_Diagram_Tool_Article/draw_visio_like_diagram_vc_tool.htm
E-Form++可视化图形组件库企业版本全功能免费评估版本(附带大量示例VC++源代码)下载地址:http://www.ucancode.com