下面的代码作用是将一个位图不透明的地方透明,但是用C写的,我照着用C#翻译了一下,没成功,哪位高手可以帮忙翻译一下。用C#自己的MakeTanspent方法作的透明效果不好,对于图片的阴影不能处理。
Bitmap* CreateBitmapFromHBITMAP(IN HBITMAP hBitmap)
{
BITMAP bmp = { 0 };
if ( 0 == GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bmp) )
{
return FALSE;
} // Although we can get bitmap data address by bmp.bmBits member of BITMAP which is got by GetObject function sometime,
// we can determine the bitmap data in the HBITMAP is arranged bottom-up or top-down, so we should always use GetDIBits to get bitmap data.
BYTE *piexlsSrc = NULL;
LONG cbSize = bmp.bmWidthBytes * bmp.bmHeight;
piexlsSrc = new BYTE[cbSize];BITMAPINFO bmpInfo = { 0 };// We should initialize the first six members of BITMAPINFOHEADER structure.
// A bottom-up DIB is specified by setting the height to a positive number, while a top-down DIB is specified by setting the height to a negative number.bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = bmp.bmWidth;
bmpInfo.bmiHeader.biHeight = bmp.bmHeight; // 正数,说明数据从下到上,如未负数,则从上到下
bmpInfo.bmiHeader.biPlanes = bmp.bmPlanes;
bmpInfo.bmiHeader.biBitCount = bmp.bmBitsPixel;
bmpInfo.bmiHeader.biCompression = BI_RGB;
 HDC hdcScreen = CreateDC(L"DISPLAY", NULL, NULL,NULL);
LONG cbCopied = GetDIBits(hdcScreen, hBitmap, 0, bmp.bmHeight, piexlsSrc, &bmpInfo, DIB_RGB_COLORS);
DeleteDC(hdcScreen);
if ( 0 == cbCopied )
{
delete [] piexlsSrc;
return FALSE;
}// Create an GDI+ Bitmap has the same dimensions with hbitmapBitmap *pBitmap = new Bitmap(bmp.bmWidth, bmp.bmHeight, PixelFormat32bppPARGB);// Access to the Gdiplus::Bitmap's pixel dataBitmapData bitmapData;
Rect rect(0, 0, bmp.bmWidth, bmp.bmHeight);
if ( Ok != pBitmap->LockBits(&rect, ImageLockModeRead, PixelFormat32bppPARGB, &bitmapData) )
{
SAFE_DELETE(pBitmap);
return NULL;
}
 
BYTE *pixelsDest = (BYTE*)bitmapData.Scan0;
int nLinesize = bmp.bmWidth * sizeof(UINT);
int nHeight = bmp.bmHeight;// Copy pixel data from HBITMAP by bottom-up.for ( int y = 0; y < nHeight; y++ )
{
// 从下到上复制数据,因为前面设置高度时是正数。
memcpy_s( (pixelsDest + y * nLinesize), nLinesize, (piexlsSrc + (nHeight - y - 1) * nLinesize), nLinesize);
} // Copy the data in temporary buffer to pBitmap
if ( Ok != pBitmap->UnlockBits(&bitmapData) )
{
delete pBitmap;
}
 
delete [] piexlsSrc;
return pBitmap;
}

解决方案 »

  1.   

    什么叫“不透明的地方透明”,这话通吗?这段代码就是一个从HBITMAP复制到Bitmap的,没有其他任何处理,甚至只能处理32位的位图,Bitmap构造函数直接就可以……
      

  2.   

    HBITMAP是GDI句柄,但c#用的都是GDI+,在c#中用GDI的东西很麻烦,
      

  3.   

    不透明的地方透明,无非就是将某种颜色视作MaskColor,然后替换颜色值为无色,并且Alpha分量为0。不需要一行一行改写这个代码。
      

  4.   

    呃,不好意思,问题没写好,本来是这样的:通过IShellItemImageFactory.GetImage()获取的图像,在通过Image.FromHBitmap()得到一个Bitmap时,将它显示在窗体上,会发现,图像中原本是透明的地方全变成了黑色,即失去了透明效果。如果用Bitmap.MakeTransparent()方法处理,会发现基本达到了透明,但是如果图片边缘有阴影的话,阴影仍然是黑色。 在网上找到这样的解决方案,但是一时没办法搬到C#中来,不过现在我已经用AlphBlend方式,达到了目的。谢谢大家!
      

  5.   

    呃,问题还没完,发现仍然有问题,我的代码如下:
     Bitmap nbmp=new Bitmap(96,96,System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
                //下面这一句,如果换成Graphics g=CreateGraphics();由窗体创建的Graphics对象,则可以正确地在窗体上显示图像,但是如果用从Image创建,图像阴影边缘就成了黑色的了
                Graphics g=Graphics.FromImage(nbmp);
                IntPtr hdcDest = g.GetHdc();
                IntPtr hdcMem = IntPtr.Zero;
                hdcMem = Win32.CreateCompatibleDC(IntPtr.Zero);
                Win32.SelectObject(hdcMem, hBitmap);
                Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
                blend.AlphaFormat = Win32.AC_SRC_ALPHA;
                blend.BlendOp = Win32.AC_SRC_OVER;
                blend.BlendFlags = 0;
                blend.SourceConstantAlpha = 255;
                Win32.AlphaBlend(hdcDest, 0, 0, 96, 96, hdcMem, 0,0, 96, 96, blend);
                g.ReleaseHdc(hdcDest);
                g.Dispose();            
                Win32.DeleteObject(hdcMem);
                return nbmp;
    上面代码中,关键点就在第二行,如果把图像直接绘制在窗体上,则没有问题,如果用nbmp返回,再绘制的话,图像边缘部分就成了黑的了。
    请大家再帮看看?