关于双缓存绘制的问题

love514425 2010-08-02 10:53:47


绘制操作
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里面则没起作用了。
我是想实现一张图片小的时候点击它一下然后变成全屏的,所以必须填充一个整个窗口
大家有什么办法吗?
...全文
248 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
向立天 2010-09-01
  • 打赏
  • 举报
回复
您好
我是本版版主
此帖已多日无人关注
请您及时结帖
如您认为问题没有解决可按无满意结帖处理
另外本版设置了疑难问题汇总帖
并已在版面置顶
相关规定其帖子中有说明
您可以根据规定提交您帖子的链接
如您目前不想结帖只需回帖说明
我们会删除此结帖通知

见此回复三日内无回应
我们将强制结帖
相关规定详见界面界面版关于版主结帖工作的具体办法
love514425 2010-08-05
  • 打赏
  • 举报
回复
> 非常感谢xxd_qd,这个问题已经解决了。稍后结贴
> 请大家移步这里

http://topic.csdn.net/u/20100805/18/31121f9c-cc3e-4960-b568-e7f092e5a96b.html?61483
sunyouhao 2010-08-02
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 love514425 的回复:]

> 将FillRect放到MemDC中,并且将WM_ERASEBKGND直接返回TRUE以后,背景色都没有被填充了,这是什么原因?
[/Quote]
WM_ERASEBKGND直接返回TRUE 当然不绘制背景了,如果想绘制某种背景,在这个函数里面绘制就行了,和你的双缓存绘制那边也不冲突。
love514425 2010-08-02
  • 打赏
  • 举报
回复
> 将FillRect放到MemDC中,并且将WM_ERASEBKGND直接返回TRUE以后,背景色都没有被填充了,这是什么原因?
love514425 2010-08-02
  • 打赏
  • 举报
回复
> FillRect 已经放在MemDC中了,还是同样的闪烁,是怎么回事?
stonewater 2010-08-02
  • 打赏
  • 举报
回复
FillRect的结果被后面的函数StretchBlt覆盖掉了
stonewater 2010-08-02
  • 打赏
  • 举报
回复
FillRect(m_hdc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
要么在m_hdcSrcMem上绘,要么放在在函数StretchBlt后面一行,
当然了,你既然用来双缓冲,还是
FillRect(m_hdcSrcMem, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
xxd_qd 2010-08-02
  • 打赏
  • 举报
回复
FillRect也必须在MemoryDC里做,否则在屏幕上先FillRect再贴图,当然要闪烁。

cpp2017 2010-08-02
  • 打赏
  • 举报
回复
FillRect(m_hdc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));

===>
这个也可以缓存到内存设备中去.否则你在屏幕dc上做了两次
xxd_qd 2010-08-02
  • 打赏
  • 举报
回复
你既然做的是双缓冲,那就是把所有本来需要在屏幕上画的东西全部先画在一个MemoryDC里,然后把整个MemoryDC里的内容全部一股脑贴到屏幕上,这就避免了在屏幕上先画一样东西、然后再画另一样东西覆盖上去而导致的屏幕闪烁。

根据你的代码可以判断出,你需要在整个客户区填上黑色背景,然后在客户区的某个位置上贴一幅图片。这幅图片的尺寸显然不至于把客户区全部覆盖,否则你也没必要填什么黑色背景了。按照双缓冲的原理,你在MemoryDC里用来绘图的Bitmap显然至少应该不比客户区的尺寸小(否则你怎么把画好的内容往屏幕上贴?),而你的CreateCompatibleBitmap传入的参数却仅仅是图片的大小(m_rcSrcMem),这当然不行了,你至少应该把GetClientRect返回的rect传进去。另外,在你的OnPaint里,也远远不是仅仅把你的图片部分(m_rcSrcMem)往屏幕上贴了,而是整个客户区的内容全贴。

实际上,画图的时候,你应该完全把这个MemoryDC当作你屏幕上的客户区来看待,画完以后直接“印”到屏幕上(这个“印”的过程直接用BitBlt即可,因为像素应该是一对一的,完全不需要拉伸操作。而BitBlt比StretchBlt快)。
love514425 2010-08-02
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 xxd_qd 的回复:]
嗯?
m_hSrcBitmap = CreateCompatibleBitmap(m_hdc, m_rcSrcMem.right, m_rcSrcMem.bottom);
这个Bitmap只有m_rcSrcMem这么大?这个m_rcSrcMem是你m_pImage的大小吧?应该小于Client Rect的大小吧?那么你的FillRect的效果。。。

另外OnPaint和OnEraseBk……
[/Quote]
兄弟,能否说的详细一点啊,我以前基本上是做通信,做界面做的不是很多,
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
xxd_qd 2010-08-02
  • 打赏
  • 举报
回复
嗯?
m_hSrcBitmap = CreateCompatibleBitmap(m_hdc, m_rcSrcMem.right, m_rcSrcMem.bottom);
这个Bitmap只有m_rcSrcMem这么大?这个m_rcSrcMem是你m_pImage的大小吧?应该小于Client Rect的大小吧?那么你的FillRect的效果。。。

另外OnPaint和OnEraseBkgnd呢?怎么写的?
love514425 2010-08-02
  • 打赏
  • 举报
回复

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);
hcyu568 2010-08-02
  • 打赏
  • 举报
回复
双缓存:我的理解就是 把你要画的东西 全都画到你看不到的内存dc上,然后把内存dc的东西一次性贴到屏幕dc 就ok了 当然WM_ERASEBKGND要直接返回TRUE
xxd_qd 2010-08-02
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 love514425 的回复:]
> FillRect 已经放在MemDC中了,还是同样的闪烁,是怎么回事?
[/Quote]
贴代码
love514425 2010-08-02
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 sunyouhao 的回复:]
引用 7 楼 love514425 的回复:

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

WM_ERASEBKGND直接返回TRUE 当然不绘制背景了,如果想绘制某种背景,在这个函数里面绘制就行了,和你的双缓存绘制那边也不冲突。
[/Quote]
在WM_ERASEBKGND中直接绘制会造成闪烁啊。

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