怎么透明显示一张bmp图片(急,在线等待) 已知图片的文件名fileName,怎么在一个窗口上将其透明显示出来??希望各位帮助 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我已有读取的函数,现需要知道如何将其透明显示出来BOOL CTestDlg::LoadBMPImage(LPCTSTR sBMPFile, CBitmap &bitmap, CPalette *pPal){ CFile file; if( !file.Open( sBMPFile, CFile::modeRead) ) return FALSE; BITMAPFILEHEADER bmfHeader; // Read file header if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) return FALSE; // File type should be 'BM' if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B')) return FALSE; // Get length of the remainder of the file and allocate memory DWORD nPackedDIBLen = file.GetLength() - sizeof(BITMAPFILEHEADER); HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen); if (hDIB == 0) return FALSE; // Read the remainder of the bitmap file. if (file.ReadHuge((LPSTR)hDIB, nPackedDIBLen) != nPackedDIBLen ) { ::GlobalFree(hDIB); return FALSE; } BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ; BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ; // If bmiHeader.biClrUsed is zero we have to infer the number // of colors from the number of bits used to specify it. int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed : 1 << bmiHeader.biBitCount; LPVOID lpDIBBits; if( bmInfo.bmiHeader.biBitCount > 8 ) lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) + ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0)); else lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors); // Create the logical palette if( pPal != NULL ) { // Create the palette if( nColors <= 256 ) { UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors); LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; pLP->palVersion = 0x300; pLP->palNumEntries = nColors; for( int i=0; i < nColors; i++) { pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed; pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen; pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue; pLP->palPalEntry[i].peFlags = 0; } pPal->CreatePalette( pLP ); delete[] pLP; } } CClientDC dc(NULL); CPalette* pOldPalette = NULL; if( pPal ) { pOldPalette = dc.SelectPalette( pPal, FALSE ); dc.RealizePalette(); } HBITMAP hBmp = CreateDIBitmap( dc.m_hDC, // handle to device context &bmiHeader, // pointer to bitmap size and format data CBM_INIT, // initialization flag lpDIBBits, // pointer to initialization data &bmInfo, // pointer to bitmap color-format data DIB_RGB_COLORS); // color-data usage bitmap.Attach( hBmp ); if( pOldPalette ) dc.SelectPalette( pOldPalette, FALSE ); ::GlobalFree(hDIB); return TRUE;} 窗口的背景色是会变得,如果这点不考虑到,拿出去的程序就没有专业水准。3个实现思路:1。兼容性略差,但最简单。TransparentBlt,系统api,不支持95。2。自己从内存位图中逐点SetPixel到目标去,如果透明色就不画。3。最复杂,但兼容性好,速度也比逐点画快。做一个单色的mask位图,先和目标位图BitBlt一次,然后再将原位图BitBlt到目标上,不过两次的操作要用到非常不常用的raster operation code,其中一次是sdk中没有定义的。Windows 本身用的就是这种方式,有谁感兴趣再说吧,不费口舌了。 此外,读取位图需要这么长的程序吗?一行不够吗?LoadImage(...) BOOL CBmpProc::DrawTransparentInRect(CDC& dc,COLORREF crColour,CRect* crDest,CRect* crSou,int mode){// 如果类中没有图像,直接返回if (!IsValid())return TRUE;ASSERT(m_hObject);// 缺省矩形等于图像尺寸CRect DCRect(Rect()); // 目标位置CRect SORect(Rect()); // 源位置if (crDest) DCRect = *crDest;if (crSou) SORect = *crSou;// 如果待绘制的图像不在当前剪贴区域内,则直接返回if (!dc.RectVisible(&DCRect))return TRUE;COLORREF crOldBack;COLORREF crOldText;if (mode==0){ // 去除指定的颜色crOldBack = dc.SetBkColor(RGB(255,255,255));crOldText = dc.SetTextColor(RGB(0,0,0));} else{ // 保留指定的颜色crOldBack = dc.SetBkColor(RGB(0,0,0));crOldText = dc.SetTextColor(RGB(255,255,255));}CDC dcImage, dcTrans;// 创建内存设备描述表dcImage.CreateCompatibleDC(&dc);dcTrans.CreateCompatibleDC(&dc); // 选择原始图像到DC中CBitmap* pOldBitmapImage = dcImage.SelectObject(this);// 创建掩码位图CBitmap bitmapTrans;int nWidth = SORect.Width();int nHeight = SORect.Height();bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);// 选择掩码位图到DC中CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);// 创建掩码图像(基于指定的颜色)dcImage.SetBkColor(crColour);dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, SORect.left, SORect.top,SRCCOPY);// 显示透明位图/* 设置目标DC的拉伸模式为STRETCH_DELETESCANS,也就是不显示拉伸掉的图像 */int srlold = dc.SetStretchBltMode(STRETCH_DELETESCANS);// 显示位图dc.StretchBlt(DCRect.left,DCRect.top,DCRect.Width(),DCRect.Height(),&dcImage,SORect.left,SORect.top,SORect.Width(),SORect.Height(),SRCINVERT); VC++怎么通过SOCKET传送位图数据 请问达人像360的软件管家这种界面用什么语言编写最好? VC++贴图 如何实现把一块内存当作文件来访问,而不把这块内存里的东西写到硬里盘 vc.net中组件的注册 高分求助 请问,如何用VC获取SQL Sever2000数据库中的image数据,并在程序中显示 关于Visual Studio6和MSDN98 怎么把一个文件夹中的ICO文件读入一个图象列表?? 怎么使位图旋转90? 帮帮我 请教《Windows程序设计(第五版)》中的一行代码
BOOL CTestDlg::LoadBMPImage(LPCTSTR sBMPFile, CBitmap &bitmap, CPalette *pPal)
{
CFile file;
if( !file.Open( sBMPFile, CFile::modeRead) )
return FALSE; BITMAPFILEHEADER bmfHeader; // Read file header
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
return FALSE; // File type should be 'BM'
if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B'))
return FALSE; // Get length of the remainder of the file and allocate memory
DWORD nPackedDIBLen = file.GetLength() - sizeof(BITMAPFILEHEADER);
HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen);
if (hDIB == 0)
return FALSE; // Read the remainder of the bitmap file.
if (file.ReadHuge((LPSTR)hDIB, nPackedDIBLen) != nPackedDIBLen )
{
::GlobalFree(hDIB);
return FALSE;
}
BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ; // If bmiHeader.biClrUsed is zero we have to infer the number
// of colors from the number of bits used to specify it.
int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed :
1 << bmiHeader.biBitCount; LPVOID lpDIBBits;
if( bmInfo.bmiHeader.biBitCount > 8 )
lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) +
((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
else
lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors); // Create the logical palette
if( pPal != NULL )
{
// Create the palette
if( nColors <= 256 )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; pLP->palVersion = 0x300;
pLP->palNumEntries = nColors; for( int i=0; i < nColors; i++)
{
pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
pLP->palPalEntry[i].peFlags = 0;
} pPal->CreatePalette( pLP ); delete[] pLP;
}
} CClientDC dc(NULL);
CPalette* pOldPalette = NULL;
if( pPal )
{
pOldPalette = dc.SelectPalette( pPal, FALSE );
dc.RealizePalette();
} HBITMAP hBmp = CreateDIBitmap( dc.m_hDC, // handle to device context
&bmiHeader, // pointer to bitmap size and format data
CBM_INIT, // initialization flag
lpDIBBits, // pointer to initialization data
&bmInfo, // pointer to bitmap color-format data
DIB_RGB_COLORS); // color-data usage
bitmap.Attach( hBmp ); if( pOldPalette )
dc.SelectPalette( pOldPalette, FALSE ); ::GlobalFree(hDIB);
return TRUE;
}
1。兼容性略差,但最简单。TransparentBlt,系统api,不支持95。
2。自己从内存位图中逐点SetPixel到目标去,如果透明色就不画。
3。最复杂,但兼容性好,速度也比逐点画快。做一个单色的mask位图,先和目标位图BitBlt一次,然后再将原位图BitBlt到目标上,不过两次的操作要用到非常不常用的raster operation code,其中一次是sdk中没有定义的。Windows 本身用的就是这种方式,有谁感兴趣再说吧,不费口舌了。
一行不够吗?
LoadImage(...)
COLORREF crColour,
CRect* crDest,
CRect* crSou,
int mode)
{
// 如果类中没有图像,直接返回
if (!IsValid())return TRUE;
ASSERT(m_hObject);
// 缺省矩形等于图像尺寸
CRect DCRect(Rect()); // 目标位置
CRect SORect(Rect()); // 源位置
if (crDest) DCRect = *crDest;
if (crSou) SORect = *crSou;
// 如果待绘制的图像不在当前剪贴区域内,则直接返回
if (!dc.RectVisible(&DCRect))return TRUE;
COLORREF crOldBack;
COLORREF crOldText;
if (mode==0){ // 去除指定的颜色
crOldBack = dc.SetBkColor(RGB(255,255,255));
crOldText = dc.SetTextColor(RGB(0,0,0));
}
{ // 保留指定的颜色
crOldBack = dc.SetBkColor(RGB(0,0,0));
crOldText = dc.SetTextColor(RGB(255,255,255));
}
CDC dcImage, dcTrans;
// 创建内存设备描述表
dcImage.CreateCompatibleDC(&dc);
dcTrans.CreateCompatibleDC(&dc);
CBitmap* pOldBitmapImage = dcImage.SelectObject(this);
// 创建掩码位图
CBitmap bitmapTrans;
int nWidth = SORect.Width();
int nHeight = SORect.Height();
bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);
// 选择掩码位图到DC中
CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);
// 创建掩码图像(基于指定的颜色)
dcImage.SetBkColor(crColour);
dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, SORect.left, SORect.top,
SRCCOPY);
// 显示透明位图
/* 设置目标DC的拉伸模式为STRETCH_DELETESCANS,也就是不显示拉伸掉的图像 */
int srlold = dc.SetStretchBltMode(STRETCH_DELETESCANS);
// 显示位图
dc.StretchBlt(DCRect.left,DCRect.top,DCRect.Width(),DCRect.Height(),
&dcImage,SORect.left,SORect.top,SORect.Width(),SORect.Height(),SRCINVERT);