Introduction
I really like the IPicture
object. This COM object works very well.
However, I met some problems when I was trying to use this object in the Document-View architecture.
The main problem is implementation of serialization. I built two classes to resolve those problems.
The first class called CPictureObj
. This class is responsible for drawing picture. The second one is collection of picture objects.
By using both of them it is easy to implement the following functionality:
- Load one or more images into document (*.bmp, *.jpeg, *.ico,...)
- Scaling images (Zoom In, Zoom Out)
- Move images by cursor
- Alignment
- Save/Load images to/from compound document file.
Classes
class <code>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);
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();
CSize GetSize(CDC*pDC);
CSize GetSize(CWnd*pWnd);
BOOL IsValidPicture();
public:
BOOL Load(LPCTSTR szFile);
BOOL CreateFromFile(const CPoint pt);
void ReleasePicture();
void MoveTo(const CRect& position, CWnd* pView);
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;
CRect m_startRect;
int m_trackerStyle;
int m_zoomX,m_zoomY;
CString m_strPathName;
};
class CPictureObjList : public CTypedPtrList {CObList, CPictureObj*}
{
public :
~CPictureObjList();
void RemoveAndDestroy();
void DeselectAll();
CSize ComputeMaxSize();
CSize ComputeMaxSize(CDC* pDC);
CSize ComputeMaxSize(CWnd* pWnd);
CRect GetRect();
CPictureObj* FindSelected();
CPictureObj* ObjectAt(const CPoint& pt);
bool Remove(CPictureObj* pObj);
void Draw(CDC* pDC);
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
Inside of the document object define a picture collection like here:
CPictureObjList m_objects;
Now, you can insert picture by this simple method:
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 pictures you can use the 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 a 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();
}
}
Good luck!