绘制操作
m_hSrcBitmap = CreateCompatibleBitmap(m_hdc, m_rcSrcMem.right, m_rcSrcMem.bottom);
m_hdcSrcMem =  CreateCompatibleDC(m_hdc);
m_hOldSel =    SelectObject(m_hdcSrcMem,m_hSrcBitmap);
m_pImage->Draw(m_hdcSrcMem,&m_rcSrcMem,NULL);
//m_pImage 为 IImage
OnPaint()里面
PAINTSTRUCT ps;
m_hdc = BeginPaint(m_hSlide, &ps); if(m_bIsInitialized && m_hdc && m_hdcSrcMem)
{
RECT rect = {0};
GetClientRect(m_hSlide, &rect);
FillRect(m_hdc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
StretchBlt(m_hdc,
m_rcThumbnail.left,
m_rcThumbnail.top,
m_rcThumbnail.right - m_rcThumbnail.left,
m_rcThumbnail.bottom - m_rcThumbnail.top,
m_hdcSrcMem,
m_rcSrcMem.left,
m_rcSrcMem.top,
m_rcSrcMem.right - m_rcSrcMem.left,
m_rcSrcMem.bottom - m_rcSrcMem.top,
SRCCOPY);
RETAILMSG(1, (TEXT("CPicture::ShowEx() Paint1111 \r\n")));
}
EndPaint(m_hSlide, &ps);为什么这样子还会有闪烁?
把WM_ERASEBKGND直接返回TRUE则没有闪烁,但是OnPaint() FillRect里面则没起作用了。
我是想实现一张图片小的时候点击它一下然后变成全屏的,所以必须填充一个整个窗口
大家有什么办法吗?

解决方案 »

  1.   

    FillRect(m_hdc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));===>
    这个也可以缓存到内存设备中去.否则你在屏幕dc上做了两次
      

  2.   

    FillRect也必须在MemoryDC里做,否则在屏幕上先FillRect再贴图,当然要闪烁。
      

  3.   

    FillRect(m_hdc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
    要么在m_hdcSrcMem上绘,要么放在在函数StretchBlt后面一行,
    当然了,你既然用来双缓冲,还是
    FillRect(m_hdcSrcMem, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
      

  4.   

    FillRect的结果被后面的函数StretchBlt覆盖掉了
      

  5.   

    > FillRect 已经放在MemDC中了,还是同样的闪烁,是怎么回事?
      

  6.   

    > 将FillRect放到MemDC中,并且将WM_ERASEBKGND直接返回TRUE以后,背景色都没有被填充了,这是什么原因?
      

  7.   

    WM_ERASEBKGND直接返回TRUE 当然不绘制背景了,如果想绘制某种背景,在这个函数里面绘制就行了,和你的双缓存绘制那边也不冲突。
      

  8.   

    在WM_ERASEBKGND中直接绘制会造成闪烁啊。
      

  9.   

    双缓存:我的理解就是 把你要画的东西 全都画到你看不到的内存dc上,然后把内存dc的东西一次性贴到屏幕dc 就ok了 当然WM_ERASEBKGND要直接返回TRUE 
      

  10.   

     
    m_hSrcBitmap = CreateCompatibleBitmap(m_hdc, m_rcSrcMem.right, m_rcSrcMem.bottom);
    m_hdcSrcMem =  CreateCompatibleDC(m_hdc);
    m_hOldSel =    SelectObject(m_hdcSrcMem,m_hSrcBitmap);
    RECT rect = {0};
    GetClientRect(m_hSlide, &rect);
    int nFillRet = FillRect(m_hdcSrcMem, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
    RETAILMSG(1, (TEXT("CPicture::Load() Fill rect:%d--%d-%d-%d-%d \r\n"),nFillRet,
    rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
    RETAILMSG(1, (TEXT("CPicture::Load() Draw rect:%d-%d-%d-%d \r\n"),
    m_rcSrcMem.left, m_rcSrcMem.top, m_rcSrcMem.right - m_rcSrcMem.left, m_rcSrcMem.bottom - m_rcSrcMem.top));
    m_pImage->Draw(m_hdcSrcMem,&m_rcSrcMem,NULL);
      

  11.   

    嗯?
    m_hSrcBitmap = CreateCompatibleBitmap(m_hdc, m_rcSrcMem.right, m_rcSrcMem.bottom);
    这个Bitmap只有m_rcSrcMem这么大?这个m_rcSrcMem是你m_pImage的大小吧?应该小于Client Rect的大小吧?那么你的FillRect的效果另外OnPaint和OnEraseBkgnd呢?怎么写的?
      

  12.   

    兄弟,能否说的详细一点啊,我以前基本上是做通信,做界面做的不是很多,
    m_hSrcBitmap = CreateCompatibleBitmap(m_hdc, m_rcSrcMem.right, m_rcSrcMem.bottom);
    这个Rect的是不是传得不对。
    这是OnPaint的代码:
    PAINTSTRUCT ps;
    m_hdc = BeginPaint(m_hSlide, &ps); if(m_bIsInitialized && m_hdc && m_hdcSrcMem)
    {

    StretchBlt(m_hdc,
    m_rcThumbnail.left,
    m_rcThumbnail.top,
    m_rcThumbnail.right - m_rcThumbnail.left,
    m_rcThumbnail.bottom - m_rcThumbnail.top,
    m_hdcSrcMem,
    m_rcSrcMem.left,
    m_rcSrcMem.top,
    m_rcSrcMem.right - m_rcSrcMem.left,
    m_rcSrcMem.bottom - m_rcSrcMem.top,
    SRCCOPY);
    RETAILMSG(1, (TEXT("CPicture::ShowEx() FillRect(m_hdcSrcMem) Paint1111 \r\n")));
    }
    EndPaint(m_hSlide, &ps)OnEraseBkgnd 直接返回TRUE
      

  13.   

    你既然做的是双缓冲,那就是把所有本来需要在屏幕上画的东西全部先画在一个MemoryDC里,然后把整个MemoryDC里的内容全部一股脑贴到屏幕上,这就避免了在屏幕上先画一样东西、然后再画另一样东西覆盖上去而导致的屏幕闪烁。根据你的代码可以判断出,你需要在整个客户区填上黑色背景,然后在客户区的某个位置上贴一幅图片。这幅图片的尺寸显然不至于把客户区全部覆盖,否则你也没必要填什么黑色背景了。按照双缓冲的原理,你在MemoryDC里用来绘图的Bitmap显然至少应该不比客户区的尺寸小(否则你怎么把画好的内容往屏幕上贴?),而你的CreateCompatibleBitmap传入的参数却仅仅是图片的大小(m_rcSrcMem),这当然不行了,你至少应该把GetClientRect返回的rect传进去。另外,在你的OnPaint里,也远远不是仅仅把你的图片部分(m_rcSrcMem)往屏幕上贴了,而是整个客户区的内容全贴。实际上,画图的时候,你应该完全把这个MemoryDC当作你屏幕上的客户区来看待,画完以后直接“印”到屏幕上(这个“印”的过程直接用BitBlt即可,因为像素应该是一对一的,完全不需要拉伸操作。而BitBlt比StretchBlt快)。
      

  14.   

    > 非常感谢xxd_qd,这个问题已经解决了。稍后结贴
    > 请大家移步这里 http://topic.csdn.net/u/20100805/18/31121f9c-cc3e-4960-b568-e7f092e5a96b.html?61483