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
classCPictureObj
:
publicCPictureHolder
, publicCObject
{
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
: publicCTypedPtrList
{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 pixelCPictureObj* 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();
}
}