如何透明地贴图?

ad 2000-06-11 07:45:00
我向view中贴一个位图,但位图本身是圆的或椭圆的甚至不规则,不属于图片本身的部分用特殊颜色填充,贴图时希望这一特殊部分不要显示出来,即不要盖住view中这部分的原内容,如何做?
...全文
474 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
sun2000 2000-06-13
  • 打赏
  • 举报
回复

void TransparentBlt( HDC hdcDest, int nXDest, int nYDest, int nWidth,
int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc,
COLORREF colorTransparent, HPALETTE hPal )
{
CDC dc, memDC, maskDC, tempDC;
dc.Attach( hdcDest );
maskDC.CreateCompatibleDC(&dc);
CBitmap maskBitmap;

//add these to store return of SelectObject() calls
CBitmap* pOldMemBmp = NULL;
CBitmap* pOldMaskBmp = NULL;
HBITMAP hOldTempBmp = NULL;

memDC.CreateCompatibleDC(&dc);
tempDC.CreateCompatibleDC(&dc);
CBitmap bmpImage;
bmpImage.CreateCompatibleBitmap( &dc, nWidth, nHeight );
pOldMemBmp = memDC.SelectObject( &bmpImage );

// Select and realize the palette
if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && hPal )
{
::SelectPalette( dc, hPal, FALSE );
dc.RealizePalette();

::SelectPalette( memDC, hPal, FALSE );
}

hOldTempBmp = (HBITMAP) ::SelectObject( tempDC.m_hDC, hBitmap );

memDC.BitBlt( 0,0,nWidth, nHeight, &tempDC, nXSrc, nYSrc, SRCCOPY );

// Create monochrome bitmap for the mask
maskBitmap.CreateBitmap( nWidth, nHeight, 1, 1, NULL );
pOldMaskBmp = maskDC.SelectObject( &maskBitmap );
memDC.SetBkColor( colorTransparent );

// Create the mask from the memory DC
maskDC.BitBlt( 0, 0, nWidth, nHeight, &memDC,
0, 0, SRCCOPY );

// Set the background in memDC to black. Using SRCPAINT with black
// and any other color results in the other color, thus making
// black the transparent color
memDC.SetBkColor(RGB(0,0,0));
memDC.SetTextColor(RGB(255,255,255));
memDC.BitBlt(0, 0, nWidth, nHeight, &maskDC, 0, 0, SRCAND);

// Set the foreground to black. See comment above.
dc.SetBkColor(RGB(255,255,255));
dc.SetTextColor(RGB(0,0,0));
dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &maskDC, 0, 0, SRCAND);

// Combine the foreground with the background
dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &memDC,
0, 0, SRCPAINT);


if (hOldTempBmp)
::SelectObject( tempDC.m_hDC, hOldTempBmp);
if (pOldMaskBmp)
maskDC.SelectObject( pOldMaskBmp );
if (pOldMemBmp)
memDC.SelectObject( pOldMemBmp );

dc.Detach();
}


//Setup the windows Region
//The windows region controls what the OS will draw in reguards to the window
//The loop below will search for the "magic color" and add it to a region
//then Xor the region and assign it to the window and viola.
void CTestDlg::SetupBk(HDC hdc)
{
int X,Y,H,W;
CBitmap CB;
CRect R;
COLORREF C;
GetWindowRect(&R);
H = R.bottom - R.top;
W = R.right - R.left;
// CB.LoadBitmap(IDB_BITMAP2);
CB.LoadBitmap(IDB_BITMAP2);
HBITMAP HB = (HBITMAP)CB;

TransparentBlt( hdc , 0, 0, 535, 105, HB, 0, 0,0x00000000 , NULL );
// TransparentBlt( hdc , 0, 0, 96, 36, HB, 0, 0,0x00000000 , NULL );


//Only do this once because it takes some time.
//maybe should pre-make a seperate file to hold region data?
if (FirstRun){
int Set = 0;
//begin pixel by pixel scan for transparent color
for(X=0;X<=W;X++){
for(Y=0;Y<=H;Y++){
C = GetPixel(hdc,X,Y);
//Get the color
if(C == 0x00FFFFFF){
if(Set == 0){
//First, init the working region
//never delete Working, the OS does not store the value, only a pointer to it.
Working.CreateRectRgn(X,Y,X+1,Y+1);
Set = 1;
}
else{
Temp.CreateRectRgn(X,Y,X+1,Y+1);
//Add pixel to region
Working.CombineRgn( &Working, &Temp,RGN_OR );
Temp.DeleteObject();
}
}
}
}
FirstRun = 0;
Temp.CreateRectRgn(0,0,1200,1200);
//flip to get the non-transparent region
Working.CombineRgn( &Working, &Temp,RGN_XOR );
Temp.DeleteObject();
if (Set) SetWindowRgn((HRGN)Working,TRUE);
//redraw just incase.. trust me.. leave this here
RedrawWindow();
}

}
ad 2000-06-13
  • 打赏
  • 举报
回复
davyguo:
我还没收到,163.com有点问题,请发到dzm_xy@cmmail.com.
ad 2000-06-13
  • 打赏
  • 举报
回复
davyguo:
你的代码我收到了,编译后运行单击左键什么也没有!
后来我仔细看MSDN,在函数说明的最后发现,PlgBlt和MaskBlt函数不支持Windows,必须在windows NT下使用才行,得,我自己些个MaskBltEx吧!
ad 2000-06-13
  • 打赏
  • 举报
回复
Sun2000的代码实现的是什么功能?我的问题需要这么复杂吗?怎么还牵涉到调色板?

