一个比较简单的效果。在对话框上放几个单项选择,当用户改变选择时,在对话框上有一个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 );
}
}
#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 );
}
}
源代码下载链接: