imageflatview.cpp

来自「VC++6开发指南的源代码第24章-第25章」· C++ 代码 · 共 327 行

CPP
327
字号
// ImageFlatView.cpp : implementation of the CImageFlatView class
//

#include "stdafx.h"
#include "ImageFlat.h"

#include "ImageFlatDoc.h"
#include "ImageFlatView.h"

#include "ChildFrm.h"

#include "ZoomDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CImageFlatView

IMPLEMENT_DYNCREATE(CImageFlatView, CScrollView)

BEGIN_MESSAGE_MAP(CImageFlatView, CScrollView)
	//{{AFX_MSG_MAP(CImageFlatView)
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_MOUSEMOVE()
	ON_COMMAND(ID_ZOOM, OnZoom)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)

	ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUMXX, OnUpdateeIndicatorXX)
	ON_UPDATE_COMMAND_UI(ID_INDICATOR_NUMYY, OnUpdateeIndicatorYY)

END_MESSAGE_MAP()

	/*************************************************************************
 * 函数名称:Zoom(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight,
				   long lLineBytes,	WORD palSize, long lDstWidth, 
				   long lDstHeight,long lDstLineBytes,float	fXZoomRatio, float fYZoomRatio)
 * 函数参数:
 *   LPSTR lpSrcDib,				指向源DIB的指针
 *   LPSTR lpSrcStartBits,			指向源DIB的起始像素的指针
 *   long lWidth,					源DIB图像宽度
 *   long lHeight,					源DIB图像高度
 *	 long lLineBytes,				源DIB图像字节宽度(4的倍数)
 *	 WORD palSize,					源DIB图像调色板大小
 *	 long lDstWidth,					目标图像宽度
 *	 long lDstHeight,				目标DIB图像高度
 *	 long lDstLineBytes,				目标DIB图像行字节数(4的倍数)
 *	 float	fhorRatio,					水平缩放比率
 *	 float fverRatio,					垂直缩放比率
 * 函数类型:HGLOBAL
 * 函数功能:用来缩放DIB图像
 ************************************************************************/

HGLOBAL  Zoom(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight,
				   long lLineBytes,	WORD palSize,long lDstWidth,long lDstLineBytes,long lDstHeight,
				   float fhorRatio,float fverRatio)
{			
	LPSTR	lpDstDib;							//指向临时图像的指针	
	long i;                 						//行循环变量
	long j;                 						//列循环变量
	long i1;                 						//行循环变量
	long j1;                 						//列循环变量
	LPSTR	lpSrcDIBBits;						//指向源像素的指针
	LPSTR	lpDstDIBBits;						//指向临时图像对应像素的指针
	LPSTR	lpDstStartBits;						//指向临时图像对应像素的指针 	
	LPBITMAPINFOHEADER lpbmi;				// 指向BITMAPINFO结构的指针
	// 分配内存,以保存缩放后的DIB
HGLOBAL hDIB = (HGLOBAL) ::GlobalAlloc(GHND, lDstLineBytes* lDstHeight + 					*(LPDWORD)lpSrcDib +palSize);
	if (hDIB == NULL)							// 判断是否是有效的DIB对象
	{		
		return FALSE;							// 不是,则返回
	}		
	lpDstDib=  (char * )::GlobalLock((HGLOBAL) hDIB);// 锁定内存		
	memcpy(lpDstDib, lpSrcDib, *(LPDWORD)lpSrcDib +palSize);// 复制DIB信息头和调色板
	lpDstStartBits=lpDstDib+ *(LPDWORD)lpDstDib+palSize;// 找到新DIB像素起始位置
	lpbmi = (LPBITMAPINFOHEADER)lpDstDib;		// 获取指针
	lpbmi->biWidth = lDstWidth;					// 更新DIB中图像的高度和宽度
	lpbmi->biHeight =lDstHeight;	
	for(i = 0; i < lDstHeight; i++)					// 行操作
	{		
		for(j = 0; j < lDstWidth; j++)					// 列操作
		{
			// 指向新DIB第i行,第j个像素的指针
			lpDstDIBBits= (char *)lpDstStartBits + lDstLineBytes * (lDstHeight-1-i)+j;		
			i1= (long) (i / fverRatio + 0.5);			// 计算该像素在源DIB中的坐标
			j1= (long) (j / fhorRatio + 0.5);			
			if( (j1>= 0) && (j1< lWidth) && (i1>= 0) && (i1< lHeight))
			{				
				// 指向源DIB第i行,第j个像素的指针
lpSrcDIBBits= (char *)lpSrcStartBits+ lLineBytes * (lHeight - 1 -i1) + j1;	
				*lpDstDIBBits= *lpSrcDIBBits;		// 复制像素
			}
			else
			{
				* ((unsigned char*)lpDstDIBBits) = 255;// 源图中不存在的像素,赋为255
			}				
		}		
	}
	return hDIB;
}
/////////////////////////////////////////////////////////////////////////////
// CImageFlatView construction/destruction

