在 OnPaint 的函数中 直接加载图片到DC上
CPaintDC dc(this); 
CRect m_PictureRect;
GetClientRect(m_PictureRect);
          Gdiplus::Rect rccd;
Graphics graphics(dc.m_hDC);
rccd.X = m_PictureRect.left;
rccd.Y = m_PictureRect.top;
rccd.Width = m_PictureRect.Width();
rccd.Height = m_PictureRect.Height();
Image imagePic(_T("ico_tip.png"));    是PNG 的图片
graphics.DrawImage(&imagePic, rccd);
和缓冲一次在加载到DC上效果不一样?(图片周围有少量的黑色)
CPaintDC dc(this); 
CRect m_PictureRect;
GetClientRect(m_PictureRect);
CDC SaveDC;
SaveDC.CreateCompatibleDC(&dc);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc,m_PictureRect.Width(),m_PictureRect.Height());
SaveDC.SelectObject(bitmap);
Gdiplus::Rect rccd;
Graphics graphics(SaveDC.m_hDC);
rccd.X = m_PictureRect.left;
rccd.Y = m_PictureRect.top;
rccd.Width = m_PictureRect.Width();
rccd.Height = m_PictureRect.Height();
Image imagePic(_T("ico_tip.png"));
graphics.DrawImage(&imagePic, rccd);
dc.TransparentBlt(0,0,m_PictureRect.Width(),m_PictureRect.Height(),&SaveDC,0,0,m_PictureRect.Width(),m_PictureRect.Height(),RGB(0,0,0));
大神们 帮帮小弟把 怎么解决啊?

