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 + -
显示快捷键?