(1)实现原理:将图像分成不同的区域小块,然后按照一定的方向、顺序先后显示在屏幕上。
(2)图像块的显示:一般使用下面这个函数进行处理
BOOL CDC::BitBIt(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,int xSrc,int ySrc,DWORD dwRop);
BitBlt的全称是 Bit Block Transfer(位块传输),专门用于将源设备上下文的一部分图像直接传送到当前设备上下文中。BitBlt函数实际完成的功能是图像的内存复制,所以效率很高。
(3)延时:图像的显示特效是通过图像的显示过程体现出来的,由于计算机处理速度太快,所以为了明星表现整个显示过程,需要加入延时函数。一个好的延时函数必须满足两个条件:一、精确延时,至少精确到毫秒级;二、延时函数与计算机的运行速度无关。延时函数如下:
void CMyEffectDisplay::DelayTime(DWORD dwMilliseconds){ LARGE_INTEGER litmp; LONGLONG lTimeBeign; LONGLONG lTimeEnd; double dMinus; double dFreq; double dTim; QueryPerformanceFrequency(&litmp); // 获得机器内部定时器的时钟频率 dFreq = (double)litmp.QuadPart; // 获得计数器的时钟频率 QueryPerformanceCounter(&litmp); lTimeBeign = litmp.QuadPart; // 获得时间起始值 do { QueryPerformanceCounter(&litmp); lTimeEnd = litmp.QuadPart; //获得中止值 dMinus = (double)(lTimeEnd - lTimeBeign); dTim = dMinus / dFreq; // 获得对应的时间值,单位为秒 } while (dTim < dwMilliseconds * 0.001);}
首先在CMyEffectDisplay头文件声明一些变量:
static int s_nOffsetX; // 图像在内存CDC中的X偏移量 static int s_nOffsetY; // 图像在内存CDC中的Y偏移量 static int s_nPicWidth; // 图像的宽度 static int s_nPicHeight; // 图像的高度 static int s_nCDCWidth; // 内存CDC的宽度 static int s_nCDCHeight; // 内存CDC的高度
然后再OnDraw函数中做一些准备工作:
CRect rect; GetClientRect(rect); CDC memDC; CBitmap MemBitmap; memDC.CreateCompatibleDC(NULL); MemBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()); memDC.SelectObject(MemBitmap); memDC.FillSolidRect(rect, RGB(255, 255, 255)); Image image(_T("E:\\素材\\jpg\\1.jpg")); Graphics graph(memDC.GetSafeHdc()); graph.DrawImage(&image, 0, 0); CMyEffectDisplay::s_nOffsetX = 0; CMyEffectDisplay::s_nOffsetY = 0; CMyEffectDisplay::s_nCDCWidth = rect.Width(); CMyEffectDisplay::s_nCDCHeight = rect.Height(); CMyEffectDisplay::s_nPicWidth = image.GetWidth(); CMyEffectDisplay::s_nPicHeight = image.GetHeight(); // CMyEffectDisplay::ScanDownDisplay(pDC, &memDC); // 函数调用 ...
一、向下扫描特效实现
void CMyEffectDisplay::ScanDownDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); // 扫描宽度 int nWidth = min(s_nPicWidth, s_nCDCWidth); for (int i = 0; i <= nHeight; i += 1) { pDC->BitBlt(s_nOffsetX, i + s_nOffsetY, nWidth, 1, pMemDC, s_nOffsetX, i + s_nOffsetY, SRCCOPY); DelayTime(1); }}
二、垂直双重扫描特效实现
void CMyEffectDisplay::VSScanDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); // 扫描宽度 int nWidth = min(s_nPicWidth, s_nCDCWidth); for (int i = 0; i <= nHeight / 2; i += 1) { // 向下扫描 pDC->BitBlt(s_nOffsetX, i + s_nOffsetY, nWidth, 1, pMemDC, s_nOffsetX, i + s_nOffsetY, SRCCOPY); // 向上扫描 pDC->BitBlt(s_nOffsetX, nHeight - i - 1, nWidth, 1, pMemDC, s_nOffsetX, nHeight - i - 1, SRCCOPY); // 延时 DelayTime(2); }}
三、向右移动特效实现:
void CMyEffectDisplay::MoveRightDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); for (int i = 0; i <= s_nCDCWidth - s_nOffsetX; i += 2) { pDC->BitBlt(0, s_nOffsetY, i, nHeight, pMemDC, s_nCDCWidth - s_nOffsetX - i, s_nOffsetY, SRCCOPY); DelayTime(1); } // 修正图像位置 pDC->BitBlt(0, s_nOffsetY, s_nCDCWidth - s_nOffsetX, nHeight, pMemDC, 0, s_nOffsetY, SRCCOPY);}
四、水平双重移动特效实现:
void CMyEffectDisplay::HSMoveDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); // 扫描宽度 int nWidth = min(s_nPicWidth, s_nCDCWidth); for (int i = 0; i <= s_nCDCWidth / 2; i += 2) { // 左面部分 pDC->BitBlt(0, s_nOffsetY, i, nHeight, pMemDC, nWidth / 2 - i + s_nOffsetX, s_nOffsetY, SRCCOPY); // 右面部分 pDC->BitBlt(s_nCDCWidth - i, s_nOffsetY, i, nHeight, pMemDC, nWidth / 2 + s_nOffsetX, s_nOffsetY, SRCCOPY); DelayTime(1); } // 修正图像位置 pDC->BitBlt(0, s_nOffsetY, s_nCDCWidth - s_nOffsetX, nHeight, pMemDC, 0, s_nOffsetY, SRCCOPY);}
五、垂直百叶窗特效实现
void CMyEffectDisplay::VBlindDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); // 扫描宽度 int nWidth = min(s_nPicWidth, s_nCDCWidth); // 百叶窗宽度 int nScanLine = 8; for (int i = 0; i < nScanLine; i++) // 循环8次,即分8列显示 { for (int j = 0; j < nWidth; j += nScanLine) { pDC->BitBlt(j + i + s_nOffsetX, s_nOffsetY, 1, nHeight, pMemDC, j + i + s_nOffsetX, s_nOffsetY, SRCCOPY); } DelayTime(200); }}
六、水平百叶窗特效实现
void CMyEffectDisplay::HBlindDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); // 扫描宽度 int nWidth = min(s_nPicWidth, s_nCDCWidth); // 百叶窗宽度 int nScanLine = 8; for (int i = 0; i < nScanLine; i++) { for (int j = 0; j < nHeight; j += nScanLine) { pDC->BitBlt(s_nOffsetX, j + i + s_nOffsetY, nWidth, 1, pMemDC, s_nOffsetX, j + i + s_nOffsetY, SRCCOPY); } DelayTime(200); }}
七、垂直栅条特效实现
void CMyEffectDisplay::VRasterDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); // 扫描宽度 int nWidth = min(s_nPicWidth, s_nCDCWidth); int nScanLine = 16; for (int i = 0; i <= nHeight + s_nOffsetY; i++) { for (int j = 0; j <= nWidth; j += 2 * nScanLine) { pDC->BitBlt(j + s_nOffsetX, 0, nScanLine, i, pMemDC, j + s_nOffsetX, nHeight + s_nOffsetY - i, SRCCOPY); int k = j + nScanLine; pDC->BitBlt(k + s_nOffsetX, nHeight + s_nOffsetY - i, nScanLine, i + s_nOffsetY, pMemDC, k + s_nOffsetX, 0, SRCCOPY); } DelayTime(1); }}
八、水平栅条特效实现
void CMyEffectDisplay::HRasterDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); // 扫描宽度 int nWidth = min(s_nPicWidth, s_nCDCWidth); int nScanLine = 16; for (int i = 0; i <= nWidth + s_nOffsetX; i++) { for (int j = 0; j <= nHeight; j += 2 * nScanLine) { pDC->BitBlt(0, j + s_nOffsetY, i, nScanLine, pMemDC, nWidth + s_nOffsetX - i, j + s_nOffsetY, SRCCOPY); int k = j + nScanLine; pDC->BitBlt(nWidth + s_nOffsetX - i, k + s_nOffsetY, i + s_nOffsetX, nScanLine, pMemDC, 0, k + s_nOffsetY, SRCCOPY); } DelayTime(1); }}
九、马赛克特效实现
void CMyEffectDisplay::MosaicDisplay(CDC* pDC, CDC* pMemDC){ int nTileSize = 24; // 马赛克小方块大小 int nRw = 0; int nRh = 0; if (s_nPicWidth % nTileSize != 0) nRw = 1; if (s_nPicHeight % nTileSize != 0) nRh = 1; // 计算小方块的个数 int nTileCount = (s_nPicWidth / nTileSize + nRw) * (s_nPicHeight / nTileSize + nRh); CPtrArray points; // 保存所有小方块的左上坐标 long lx = 0; long ly = 0; for (int k = 0; k < nTileCount; k++) { CPoint* point = new CPoint; point->x = lx; point->y = ly; lx = lx + nTileSize; if (lx >= s_nPicWidth) { lx = 0; ly = ly + nTileSize; } points.Add(point); } int nDelayTime = 2; if (s_nPicHeight * s_nPicWidth > 600 * 500) nDelayTime = 1; LARGE_INTEGER seed; QueryPerformanceFrequency(&seed); QueryPerformanceCounter(&seed); //初始化一个以微秒为单位的时间种子 srand((int)seed.QuadPart); for (int i = nTileCount - 1; i >= 0; i--) { int n = rand() % (i + 1); CPoint* point = (CPoint*)points[n]; lx = point->x; ly = point->y; pDC->BitBlt(lx + s_nOffsetX, ly + s_nOffsetY, nTileSize, nTileSize, pMemDC, lx + s_nOffsetX, ly + s_nOffsetY, SRCCOPY); /*SAFE_DELETE(point);*/ if (point != NULL) { delete point; point = NULL; } points.RemoveAt(n); DelayTime(nDelayTime); }}
十、雨滴特效实现
void CMyEffectDisplay::RaindropDisplay(CDC* pDC, CDC* pMemDC){ // 扫描高度 int nHeight = min(s_nPicHeight, s_nCDCHeight); // 扫描宽度 int nWidth = min(s_nPicWidth, s_nCDCWidth); for (int i = 0; i <= nHeight + s_nOffsetY; i++) { for (int j = 0; j <= nHeight + s_nOffsetY - i; j++) { pDC->BitBlt(s_nOffsetX, j, nWidth, 1, pMemDC, s_nOffsetX, nHeight + s_nOffsetY - i, SRCCOPY); } DelayTime(1); }}