none
TransparentBlt在打印预览时候偶尔会出现无效的情况 RRS feed

  • 问题

  • 问题现象:在点击预览后,预览界面里,通过transparentblt绘制的透明区域,有时候正常,有时候不正常。

    具体的代码和现象图片如下:

    CDC dcForeground;
    dcForeground.CreateCompatibleDC(pDC);
    CBitmap bmpForeground;
    bmpForeground.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
    dcForeground.SelectObject(&bmpForeground);
    if(FAILED(pPic->Render(dcForeground, /*rect.left*/0, /*rect.top*/0, rect.Width(), rect.Height(), 0, hmHeight, hmWidth, -hmHeight, NULL)))         
    {
    	pPic->Release();  
    	pPic = NULL;   
    	bmpForeground.DeleteObject();
    	dcForeground.DeleteDC();
    	goto CLEAROBJECT;
    }
    
    if(m_bEnableTransparent)
    {
    	CDC dcBackground;
    	dcBackground.CreateCompatibleDC(pDC);
    	CBitmap bmpBackground;
    	bmpBackground.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
    	dcBackground.SelectObject(&bmpBackground);
    	TransparentBlt(dcBackground, 0, 0, rect.Width(), rect.Height(), dcForeground, 0, 0, rect.Width(), rect.Height(), m_colorTransparent);
    	TransparentBlt(pDC->m_hDC, rect.left, rect.top, rect.Width(), rect.Height(), dcBackground, 0, 0, rect.Width(), rect.Height(), RGB(0,0,0));
    	bmpBackground.DeleteObject();
    	dcBackground.DeleteDC();
    }
    else
    {
    	BitBlt(pDC->m_hDC, rect.left, rect.top, rect.Width(), rect.Height(), dcForeground, 0, 0, SRCCOPY);
    }
    
    bmpForeground.DeleteObject();
    dcForeground.DeleteDC();

    正常现象

    错误现象

    2015年8月4日 1:18

答案

  • 你好,我今天更改了原来的实现逻辑,原来的实现有点方式有点多余,直接只用一次TransparentBlt函数,从缓冲dc直接复制到目标dc,然后设置透明色为指定的颜色。发现没有问题了。

    原来的实现流程是先把缓冲dc复制到另一个dc上,透明色设置为指定颜色,把透明部分变为黑色,然后再把这个dc上的内容复制到最终的显示dc上,透明色设置为黑色。这种实现方式是有点多余,效率低下,现在虽然简化解决了问题,但是我想弄清楚为什么第一次blt后指定的颜色变为黑色,但是第二次blt时偶尔会黑色没有过滤为透明色?我加了trace打印,发现都有调用到这些函数(在onpaint函数里调用到上述的代码片段),不知道会不会是因为我都是用的自绘的方式打印预览的view出现了需要刷新的背景部分却没有进行刷新呢?

    更改后的正常运行代码片段如下:

    if(m_bEnableTransparent)
    {	
    	TransparentBlt(pDC->m_hDC, rect.left, rect.top, rect.Width(), rect.Height(), dcForeground, 0, 0, rect.Width(), rect.Height(), m_colorTransparent);
    }
    else
    {
    	BitBlt(pDC->m_hDC, rect.left, rect.top, rect.Width(), rect.Height(), dcForeground, 0, 0, SRCCOPY);
    }

    • 已标记为答案 Shu 2017 2015年9月9日 1:43
    2015年8月6日 10:00

全部回复

  • 上面的代码片段实在什么函数内使用的?有没有可能没有用到TransparentBlt函数,直接调用了BitBlt函数?在Bitblt函数设个断点看看能不能触发断点。

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2015年8月5日 2:49
  • 你好,我今天更改了原来的实现逻辑,原来的实现有点方式有点多余,直接只用一次TransparentBlt函数,从缓冲dc直接复制到目标dc,然后设置透明色为指定的颜色。发现没有问题了。

    原来的实现流程是先把缓冲dc复制到另一个dc上,透明色设置为指定颜色,把透明部分变为黑色,然后再把这个dc上的内容复制到最终的显示dc上,透明色设置为黑色。这种实现方式是有点多余,效率低下,现在虽然简化解决了问题,但是我想弄清楚为什么第一次blt后指定的颜色变为黑色,但是第二次blt时偶尔会黑色没有过滤为透明色?我加了trace打印,发现都有调用到这些函数(在onpaint函数里调用到上述的代码片段),不知道会不会是因为我都是用的自绘的方式打印预览的view出现了需要刷新的背景部分却没有进行刷新呢?

    更改后的正常运行代码片段如下:

    if(m_bEnableTransparent)
    {	
    	TransparentBlt(pDC->m_hDC, rect.left, rect.top, rect.Width(), rect.Height(), dcForeground, 0, 0, rect.Width(), rect.Height(), m_colorTransparent);
    }
    else
    {
    	BitBlt(pDC->m_hDC, rect.left, rect.top, rect.Width(), rect.Height(), dcForeground, 0, 0, SRCCOPY);
    }

    • 已标记为答案 Shu 2017 2015年9月9日 1:43
    2015年8月6日 10:00