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

More by Author

Must Read