解决方案 »

  1.   

    rccd.X = 0;
    rccd.Y = 0;
      

  2.   

    rccd.X = m_PictureRect.left;
    rccd.Y = m_PictureRect.top;
    其实就是
    rccd.X = 0;
    rccd.Y = 0;
     我觉得是经过一次缓冲后 图片周围的像素值改变了
      

  3.   

    dc.TransparentBlt(0,0,m_PictureRect.Width(),m_PictureRect.Height(),&SaveDC,0,0,m_PictureRect.Width(),m_PictureRect.Height(),RGB(0,0,0));
    ==你这个代码把黑色透明掉了啊
      

  4.   

     感谢 happyparrot 不信 大神们试试  圆形的图片 周边真的有黑色(不是图片的问题我换了好多) 应为我好使用不止一个图片 所以为了防止闪烁要使用双缓冲,可是一缓冲就有黑色,直接使用dc就没有黑色 但是闪烁,我怀疑 是经过一次缓冲后 图片周围的像素值莫名奇妙的就改变了。 有什么解决办法吗?
      

  5.   

    我可能没说清楚 我的意思是出现的黑色的像素值可能(不是可能是很有可能)已经不是 RGB(0,0,0) 所以透明不了 
      

  6.   

    png 图片你要是有半透明边缘的话, 贴PNG之前要贴父窗口该区域的图像,也就是底图
      

  7.   

    这个我试过 黑边确实是没了 可是我要做像windows桌面那样的功能 控件是可以移动的 如果贴上底图的话移动的话,可以想象多么难看,难道我要动态的取底图?,我试试!
      

  8.   

    测试代码1:
    void C**View::OnDraw( CDC* pDC )
    {
    C**Doc* pDoc = GetDocument( ); ASSERT_VALID( pDoc );

    CRect m_PictureRect;
    GetClientRect(m_PictureRect);
    Gdiplus::Rect rccd;
    Graphics graphics( pDC->m_hDC);
    rccd.X = m_PictureRect.left;
    rccd.Y = m_PictureRect.top;
    rccd.Width = m_PictureRect.Width();
    rccd.Height = m_PictureRect.Height();
    Image imagePic( L"2.png" );
    graphics.DrawImage(&imagePic, rccd);
    }

    代码1效果图:测试代码2:
    void CMSPrintView::OnDraw( CDC* pDC )
    {
    CMSPrintDoc* pDoc = GetDocument( ); ASSERT_VALID( pDoc ); CRect m_PictureRect;
    GetClientRect(m_PictureRect);
    CDC SaveDC;
    SaveDC.CreateCompatibleDC( pDC );
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap( pDC, m_PictureRect.Width( ), m_PictureRect.Height( ) );
    SaveDC.SelectObject(bitmap);
    Gdiplus::Rect rccd;
    Graphics graphics(SaveDC.m_hDC);
    rccd.X = m_PictureRect.left;
    rccd.Y = m_PictureRect.top;
    rccd.Width = m_PictureRect.Width();
    rccd.Height = m_PictureRect.Height();
    Image imagePic( L"2.png" );
    graphics.DrawImage(&imagePic, rccd); pDC->BitBlt( 0, 0, m_PictureRect.Width( ), m_PictureRect.Height( ), &SaveDC, 0, 0, SRCCOPY );}

    代码2效果图:我这样的测试应该没有违背楼主的主要意图。
    从测试结果来看,楼主的主要问题是,在调用dc.TransparentBlt之前,你不进行内存绘图和进行内存绘图时,源DC得到的是两张不同的图,一个背景为白色,一个背景为黑色。这对dc.TransparentBlt的影响就是会产生黑边。
    我想楼主应该明白怎么做了,呵呵 代码:
    void CMSPrintView::OnDraw( CDC* pDC )
    {
    C**Doc* pDoc = GetDocument( ); ASSERT_VALID( pDoc ); CRect m_PictureRect;
    GetClientRect(m_PictureRect);
    CDC SaveDC;
    SaveDC.CreateCompatibleDC( pDC );
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap( pDC, m_PictureRect.Width( ), m_PictureRect.Height( ) );
    SaveDC.SelectObject(bitmap);
    SaveDC.FillSolidRect( 0, 0, m_PictureRect.Width( ), m_PictureRect.Height( ), RGB( 255,255,255 ) );
    Gdiplus::Rect rccd;
    Graphics graphics(SaveDC.m_hDC);
    rccd.X = m_PictureRect.left;
    rccd.Y = m_PictureRect.top;
    rccd.Width = m_PictureRect.Width();
    rccd.Height = m_PictureRect.Height();
    Image imagePic( L"2.png" );
    graphics.DrawImage(&imagePic, rccd); pDC->BitBlt( 0, 0, m_PictureRect.Width( ), m_PictureRect.Height( ), &SaveDC, 0, 0, SRCCOPY ); DrawTransBitmap( pDC->m_hDC, 0, 0, m_PictureRect.Width( ), m_PictureRect.Height( ), SaveDC.m_hDC, 0, 0, RGB( 24, 24, 24 ) ); //pDC->TransparentBlt(0,0,m_PictureRect.Width(),m_PictureRect.Height(),&SaveDC,0,0,m_PictureRect.Width(),m_PictureRect.Height(),RGB(0,0,0));
    }
    SaveDC.FillSolidRect( 0, 0, m_PictureRect.Width( ), m_PictureRect.Height( ), RGB( 255,255,255 ) );这一句加上试试。
    出现黑边的原因是你PNG边缘是有一定透明度的,叠加白色和叠加黑色后,去除黑色没有去除干净。
      

  9.   

    虽然我不是楼主 ,但是楼上Tinary3v0你的回答好专业!支持一下!
    学习中~~~
      

  10.   

    其实11L说了这么多无非想表述一个意思
    你自己构造出来的DC默认填充的未必一定是黑色,需要你自己去填充这个DC,完了之后就没问题了。
      

  11.   

    这种确实可以去掉“黑边”但麻烦就麻烦再我的Button是可以拖动的位置的改变后面的背景也就改了,你那样做的话就会出现“白边”了,这种情况在不规则的图片上十分明显,矩形就好一些,我对图片不是很了解
    有边缘没有透明度的PNG图片吗 我换了好多图片都有这个问题。还有这个和9楼的贴底图的思路差不过,有没有办法不贴底图,也就说 叠加白色或叠加黑色后 能完全去除白色和黑色?
      

  12.   

    1. 缓存还是要用的,否则绘图效果将是各种悲剧;
    2. 你出现“周围有少量的黑色”的本质原因在于TransparentBlt。这个函数会进行掩码处理(在2D游戏人物贴图中经常使用),可以达到背景透明的效果。
    3. 使用这种掩码处理的图片必须满足一个条件:图片的前景部分绝对不能包含和背景色相同的颜色RGB,否则就是你所描述的效果。
    4. 要解决这个问题,两个选择:(1) 不做掩码处理,直接BitBlt或者StretchBlt,但贴图的背景色全部选用同一种颜色,且不能有区域重叠 (2)做掩码处理,但请专门搞美工的处理下图片,使得处理过的图片满足3中的条件。总之不管怎么解,都得从图源下手,图源不行的话,你的算法再牛逼也没用。
      

  13.   

    虽然我现在没有完美解决,但我把图片转成多种格式试验,有bmp gif png jpg 测试出:是因为为了使图片美观防止锯齿,大多数png图片周边都有半透明边缘,所以才导致“黑边”的结果,找美工把半透明的周边扣掉,效果好了很多, 谢谢大家。就此结贴!