📄 imageotherspreadview.cpp
字号:
// ImageOtherSpreadView.cpp : implementation of the CImageOtherSpreadView class
//
#include "stdafx.h"
#include "ImageOtherSpread.h"
#include "ImageOtherSpreadDoc.h"
#include "ImageOtherSpreadView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "math.h"
#include "BorderRect.h"
#include "ImageSSDialog.h"
/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView
IMPLEMENT_DYNCREATE(CImageOtherSpreadView, CView)
BEGIN_MESSAGE_MAP(CImageOtherSpreadView, CView)
//{{AFX_MSG_MAP(CImageOtherSpreadView)
ON_WM_CREATE()
ON_COMMAND(IDM_OTHER_SPREAD_WAY, OnOtherSpreadWay)
ON_UPDATE_COMMAND_UI(IDM_OTHER_SPREAD_WAY, OnUpdateOtherSpreadWay)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView construction/destruction
CImageOtherSpreadView::CImageOtherSpreadView()
{
// TODO: add construction code here
m_nWay = rhombus_outward;
}
CImageOtherSpreadView::~CImageOtherSpreadView()
{
}
BOOL CImageOtherSpreadView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView drawing
void CImageOtherSpreadView::OnDraw(CDC* pDC)
{
BeginWaitCursor();
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = memDC.SelectObject(&m_bitmap);
CRect clientRect;
GetClientRect(&clientRect);
int cx = clientRect.Width();
int cy = clientRect.Height();
pDC->BitBlt(0, 0, cx, cy, &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(pOldBitmap);
EndWaitCursor();
SpreadInto(pDC);
}
/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView diagnostics
#ifdef _DEBUG
void CImageOtherSpreadView::AssertValid() const
{
CView::AssertValid();
}
void CImageOtherSpreadView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CImageOtherSpreadDoc* CImageOtherSpreadView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CImageOtherSpreadDoc)));
return (CImageOtherSpreadDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView message handlers
int CImageOtherSpreadView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
//打开文件
CDib* pBackDib = new CDib("back.bmp");
if (!pBackDib->IsValid())
MessageBox("文件打开出错", "文件 \"back.bmp\"",
MB_OK | MB_ICONEXCLAMATION);
//
CClientDC dc(this);
m_bitmap.CreateCompatibleBitmap(&dc, 800, 600);
CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap* pOldBitmap = memDC.SelectObject(&m_bitmap);
CBrush* pBrush = new CBrush(RGB(255, 255, 255));
CRect rect(0, 0, 800, 600);
memDC.FillRect(rect, pBrush);
//绘制背景位图
if (pBackDib)
{
BYTE* pBackDibData = pBackDib->GetDibData();
LPBITMAPINFO pBackBmpInfo = pBackDib->GetBmpInfo();
int nWidth = (int)pBackDib->GetWidth();
int nHeight = (int)pBackDib->GetHeight();
StretchDIBits(memDC.m_hDC, 0, 0, nWidth, nHeight,
0, 0, nWidth, nHeight, pBackDibData, pBackBmpInfo,
DIB_RGB_COLORS, SRCCOPY);
}
memDC.SelectObject(pOldBitmap);
delete pBrush;
ReleaseDC(&dc);
if (pBackDib)
{
delete pBackDib;
pBackDib = NULL;
}
return 0;
}
void CImageOtherSpreadView::Delay(DWORD ms)
{
DWORD time = GetTickCount();
do{;}while((GetTickCount() - time) < ms);
}
void CImageOtherSpreadView::SpreadInto(CDC *pDC)
{
CImageOtherSpreadDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//第一步, 获取在文档中已经打开的位图
//获取外部DIB信息
CDib* pDib = pDoc->m_pDib;
if(!pDib)return;
int nWidth = (int)pDib->GetWidth();
int nHeight = (int)pDib->GetHeight();
//第二步, 将位图绘制到内存设备
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap ddb;
ddb.CreateCompatibleBitmap(pDC, nWidth, nHeight);
CBitmap* pOldBitmap = memDC.SelectObject(&ddb);
//把整个位图绘制到内存,
//更快的办法是将图像直接绘制到pDC
pDib->Draw(memDC.m_hDC, 0, 0, nWidth, nHeight,
0, 0, nWidth, nHeight, DIB_RGB_COLORS, SRCCOPY);
//第三步, 从内存设备中读出位图
CRect clientRect;
GetClientRect(&clientRect);
//左上角点
int cx = clientRect.Width();
int cy = clientRect.Height();
cx = (cx - nWidth) / 2;
cy = (cy - nHeight) / 2;
//绘制一个内嵌框
CBorderRect br(cx - 2, cy - 2, nWidth + 4, nHeight + 4);
br.Draw(pDC, FALSE);
//绘制坐标步长,
int nStepX, nStepY;
//求出宽度和高度的最大者
if(nWidth >= nHeight)
{
nStepX = 10;
nStepY = (int)(10.0f * ((float)nHeight / (float)nWidth) + 0.5f);
}
else
{
nStepY = 10;
nStepX = (int)(10.0f * ((float)nWidth / (float)nHeight) + 0.5f);
}
switch(m_nWay)
{
//菱形向外渐铺
//
case rhombus_outward:
{
//图像中心坐标
int nCenterX = cx + (nWidth / 2);
int nCenterY = cy + (nHeight / 2);
for(int x = nStepX, y = nStepY; x < nWidth; x += nStepX, y += nStepY)
{
//创建矩形剪切区域
CRgn rgn;
rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
pDC->SelectClipRgn(&rgn, RGN_COPY);
//创建菱形剪切区域, 并求交运算
CRgn rgnRhombus;
//菱形坐标
POINT point[4] = {nCenterX, (nCenterY - y), (nCenterX + x), nCenterY,
nCenterX, (nCenterY + y), (nCenterX - x), nCenterY};
rgnRhombus.CreatePolygonRgn(point, 4, WINDING);
pDC->SelectClipRgn(&rgnRhombus, RGN_AND);
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
rgnRhombus.DeleteObject();
pDC->SelectClipRgn(NULL, RGN_COPY);
Delay(20);
}
//由于少绘制一次, 所以必须补画最后一次
//如果把循环的判断变为(x < nWidth + nStepX)
//那么下面这条语句就没有必要了
//但是, 这样处理有两个好处:
//第一, 每做一次循环就少做一次加法运算
//第二, 少最后一次区域求交运算.
//但是, 这两点在视觉上是不会体会到的.
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
break;
}
//菱形向里渐铺
case rhombus_inward:
{
//图像中心坐标
int nCenterX = cx + (nWidth / 2);
int nCenterY = cy + (nHeight / 2);
for(int x = (nWidth - nStepX), y = (nHeight - nStepY); x > nStepX; x -= nStepX, y -= nStepY)
{
//创建矩形剪切区域
CRgn rgn;
rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
pDC->SelectClipRgn(&rgn, RGN_COPY);
//创建菱形剪切区域, 并求交运算
CRgn rgnRhombus;
POINT point[4] = {nCenterX, (nCenterY - y), (nCenterX + x), nCenterY,
nCenterX, (nCenterY + y), (nCenterX - x), nCenterY};
rgnRhombus.CreatePolygonRgn(point, 4, WINDING);
pDC->SelectClipRgn(&rgnRhombus, RGN_DIFF);//RGN_XOR略慢
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
rgnRhombus.DeleteObject();
pDC->SelectClipRgn(NULL, RGN_COPY);
Delay(20);
}
//循环少画一次, 再这里补一次
//如果循环多画一次, 可能在最后区域留下一点缺陷
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
break;
}
//圆形向外渐铺
case circle_outward:
{
//图像中心坐标
int nCenterX = cx + (nWidth / 2);
int nCenterY = cy + (nHeight / 2);
//圆的最大半径
int nMaxRadius = (int)sqrt(nWidth * nWidth + nHeight * nHeight) / 2;
for(int r = 10; r < nMaxRadius; r += 10)
{
//创建矩形剪切区域
CRgn rgn;
rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
pDC->SelectClipRgn(&rgn, RGN_COPY);
//创建圆形剪切区域, 并求交运算
CRgn rgnCirlce;
rgnCirlce.CreateEllipticRgn((nCenterX - r), (nCenterY - r), (nCenterX + r), (nCenterY + r));
pDC->SelectClipRgn(&rgnCirlce, RGN_AND);
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
rgnCirlce.DeleteObject();
pDC->SelectClipRgn(NULL, RGN_COPY);
Delay(25);
}
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
break;
}
//圆形向里渐铺
case circle_inward:
{
//图像中心坐标
int nCenterX = cx + (nWidth / 2);
int nCenterY = cy + (nHeight / 2);
//圆的最大半径
int nMaxRadius = (int)sqrt(nWidth * nWidth + nHeight * nHeight) / 2;
for(int r = (nMaxRadius - 10); r > 10; r -= 10)
{
//创建矩形剪切区域
CRgn rgn;
rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
pDC->SelectClipRgn(&rgn, RGN_COPY);
//创建圆形剪切区域, 并求交运算
CRgn rgnCirlce;
rgnCirlce.CreateEllipticRgn((nCenterX - r), (nCenterY - r), (nCenterX + r), (nCenterY + r));
pDC->SelectClipRgn(&rgnCirlce, RGN_DIFF);
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
rgnCirlce.DeleteObject();
pDC->SelectClipRgn(NULL, RGN_COPY);
Delay(25);
}
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
break;
}
//椭圆形向外渐铺
case ellipse_outward:
{
//图像中心坐标
int nCenterX = cx + (nWidth / 2);
int nCenterY = cy + (nHeight / 2);
//最大水平半轴
int nMaxAxisX = (int)(1.414f * nWidth + 0.5f) / 2;
for(int x = nStepX, y = nStepY; x < nMaxAxisX; x += nStepX, y += nStepY)
{
//创建矩形剪切区域
CRgn rgn;
rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
pDC->SelectClipRgn(&rgn, RGN_COPY);
//创建椭圆形剪切区域, 并求交运算
CRgn rgnEllipse;
rgnEllipse.CreateEllipticRgn((nCenterX - x), (nCenterY - y), (nCenterX + x), (nCenterY + y));
pDC->SelectClipRgn(&rgnEllipse, RGN_AND);
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
rgnEllipse.DeleteObject();
pDC->SelectClipRgn(NULL, RGN_COPY);
Delay(25);
}
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
break;
}
//椭圆形向里渐铺
case ellipse_inward:
{
//图像中心坐标
int nCenterX = cx + (nWidth / 2);
int nCenterY = cy + (nHeight / 2);
//最大水平半轴
int nMaxAxisX = (int)(1.414f * nWidth + 0.5f) / 2;
//最大垂直半轴
int nMaxAxisY = (int)(1.414f * nHeight + 0.5f) / 2;
for(int x = (nMaxAxisX - nStepX), y = (nMaxAxisY - nStepY); x > nStepX; x -= nStepX, y -= nStepY)
{
//创建矩形剪切区域
CRgn rgn;
rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
pDC->SelectClipRgn(&rgn, RGN_COPY);
//创建椭圆形剪切区域, 并求交运算
CRgn rgnEllipse;
rgnEllipse.CreateEllipticRgn((nCenterX - x), (nCenterY - y), (nCenterX + x), (nCenterY + y));
pDC->SelectClipRgn(&rgnEllipse, RGN_DIFF);
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
rgnEllipse.DeleteObject();
pDC->SelectClipRgn(NULL, RGN_COPY);
Delay(25);
}
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
break;
}
//水平帘窗式进入
case curtain_horizontal:
{
//条状高度
int nStripHeight = 16;
//条数
int nStrips = nHeight / 16;
//是否在最后还残留一点
BOOL bRemnant = (nHeight > nStrips * 16) ? TRUE : FALSE;
//可能的残留高度
int nRemnantHeight = nHeight - nStrips * 16;
for(int i = 1;i < nStripHeight;i++)
{
//坐标
int y = 0;
for(int n = 0; n < nStrips; n++)
{
pDC->BitBlt(cx, (cy + y), nWidth, i, &memDC, 0, y, SRCCOPY);
y += nStripHeight;
}
if((bRemnant) && (i < nRemnantHeight))
pDC->BitBlt(cx, (cy + y), nWidth, i, &memDC, 0, y, SRCCOPY);
Delay(35);
}
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
break;
}
//垂直帘窗式进入
case curtain_vertical:
{
//条状高度
int nStripWidth = 16;
//条数
int nStrips = nWidth / 16;
//是否在最后还残留一点
BOOL bRemnant = (nWidth > nStrips * 16) ? TRUE : FALSE;
//可能的残留宽度
int nRemnantWidth = nWidth - nStrips * 16;
for(int i = 1;i < nStripWidth;i++)
{
//坐标
int x = 0;
for(int n = 0; n < nStrips; n++)
{
pDC->BitBlt((cx + x), cy, i, nHeight, &memDC, x, 0, SRCCOPY);
x += nStripWidth;
}
if((bRemnant) && (i < nRemnantWidth))
pDC->BitBlt((cx + x), cy, i, nHeight, &memDC, x, 0, SRCCOPY);
Delay(35);
}
pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
break;
}
}
ddb.DeleteObject();
memDC.SelectObject(pOldBitmap);
}
void CImageOtherSpreadView::OnOtherSpreadWay()
{
// TODO: Add your command handler code here
CImageSSDialog dlg;
dlg.m_nWay = m_nWay;
int responeDlg = dlg.DoModal();
if(responeDlg == IDOK)
{
m_nWay = dlg.m_nWay;
Invalidate();
}
}
void CImageOtherSpreadView::OnUpdateOtherSpreadWay(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -