Streaming IPicture object

Sample Image

Environment: VC++ 5.0-6.0, NT 4.0,Win2000, Win95/98

I really like the IPicture object. This COM object works very fine. However, I had some problem when I was trying to use it in a Document-View architecture. The main problem is implementation of serialization. To resolve this problem I built two classes.

The first class called CPictureObj. This class is responsible for drawing the picture. The second class, CPictureObjList, is a collection of picture objects. By using both of these classes it is easy to implement the following functionality:

  • Load one or more images into document (*.bmp, *.jpeg, *.ico,etc...)
  • Scale images(Zoom In, Zoom Out)
  • Move images by cursor
  • Alignment
  • Save/Load images to/from compound document file.

Classes

class CPictureObj  :  
           public CPictureHolder, public CObject
{
  DECLARE_SERIAL(CPictureObj);
public:
  CPictureObj();
  CPictureObj(const CRect position);
  virtual ~CPictureObj();
  void RemoveAndDestroy();

  virtual void Copy( CPictureObj &right);
  virtual HRESULT WriteToStream(IStream* pStream);
  virtual HRESULT ReadFromStream(IStream* pStream);
  
// Attributes
public:
  HorzAlign GetHorzAlign( void ) const;
  void      SetHorzAlign( HorzAlign eHorzAlign );
  VertAlign GetVertAlign( void ) const;
  void      SetVertAlign( VertAlign eVertAlign );
  BOOL      GetSelected( void ) const;
  void      SetSelected( BOOL bValue );
  void      SetVisible(BOOL bValue);
  BOOL      GetVisible();
  CRect     GetPosition();
  void      SetPosition(const CRect pos);
  CRect     GetStartRect();
  void      SetStartRect(const CRect pos);
  CString   GetPathName();
  void      SetPathName(const CString pathname);

  OLE_HANDLE GetHandle();
  CSize      GetSize();          // in himetric
  CSize      GetSize(CDC*pDC);   // in pixel
  CSize      GetSize(CWnd*pWnd); // in pixel
  BOOL       IsValidPicture();

// Operations
public:

  BOOL Load(LPCTSTR szFile);
  BOOL CreateFromFile(const CPoint pt);
  void ReleasePicture();
  void MoveTo(const CRect& position, CWnd* pView);

  // Drawing picture
  void Draw(CDC* pDC);
  void Draw(CDC* pDC, CRect& rcBounds);
  void Draw(CDC* pDC, const CRect& 
            rcPosition, const CRect& rcBounds);
  void DrawTracker(CDC* pDC);
  void DrawTracker(CDC* pDC, const CRect& rect);
  void ZoomIn();
  void ZoomOut();

protected:

  void CalcZoom();
  void SetZoomToPosition();

protected:

  HorzAlign m_eHorizAlign;
  VertAlign m_eVertAlign;
  BOOL      m_bSelected;
  BOOL      m_bVisible;
  CRect     m_rcPosition; // in pixels
  CRect     m_startRect;  // in pixels
  int       m_trackerStyle;
  int       m_zoomX,m_zoomY;

  // Not serialized
  CString   m_strPathName;

};

class CPictureObjList : public CTypedPtrList{CObList, CPictureObj*}
{
public:
  ~CPictureObjList();

  void RemoveAndDestroy();
  void DeselectAll();

  CSize ComputeMaxSize();           // in himetric
  CSize ComputeMaxSize(CDC* pDC);   // in pixel
  CSize ComputeMaxSize(CWnd* pWnd); // in pixel
  CRect GetRect();                  // in pixel

  CPictureObj* FindSelected();
  CPictureObj* ObjectAt(const CPoint& pt);
  bool Remove(CPictureObj* pObj);
  void Draw(CDC* pDC);

  // Streaming
  HRESULT WriteToStream(IStream* pStream);
  HRESULT ReadFromStream(IStream* pStream);
  BOOL WriteToStorage(LPSTORAGE lpRootStg);
  BOOL ReadFromStorage(LPSTORAGE lpRootStg);

};

Using the classes.

For use streaming picture create your document object derived from COleDocument.

class CYourDoc : public COleDocument

Define inside of document object the picture collection like here:

CPictureObjList  m_objects;

Now, you can insert picture by simple way:

CPictureObj* pObj =  new CPictureObj;
pObj->CreateFromFile(CPoint(10,10));
m_objects.AddHead(pObj);

Also, you can load picture directly from the file:

CPictureObj* pObj =  new CPictureObj;
pObj->Load("MyFile.jpg");
m_objects.AddHead(pObj);

For scaling picture you can use ZoomIn, ZoomOut member functions:

CPictureObj* pObj = m_objects.FindSelected();
if(pObj)
{
    pObj->ZoomIn();
}

Moving the selected picture is easy:

CPoint delta = point - c_last;
CPictureObj* pSel = m_objects.FindSelected();
if(pSel)
{
  CRect position = pSel->GetPosition();
  position += delta;
  pSel->MoveTo(position, this);
}

Drawing collection of pictures is also easy:

GetDocument()->m_objects.Draw(pDC);

Implementation of picture serialization you can get from here:

void CYourDoc::Serialize(CArchive& ar)
{
 CWaitCursor wait;
 COleDocument::Serialize(ar);
 if (ar.IsStoring())
 {
    m_objects.WriteToStorage(m_lpRootStg); 
 }
 else
 { 
    m_objects.ReadFromStorage(m_lpRootStg);
    m_objects.DeselectAll();
 }
}

Downloads

Download demo project - 150 Kb
Download source - 6.48 Kb


Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date