CImageFlatView::CImageFlatView()
{
	// TODO: add construction code here

}

CImageFlatView::~CImageFlatView()
{
}

BOOL CImageFlatView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CScrollView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CImageFlatView drawing

void CImageFlatView::OnDraw(CDC* pDC)
{
	CImageFlatDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	HGLOBAL hDIB = pDoc->GetHObject();	
	if (hDIB != NULL)							   	//判断DIB是否为空
	{
		LPSTR lpDibSection = (LPSTR) ::GlobalLock(hDIB);				
		int cxDIB = (int) pDoc->m_dib.GetWidth(lpDibSection);		//获取DIB宽度				
		int cyDIB = (int) pDoc->m_dib.GetHeight(lpDibSection);		//获取DIB高度
		::GlobalUnlock(hDIB);		
		CRect rcDIB;
		rcDIB.top = rcDIB.left = 0;
		rcDIB.right = cxDIB;
		rcDIB.bottom = cyDIB;		
		CRect rcDest= rcDIB;			
		pDoc->m_dib.DrawDib(pDC->m_hDC, &rcDest, pDoc->GetHObject(),//重画DIB
			&rcDIB, pDoc->GetDocPal());
	}

}

void CImageFlatView::OnInitialUpdate()
{

	CImageFlatDoc* pDoc = GetDocument();
	CSize sizeTotal;
	// TODO: 计算此视图的总大小
	sizeTotal =pDoc->GetDocDimension();	
	SetScrollSizes(MM_TEXT, sizeTotal);
	m_pParent = ((CChildFrame*)GetParentFrame());
    m_pParent->ShowRulers();
    OnUpdate(NULL, 0, NULL);
	CScrollView::OnInitialUpdate();
}

/////////////////////////////////////////////////////////////////////////////
// CImageFlatView printing

BOOL CImageFlatView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CImageFlatView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CImageFlatView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CImageFlatView diagnostics

#ifdef _DEBUG
void CImageFlatView::AssertValid() const
{
	CScrollView::AssertValid();
}

void CImageFlatView::Dump(CDumpContext& dc) const
{
	CScrollView::Dump(dc);
}

CImageFlatDoc* CImageFlatView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CImageFlatDoc)));
	return (CImageFlatDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CImageFlatView message handlers
void  CImageFlatView::UpdateRulersInfo(int nMessage, CPoint ScrollPos,CPoint Pos)
{
	if (!m_pParent)
        return;
	CImageFlatDoc* pDoc = GetDocument();
	m_ImageSize = pDoc->GetDocDimension();//图像尺寸
	stRULER_INFO pRulerInfo;//标尺结构体
    pRulerInfo.uMessage    = nMessage;
    pRulerInfo.ScrollPos   = ScrollPos;
    pRulerInfo.DocSize     = m_ImageSize;
	pRulerInfo.Pos         = Pos;
	m_pParent->UpdateRulersInfo(pRulerInfo);//标尺的更新
}

void CImageFlatView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
	// TODO: Add your specialized code here and/or call the base class
	UpdateRulersInfo(RW_POSITION, GetScrollPosition());
    Invalidate();	
}

