一个比较简单的效果。在对话框上放几个单项选择,当用户改变选择时,在对话框上有一个LOGO性质的图片进行渐变性的切换,已反应当前的选择。实现的代码量很小。我从网络上下载了三个足球俱乐部LOGO的壁纸图片,首先把它们缩放到同样的尺寸,然后添加为图片资源。在程序运行时,随着选择的改变,从当前图片逐渐过渡到另一张图片。
开发工具:VC6.0;
相关API: GetDIBs, SetDIBitsToDevice;
运行效果如下:
主题代码量很小,所以可以完整列出如下:
CODE_ImgSwitch
#include "stdafx.h"
#include <stdlib.h>
#include "resource.h"
#define ID_TIMER 1
HINSTANCE hInst;
//global variables
BYTE* lpCurBits; //当前显示用的
BYTE* lpCacheBits; //DIB临时存储区
//三幅图片
BYTE* lpBits[3];
//信息头
BITMAPINFO bminfo;
//图片所在矩形~
RECT rcImg;
//functions;
//准备工作
void DoPrepare(HWND hDlg);
LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
void GetNextDIB(int percent, int iSel);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
hInst = hInstance;
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL,
(DLGPROC)MyDlgProc, 0);
return 0;
}
//准备工作
void DoPrepare(HWND hDlg)
{
HBITMAP hBitmap;
BITMAP bm;
int i, stride;
HDC hdc = GetDC(hDlg);
//HDC hMemDC = CreateCompatibleDC(hdc);
//ReleaseDC(hDlg, hdc);
for(i=0; i<3; i++)
{
hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1 + i));
if(i == 0)
{
GetObject(hBitmap, sizeof(BITMAP), &bm);
//图片所在客户区矩形
rcImg.left = 0;
rcImg.top = 0;
rcImg.right = bm.bmWidth;
rcImg.bottom = bm.bmHeight;
//bminfo
//扫描行宽度(实际上图片大小一致)
stride = (bm.bmWidth * 24 + 31) / 32 * 4;
bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 24;
bminfo.bmiHeader.biWidth = bm.bmWidth;
bminfo.bmiHeader.biHeight = bm.bmHeight;
bminfo.bmiHeader.biSizeImage = bm.bmHeight * stride;
}
//lpBits[i] = (BYTE*)bm.bmBits;
lpBits[i] = (BYTE*)malloc(bminfo.bmiHeader.biSizeImage);
GetDIBits(hdc, hBitmap, 0, bminfo.bmiHeader.biHeight, lpBits[i], &bminfo, DIB_RGB_COLORS);
DeleteObject(hBitmap);
}
ReleaseDC(hDlg, hdc);
//DeleteDC(hMemDC);
//创建当前显示的DIB
lpCurBits = (BYTE*)malloc(bminfo.bmiHeader.biSizeImage);
memcpy(lpCurBits, lpBits[0], bminfo.bmiHeader.biSizeImage);
lpCacheBits = (BYTE*)malloc(bminfo.bmiHeader.biSizeImage);
}
//the dlg's window procedure
LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static int iSel;
//当前百分比(当为100时,停止计时器)
static int percent;
switch (message)
{
case WM_INITDIALOG:
{
DoPrepare(hDlg);
//默认选中第一个选项
CheckDlgButton(hDlg, IDC_RADIO1, BST_CHECKED);
iSel = 0;
percent = 0;
return TRUE;
}
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
break;
case IDC_RADIO1:
case IDC_RADIO2:
case IDC_RADIO3:
iSel = LOWORD(wParam) - IDC_RADIO1;
percent = 100;
//把当前位图拷贝到缓冲区
memcpy(lpCacheBits, lpCurBits, bminfo.bmiHeader.biSizeImage);
SetTimer(hDlg, ID_TIMER, 20, NULL);
break;
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hDlg, &ps);
SetDIBitsToDevice(hdc,
0, 0, rcImg.right, rcImg.bottom,
0, 0,
0, bminfo.bmiHeader.biHeight,
lpCurBits,
&bminfo,
DIB_RGB_COLORS);
EndPaint(hDlg, &ps);
}
break;
case WM_TIMER:
{
if(percent <= 0)
{
KillTimer(hDlg, ID_TIMER);
return TRUE;
}
percent -= 5;
GetNextDIB(percent, iSel);
InvalidateRect(hDlg, &rcImg, FALSE);
return TRUE;
}
break;
case WM_DESTROY:
{
int i;
for(i=0; i<3; i++)
{
free(lpBits[i]);
}
free(lpCurBits);
free(lpCacheBits);
}
return TRUE;
}
return FALSE;
}
//已当前百分比进行混合图像
// 100 0
//percent: 混合百分比 当前图片|------------------>|目标图片
// |---percent-->|
//destDIB: 目标DIB
void GetNextDIB(int percent, int iSel)
{
unsigned int i;
int x1, x2;
for(i=0; i<bminfo.bmiHeader.biSizeImage; i++)
{
x1 = lpCacheBits[i];
x2 = lpBits[iSel][i];
lpCurBits[i] = (BYTE)((x1*percent + x2*(100-percent) )/100);
}
}
源代码下载链接:
http://files.cnblogs.com/hoodlum1980/ImgSwitch.rar