说好今天给大家写一个有点技术含量的博客的,今天就特意加班给大家送上。我认为是个难点也是比较适用的技术,就是怎样把位图的背景颜色去掉,这东西说起来简单,有ps就行了吗?但是我觉得要是自已写程序就可以办成功的话就更好了。恰好这本书上有讲到我就在这里写一下让大家都知道也让我对这个过程更深入一点(如果我有什么不对的地方,希望大牛们给予说明共同进步!!!)。
先说一下这个去掉背景颜色的一般思路:指定一种颜色,然后对这种颜色进行处理,使它的色素不画出来
先介绍介绍这个函数
TransparentBitmap(HDC hdc, HBITMAP hBitmap,short xStart,
short yStart, short xadd,short yadd, COLORREF cTransparentColor)
hdc显示句柄 hBitmap要显示的位图 xstart ystart显示的位置 xadd yadd是显示位图的大小变化 cTransparentColor就是背景的那个样色。代码如下:
void CMy1_6View::TransparentBitmap(HDC hdc, HBITMAP hBitmap,short xStart,
short yStart, short xadd,short yadd, COLORREF cTransparentColor)
{
BITMAP m_bm;
COLORREF cColor;
HDC hMem, hBack, hObject, hTemp, hSave;// 创建临时DC
hBack = CreateCompatibleDC(hdc);
hObject = CreateCompatibleDC(hdc);
hMem = CreateCompatibleDC(hdc);
hSave = CreateCompatibleDC(hdc);
hTemp = CreateCompatibleDC(hdc);
SelectObject(hTemp, hBitmap); // 选入位图
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&m_bm);
POINT ptSize; //显示位图宽高
ptSize.x = m_bm.bmWidth; // 取得位图的宽度
ptSize.y = m_bm.bmHeight; // 取得位图的该度
DPtoLP(hTemp, &ptSize, 1); // 转换为逻辑点值
HBITMAP bmBack, bmObject, bmMem, bmSave; // 创建临时位图
bmBack = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL); // 单色位图
bmObject = CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);
bmMem = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y); // 与设备兼容位图
bmSave = CreateCompatibleBitmap(hdc, ptSize.x, ptSize.y);
HBITMAP OldbmBack, OldbmObject, OldbmMem, OldbmSave; // 将创建的临时位图选入临时DC中
OldbmBack = (HBITMAP)SelectObject(hBack, bmBack);
OldbmObject = (HBITMAP)SelectObject(hObject, bmObject);
OldbmMem = (HBITMAP)SelectObject(hMem, bmMem);
OldbmSave = (HBITMAP)SelectObject(hSave, bmSave);
SetMapMode(hTemp, GetMapMode(hdc));// 设置映射模式
BitBlt(hSave, 0, 0, ptSize.x, ptSize.y, hTemp, 0, 0, SRCCOPY);// 先保留原始位图
cColor = SetBkColor(hTemp, cTransparentColor); // 将背景颜色设置为需透明的颜色
BitBlt(hObject, 0, 0, ptSize.x, ptSize.y, hTemp, 0, 0, SRCCOPY); // 创建目标屏蔽码
SetBkColor(hTemp, cColor);// 恢复源DC的原始背景色
BitBlt(hBack, 0, 0, ptSize.x, ptSize.y, hObject, 0, 0, NOTSRCCOPY);// 创建反转的目标屏蔽码
BitBlt(hMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, SRCCOPY); // 拷贝主DC的背景到目标DC
BitBlt(hMem, 0, 0, ptSize.x, ptSize.y, hObject, 0, 0, SRCAND); // 屏蔽位图的显示区
BitBlt(hTemp, 0, 0, ptSize.x, ptSize.y, hBack, 0, 0, SRCAND); // 屏蔽位图中的透明色
BitBlt(hMem, 0, 0, ptSize.x, ptSize.y, hTemp, 0, 0, SRCPAINT);// 将位图与目标DC的背景左异或操作
StretchBlt(hdc, xStart, yStart, ptSize.x+xadd, ptSize.y+yadd, hMem, 0, 0, ptSize.x, ptSize.y,SRCCOPY);// 拷贝目标到屏幕上
BitBlt(hTemp, 0, 0, ptSize.x, ptSize.y, hSave, 0, 0, SRCCOPY); // 恢复原始位图
DeleteObject(SelectObject(hBack, OldbmBack)); // 删除临时内存位图
DeleteObject(SelectObject(hObject, OldbmObject));
DeleteObject(SelectObject(hMem, OldbmMem));
DeleteObject(SelectObject(hSave, OldbmSave));
DeleteDC(hMem); // 删除临时内存DC
DeleteDC(hBack);
DeleteDC(hObject);
DeleteDC(hSave);
DeleteDC(hTemp);
}
这就是这个程序的最核心的地方,其他的代码也就相对的简单了分别如下:
CMy1_6View::CMy1_6View()
{
xStart=30;
yStart=30;
xadd=0;
yadd=0;
m_Bitmap.LoadBitmap(IDB_BITMAP1);
cTransparentColor=RGB(255,255,255);
} //对变量的初始化
然后是定时器的初始化和操作:
int CMy1_6View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
SetTimer(1,150,NULL);
return 0;
}
void CMy1_6View::OnTimer(UINT nIDEvent)
{
CDC *pDC=GetDC(); //获取指针pdc
OnDraw(pDC); //调用OnDraw(pDC)重画
CClientDC dc(this);
xStart+=5;
yStart+=5; //向右向下移动
xadd+=2;
yadd+=2;//位图宽高加2
TransparentBitmap(dc.GetSafeHdc(), m_Bitmap, xStart, yStart, xadd,yadd, cTransparentColor); //调用显示
CView::OnTimer(nIDEvent);
}
然后是绘制:
void CMy1_6View::OnDraw(CDC* pDC)
{
CMy1_6Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CBrush mybrush1;//画红色背景
mybrush1.CreateSolidBrush(RGB(255,0,0));
CRect myrect1(0,0,1200,800);
pDC->FillRect(myrect1,&mybrush1);
}
这个就是整个的过程,我下一篇博客是怎么把位图对应显示,这个问题比较简单我准备在上面的基础上,把这个程序变为一个托盘程序。希望大家给出意见!!!!