65.9K
CodeProject 正在变化。 阅读更多。
Home

将 IPicture 流式传输到复合文档文件

2001年10月29日

1分钟阅读

viewsIcon

113939

downloadIcon

3018

IPicture 对象的序列化

Sample Image - PictureStream.jpg

引言

我非常喜欢 IPicture 对象。这个 COM 对象工作得很好。然而,当我尝试在文档-视图架构中使用这个对象时遇到了一些问题。主要问题是序列化的实现。我构建了两个类来解决这些问题。第一个类叫做 CPictureObj。这个类负责绘制图片。第二个类是图片对象的集合。通过使用这两个类,很容易实现以下功能:

  • 将一个或多个图像加载到文档中(*.bmp、*.jpeg、*.ico,...)
  • 缩放图像(放大、缩小)
  • 通过光标移动图像
  • 对齐
  • 将图像保存/加载到/从复合文档文件中。

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);
	
// 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);

};

使用这些类

要使用流式传输图片,请创建从 COleDocument 派生的文档对象。

class CYourDoc : public COleDocument

在文档对象内部,像这样定义一个图片集合:

CPictureObjList	m_objects;

现在,您可以使用这个简单的方法插入图片:

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

您也可以直接从文件加载图片:

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

要缩放图片,可以使用 ZoomIn、ZoomOut 成员函数:

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

移动选定的图片很简单:

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

绘制图片集合也很容易:

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

您可以从这里获取图片序列化的实现:

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();
	}
}

祝您好运!

© . All rights reserved.