void CImageFlatView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	UpdateRulersInfo(RW_HSCROLL, GetScrollPosition());
	CScrollView::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CImageFlatView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	UpdateRulersInfo(RW_VSCROLL, GetScrollPosition());
	CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CImageFlatView::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CPoint Scro;
	Scro = GetScrollPosition();
	Mouse_xx = point.x + Scro.x;
	Mouse_yy = point.y + Scro.y;

	UpdateRulersInfo(RW_POSITION, GetScrollPosition(), point);
	CScrollView::OnMouseMove(nFlags, point);
}

//状态栏显示坐标
void CImageFlatView::OnUpdateeIndicatorXX(CCmdUI* pCmdUI)
{	CString strXY;
	strXY.Format("X:%d",Mouse_xx);
	pCmdUI->Enable(TRUE);
	pCmdUI->SetText(strXY);
}
void CImageFlatView::OnUpdateeIndicatorYY(CCmdUI* pCmdUI)
{
	CString strXY;
	strXY.Format("Y:%d",Mouse_yy);
	pCmdUI->Enable(TRUE);
	pCmdUI->SetText(strXY);
}

void CImageFlatView::OnZoom() 
{
	// TODO: Add your command handler code here
	// TODO: Add your command handler code here
	CImageFlatDoc* pDoc = GetDocument();		
	long lSrcLineBytes;							//图像每行的字节数
	long	lSrcWidth;     						 	//图像的宽度和高度
	long	lSrcHeight;
	LPSTR	lpSrcDib;							//指向源图像的指针	
	LPSTR	lpSrcStartBits;						//指向源像素的指针
	long	lDstWidth;      						//临时图像的宽度和高度
	long	lDstHeight;
	long lDstLineBytes;
	lpSrcDib= (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHObject());// 锁定DIB
	if (pDoc->m_dib.GetColorNum(lpSrcDib) != 256)		// 判断是否是8-bpp位图
	{		
		   AfxMessageBox("对不起,不是256色位图!");// 警告				
		   ::GlobalUnlock((HGLOBAL) pDoc->GetHObject());// 解除锁定		
		   return;								//返回
	 }	
	lpSrcStartBits=pDoc->m_dib.GetBits(lpSrcDib);		// 找到DIB图像像素起始位置	
	lSrcWidth= pDoc->m_dib.GetWidth(lpSrcDib);		// 获取图像的宽度		
	lSrcHeight= pDoc->m_dib.GetHeight(lpSrcDib);		// 获取图像的高度		
	lSrcLineBytes=pDoc->m_dib.GetReqByteWidth(lSrcWidth * 8);// 计算图像每行的字节数
	DWORD palSize=pDoc->m_dib.GetPalSize(lpSrcDib);	
	ZoomDlg ZoomPara;							// 创建对话框,设定平移量
	if (ZoomPara.DoModal() != IDOK)
	{
		return;	
	}
	float fX = ZoomPara.m_horZoom;					// 获取设定的平移量,缩放比率
	float fY = ZoomPara.m_verZoom;
// 计算缩放后的图像实际宽度,加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分
	lDstWidth= (long) (lSrcWidth*fX + 0.5);			//转换后图像应有的行字节数,为4的倍数
	lDstLineBytes=pDoc->m_dib.GetReqByteWidth(lDstWidth * 8); 
	lDstHeight= (long) (lSrcHeight * fY + 0.5);			// 计算缩放后的图像高度
	HGLOBAL hDstDIB = NULL;					// 创建新DIB	
	hDstDIB = (HGLOBAL) Zoom(lpSrcDib,lpSrcStartBits,lSrcWidth,lSrcHeight,
		lSrcLineBytes,palSize,lDstWidth,lDstLineBytes,lDstHeight,fX, fY);// 调用Zoom()函数转置
	if(hDstDIB != NULL)							// 判断旋转是否成功
	{				
		pDoc->UpdateObject(hDstDIB);				// 替换DIB,同时释放旧DIB对象
		pDoc->SetDib();							// 更新DIB大小和调色板
		pDoc->SetModifiedFlag(TRUE);				// 设置脏标记		
		pDoc->UpdateAllViews(NULL);				// 更新视图		
		::GlobalUnlock((HGLOBAL) pDoc->GetHObject());// 解除锁定
	}
	else
	{		
		AfxMessageBox(_T("分配内存失败!"));		// 警告	
	}	

	
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?