davyguo:
你的邮件还没收到,真奇怪!

FlowWind:
你那个函数有没有试过?还有什么新招?
ad 2000-06-12
  • 打赏
  • 举报
回复
FlowWind:
我用了PlgBlt及另一个函数MaskBlt, 都不行。
POINT p[3] = {{l,t},{l+w,t},{l,t+h}};
pDC->PlgBlt(p, pMemDC, 0, 0, w, h, bmpMask, 0, 0);

pDC->MaskBlt(l, t, w, h, pMemDC, 0, 0, bmpMask, 0, 0, MAKEOP4(...));

什么也不显示。如果加上VERIFY(...),则报错。mask位图是单色位图,绝对没错,为什么不能显示呢?

davyguo:
我原来用BitBlt一行一行地显示圆形或椭圆位图,实现透明效果,比较麻烦。我想应该有现成的函数可用,微软不会那么差劲,但FlowWind提示的方法就是不行。不知你的BitBltEx用什么方法实现(是否逐点显示)?如果需要伸缩呢?传一份代码来研究研究!
EMail: dzm_xy@163.com

BugGo:
你的方法我没试,但我想这不可取,因为效率太低。
BugGo 2000-06-12
  • 打赏
  • 举报
回复
////////将pMemDC中的图形(0,0,rtSrc.Width() , rtSrc.Height())以crTrans作为透明色画到pDC上;注:透明色通常可取左下点的颜色!!!
void CDIB::DrawTrans(CDC *pDC, CDC *pMemDC, COLORREF crTrans , CRect rtDest , CRect rtSrc)
{
int iBmpWidth = rtSrc.Width(), iBmpHeight = rtSrc.Height();

CDC MemDCObj, MemDCMask , MemDCScreen;
CBitmap bmpBack, bmpObj ,bmpScreen;
bmpBack.CreateCompatibleBitmap(pDC, iBmpWidth,iBmpHeight );
bmpObj.CreateCompatibleBitmap(pDC, iBmpWidth,iBmpHeight );
bmpScreen.CreateCompatibleBitmap(pDC, rtDest.Width(),rtDest.Height() ); //用于保存目标位图

bmpBack.DeleteObject();
bmpObj.DeleteObject();

bmpBack.CreateBitmap(iBmpWidth,iBmpHeight ,1,1,NULL);
bmpObj.CreateBitmap(iBmpWidth,iBmpHeight ,1,1,NULL);
if(!MemDCObj.CreateCompatibleDC(pDC))
return;
if(!MemDCMask.CreateCompatibleDC(pDC))
return;
if(!MemDCScreen.CreateCompatibleDC(pDC))
return;

CBitmap *oldObjBmp = MemDCObj.SelectObject(&bmpObj);
CBitmap *oldBkBmp = MemDCMask.SelectObject(&bmpBack);
CBitmap *oldScreen = MemDCScreen.SelectObject(&bmpScreen);

MemDCScreen.BitBlt(0,0, rtDest.Width(),rtDest.Height() , pDC, rtDest.left, rtDest.top , SRCCOPY); //

COLORREF cColor = pMemDC->SetBkColor(crTrans);
MemDCObj.BitBlt(0,0,iBmpWidth,iBmpHeight ,pMemDC,0,0,SRCCOPY); ///得到模2
pMemDC->SetBkColor(cColor);

MemDCMask.BitBlt(0,0,iBmpWidth,iBmpHeight ,&MemDCObj,0,0,NOTSRCCOPY); ///得到Mask

pMemDC->BitBlt(0,0,iBmpWidth,iBmpHeight ,&MemDCObj,0,0,SRCPAINT); ///模2与原图或OR

MemDCScreen.SetStretchBltMode( COLORONCOLOR );
MemDCScreen.StretchBlt(0,0 , rtDest.Width(),rtDest.Height() ,&MemDCMask ,0,0,iBmpWidth,iBmpHeight ,SRCPAINT); ///画至屏幕OR Mask
MemDCScreen.StretchBlt(0,0, rtDest.Width(),rtDest.Height() ,pMemDC ,0,0,iBmpWidth,iBmpHeight ,SRCAND); ///画至

pDC->BitBlt(rtDest.left,rtDest.top,rtDest.Width(),rtDest.Height(),&MemDCScreen,0,0,SRCCOPY); ///画至屏幕

MemDCScreen.SelectObject(oldScreen);
MemDCObj.SelectObject(oldObjBmp);
MemDCMask.SelectObject(oldBkBmp );
bmpBack.DeleteObject();
bmpObj.DeleteObject();
}
It' OK!!!!
davyguo 2000-06-12
  • 打赏
  • 举报
回复
我有代码,函数说明为
BitBltEx(HDC hdc, int xStart, int yStart, int nWidth,
int nHeight,HBITMAP hBitmap,int xSrc,int ySrc,
COLORREF cTransparentColor,COLORREF cReservedColor = RGB(0,0,0))
你若想要,告诉我你的EMail.
Kevin_qing 2000-06-12
  • 打赏
  • 举报
回复
使用DDraw!
davyguo 2000-06-12
  • 打赏
  • 举报
回复
我已发给你了,看看吧
FlowWind 2000-06-11
  • 打赏
  • 举报
回复
另外创建一个单色的掩码位图,你需要透明的部分用黑色填充,希望保留的部分用白色
然后调用PlgBlt,maskBitmap就是单色掩码位图
PlgBlt( POINT lpPoint, CDC* pSrcDC, int xSrc, int ySrc, int nWidth, int nHeight, CBitmap& maskBitmap, int xMask, int yMask );

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