Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Programmable Vector Graphics

0.00/5 (No votes)
29 Dec 2004 2  
Creating vector graphics editor, implementing vector graphics ActiveX.

Sample Image - ProgrammVectorGraphics.jpg

Introduction

What is Vector Graphics ActiveX?

Vector Graphics ActiveX is the free and easy-to-use graphics solution for creating technical drawings, illustrations, charts, diagrams and much more. It offers a wide range of new features and enhancements designed to increase productivity and extend possibilities of your applications.

Why use Vector Graphics ActiveX?

Vector Graphics ActiveX allows developers to easily create and manage 2D drawing projects and reduce development time. Also it offers a visual development environment that can be either graphical user interface (GUI) or code driven. It provides over 1000 methods, properties and events and is fully object oriented.

Implementation

First of all, create an empty MFC project with ATL support. Create an empty form, put Vector Graphics ActiveX on it and generate the generated IDispatch wrapper class.

Don't forget to include the .tlb file:

# import "PGFTLB\prographer.tlb" no_namespace named_guids

The next step is to add member variables to our form class:

CPGAX          m_PGAX;
IDocumentPtr   m_spDocument;
IWindowPtr     m_spWindow;

To handle events from the control you should create the class CComInnerObject and add two variables:

template<class T> class CComInnerObject : public CComObjectNoLock<T>
{
 STDMETHOD_(ULONG, Release)()
 {
  return InternalRelease();
 }
};

CComInnerObject<CDocEventSink> m_DocEventSink;
CComInnerObject<CWndEventSink> m_WndEventSink;

The class that describes the form should look like this:

// CPGAXTESTDlg dialog

class CPGAXTESTDlg : public CDialog
{
 DECLARE_DYNAMIC(CPGAXTESTDlg)
public:
 CPGAXTESTDlg(CWnd* pParent = NULL);
 virtual ~CPGAXTESTDlg();
 // Dialog Data

 enum { IDD = IDD_PGAXDLG };
protected:
 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

 DECLARE_MESSAGE_MAP()
private:
 class CDocEventSink :
  public CComObjectRootEx<CComSingleThreadModel>,
  public IDispEventImpl<1, CDocEventSink, &DIID_IDocumentEvents, 
             &LIBID_ProGrapherFoundation, 1, 0>
 {
 public:
  CDocEventSink()
  {
   m_pDlg = NULL;
  }
 public:
  CPGAXTESTDlg* m_pDlg;
 private:
  // Interface map

  BEGIN_COM_MAP(CDocEventSink)
  END_COM_MAP()
  BEGIN_SINK_MAP(CDocEventSink)
   SINK_ENTRY_EX(1, DIID_IDocumentEvents, 1, OnOpen)
  END_SINK_MAP()
  void _stdcall OnOpen();
 };
 class CWndEventSink :
  public CComObjectRootEx<CComSingleThreadModel>,
  public IDispEventImpl<1, CWndEventSink, &DIID_IWindowEvents, 
                               &LIBID_ProGrapherFoundation, 1, 0>
 {
 public:
   CWndEventSink()
   {
    m_pDlg = NULL;
   }
 public:
   CPGAXTESTDlg* m_pDlg;
   double   ptX, ptY;
 private:
   // Interface map

   BEGIN_COM_MAP(CWndEventSink)
   END_COM_MAP()
   BEGIN_SINK_MAP(CWndEventSink)
    SINK_ENTRY_EX(1, DIID_IWindowEvents, 1, OnMouseMove)
    SINK_ENTRY_EX(1, DIID_IWindowEvents, 2, OnLButtonDown)
    SINK_ENTRY_EX(1, DIID_IWindowEvents, 3, OnLButtonUp)
   END_SINK_MAP()
   void _stdcall OnMouseMove(long Flags, double X, double Y);
   void _stdcall OnLButtonDown(long Flags, double X, double Y);
   void _stdcall OnLButtonUp(long Flags, double X, double Y);
 };
 public:
 CComInnerObject<CDocEventSink> m_DocEventSink;
 CComInnerObject<CWndEventSink> m_WndEventSink;
 CPGAX       m_PGAX;
 IDocumentPtr     m_spDocument;
 IWindowPtr      m_spWindow;
 IShapePtr      m_spShape;
private:
 virtual BOOL OnInitDialog();
public:
 afx_msg void OnDestroy();
 afx_msg void OnBnClickedLoad();
 afx_msg void OnBnClickedNew();
 afx_msg void OnBnClickedZoomin();
 afx_msg void OnBnClickedZoomout();
 afx_msg void OnBnClickedOk();
 afx_msg void OnBnClickedGenbtn();
};

Initialization is very simple and looks like:

IDispatchPtr spDispatch;
 spDispatch.Attach(m_PGAX.get_Document(), true);
 m_spDocument = spDispatch;
 m_spWindow = m_spDocument->Window;
 m_DocEventSink.m_pDlg = this;
 m_WndEventSink.m_pDlg = this;
 m_DocEventSink.DispEventAdvise(m_spDocument);
 m_WndEventSink.DispEventAdvise(m_spWindow);

Now we are ready to work with graphics. Let's create the layer and text:

 ILayerPtr spLayer;
 spLayer = m_spDocument->CreateLayer(-1, L"Layer");
 spLayer->Active = VARIANT_TRUE;
 ITextClassPtr spTextClass;
 spTextClass = spLayer->CreateClass(ciText, NULL, 0, 0);
 spTextClass->Styles->Alignment = taCenter;
 spTextClass->Create(0.01, 0.01, _bstr_t("Move this text" 
    " using\r\nmouse or open any\r\ndocument and move\r\nany shapes."));

Conclusion

Vector Graphics ActiveX is the easiest way to add vector graphics support to your applications and improve their power. Moreover developers get full control of all objects at run-time so they can not only process graphic documents, but analyze and visualize any kind of processes and much more.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here