{
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap Bitmap;
Bitmap.LoadBitmap(IDB_BITMAP1);
BITMAP bm;
Bitmap.GetObject(sizeof(BITMAP), &bm);
CBitmap *pOldBitmap = MemDC.SelectObject(&Bitmap);
pDC->BitBlt(100, 100, bm.bmWidth, bm.bmHeight, &MemDC, 0, 0, SRCCOPY);
MemDC.SelectObject(pOldBitmap);
MemDC.DeleteDC();
Bitmap.DeleteObject();
//Invalidate();
}
这是用了双缓冲了,可是在改变窗口大小时还是闪的要命!!!!!!(把那个注释的Invalidate();加上观察一下,呵呵.....晕~~~~~~)
到底要怎么彻底避免闪烁呢?
解决了,给你多少分,随你要!!!
9 个解决方案
#1
BOOL CFlickerView::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
{
return FALSE;
}
#2
回复人: hnyyy(前进) ( ) 信誉:111 2003-02-16 14:24:00 得分:0
BOOL CFlickerView::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
这样一来,整个客户区的内容,除了我画的图形外,将会把它后面的图像全粘了上来???
好难看呀???
BOOL CFlickerView::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
这样一来,整个客户区的内容,除了我画的图形外,将会把它后面的图像全粘了上来???
好难看呀???
#3
在OnDraw中画背景
CRect rect;
GetClientRect(rect);
......
memBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
......
MemDC.FillSolidRect(rect, RGB(255, 255, 255));//画背景
......
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);//全铺满
......
CRect rect;
GetClientRect(rect);
......
memBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
......
MemDC.FillSolidRect(rect, RGB(255, 255, 255));//画背景
......
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);//全铺满
......
#4
原来是让我把整个客户区全部重画呀!!!
倒~~~~~
不过确实是达到了目的。
倒~~~~~
不过确实是达到了目的。
#5
发现,在窗口改变大小时,那个ToolBar也闪?
难道当初MS也没处理这个问题???????
难道当初MS也没处理这个问题???????
#6
OnEraseBkgnd中返回TRUE;
OnDraw中不要加Invalidate,这不是死循环吗!
OnDraw中不要加Invalidate,这不是死循环吗!
#7
OnDraw中不要加Invalidate,这不是死循环吗!
这样可以观测效果,免得我自己去拖动更改窗口大小来看闪烁的情况
这样可以观测效果,免得我自己去拖动更改窗口大小来看闪烁的情况
#8
窗口改变大小时闪的东西多着呢,对于改变大小这种不常发生的事情有一小点闪大概是可以接受的吧?
#9
我觉得应该屏蔽setredraw,然后操作,最后刷新,下面文章参考。
在图像的编程中,经常会遇到这样一种情况,在有限的区域中显示了一幅大图,这时要浏览图像的各个部分,这就需要用到图像的滚动。关于它的实现,许多书都有提及,但其中的关键点和难点,即拖动中的刷新和闪烁问题,却讲述的不多,这也是我写本文的目的所在,下面我将详细分析实现方法。
实现效果及实现方法:
在图像区域中按下鼠标左键,可拖动图像在某一有限区域中任意滚动。
方法为 :拖动时计算上次与本次的偏移,然后将图像显示的起始点进行变化并刷新图像区域。
实现部分:
第一步:响应WM_LBUTTONDOWN 消息,记录按下开始拖动的起始位置。
void CWingImgDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_lPicOldLeft = point.x;
m_lPicOldTop = point.y;
CDialog::OnLButtonDown(nFlags, point);
}
第二步:响应WM_MOUSEMOVE 消息,实现滚动。
void CWingImgDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
file://如果鼠标按下
if( (nFlags & MK_LBUTTON) == MK_LBUTTON )
{
m_lPicNewLeft = point.x;
m_lPicNewTop = point.y;
DWORD dwLRShift = m_lPicNewLeft - m_lPicOldLeft;
DWORD dwTBShift = m_lPicNewTop - m_lPicOldTop;
file://改变图像显示的起始点
m_lPicLeft = m_lPicLeft - dwLRShift;
m_lPicTop = m_lPicTop - dwTBShift;
file://判断边界的语句,省去。
m_lPicOldLeft = m_lPicNewLeft;
m_lPicOldTop = m_lPicNewTop;
file://进行刷新的语句,见第四步。
}
CDialog::OnMouseMove(nFlags, point);
}
第三步:在OnPaint中显示,显示的其他部分,如图像的得来等,省去。
void CWingImgDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
file://其他的显示内容,省去。
if(m_pImgInfo != NULL)
dc.BitBlt(m_wShowAdjLeft,m_wShowAdjTop,m_lWidth,m_lHeight,&m_AdjDC,
m_lPicLeft,m_lPicTop,SRCCOPY);
CDialog::OnPaint();
}
第四步:刷新处理。
最常想到的方法,当然是使用Invalidate(TRUE);//刷新整个无效区
UpdateWindow();
这时,会刷新整个程序区域的无效区,闪烁非常严重,改正如下:
InvalidateRect(&m_rtPic,TRUE); file://仅刷新图像显示区域
UpdateWindow();
此时,仅会刷新图像所在区域,闪烁有所缓解,再进一步,可使用
InvalidateRect(&m_rtPic,TRUE); file://使用快速重画
ReDrawWindow(&m_rtPic,NULL,RDW_INTERNALPAINT| RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
进行处理,此时闪烁更进一步减小,考虑到,其他部分可能影响刷新区域,干脆将OnPaint()直接使用在此处,即变为:
OnPaint();
但如果在OnPaint()中有大量的绘图语句,这种方法仍旧不可行,考虑到不能激发OnPaint()这一因素及控制刷新范围,我采用了如下非标准的方法解决,代码如下:
CDC *pDC;
pDC = GetDC();
if(m_pImgInfo != NULL)
pDC->BitBlt(m_wShowLeft,m_wShowTop,m_lWidth,m_lHeight,&m_AdjDC,m_lPicLeft,m_lPicTop,SRCCOPY);
ReleaseDC(pDC);
这种方法很好地解决了刷新闪烁的问题,图像拖动时很平稳且无闪烁。
在图像的编程中,经常会遇到这样一种情况,在有限的区域中显示了一幅大图,这时要浏览图像的各个部分,这就需要用到图像的滚动。关于它的实现,许多书都有提及,但其中的关键点和难点,即拖动中的刷新和闪烁问题,却讲述的不多,这也是我写本文的目的所在,下面我将详细分析实现方法。
实现效果及实现方法:
在图像区域中按下鼠标左键,可拖动图像在某一有限区域中任意滚动。
方法为 :拖动时计算上次与本次的偏移,然后将图像显示的起始点进行变化并刷新图像区域。
实现部分:
第一步:响应WM_LBUTTONDOWN 消息,记录按下开始拖动的起始位置。
void CWingImgDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_lPicOldLeft = point.x;
m_lPicOldTop = point.y;
CDialog::OnLButtonDown(nFlags, point);
}
第二步:响应WM_MOUSEMOVE 消息,实现滚动。
void CWingImgDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
file://如果鼠标按下
if( (nFlags & MK_LBUTTON) == MK_LBUTTON )
{
m_lPicNewLeft = point.x;
m_lPicNewTop = point.y;
DWORD dwLRShift = m_lPicNewLeft - m_lPicOldLeft;
DWORD dwTBShift = m_lPicNewTop - m_lPicOldTop;
file://改变图像显示的起始点
m_lPicLeft = m_lPicLeft - dwLRShift;
m_lPicTop = m_lPicTop - dwTBShift;
file://判断边界的语句,省去。
m_lPicOldLeft = m_lPicNewLeft;
m_lPicOldTop = m_lPicNewTop;
file://进行刷新的语句,见第四步。
}
CDialog::OnMouseMove(nFlags, point);
}
第三步:在OnPaint中显示,显示的其他部分,如图像的得来等,省去。
void CWingImgDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
file://其他的显示内容,省去。
if(m_pImgInfo != NULL)
dc.BitBlt(m_wShowAdjLeft,m_wShowAdjTop,m_lWidth,m_lHeight,&m_AdjDC,
m_lPicLeft,m_lPicTop,SRCCOPY);
CDialog::OnPaint();
}
第四步:刷新处理。
最常想到的方法,当然是使用Invalidate(TRUE);//刷新整个无效区
UpdateWindow();
这时,会刷新整个程序区域的无效区,闪烁非常严重,改正如下:
InvalidateRect(&m_rtPic,TRUE); file://仅刷新图像显示区域
UpdateWindow();
此时,仅会刷新图像所在区域,闪烁有所缓解,再进一步,可使用
InvalidateRect(&m_rtPic,TRUE); file://使用快速重画
ReDrawWindow(&m_rtPic,NULL,RDW_INTERNALPAINT| RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
进行处理,此时闪烁更进一步减小,考虑到,其他部分可能影响刷新区域,干脆将OnPaint()直接使用在此处,即变为:
OnPaint();
但如果在OnPaint()中有大量的绘图语句,这种方法仍旧不可行,考虑到不能激发OnPaint()这一因素及控制刷新范围,我采用了如下非标准的方法解决,代码如下:
CDC *pDC;
pDC = GetDC();
if(m_pImgInfo != NULL)
pDC->BitBlt(m_wShowLeft,m_wShowTop,m_lWidth,m_lHeight,&m_AdjDC,m_lPicLeft,m_lPicTop,SRCCOPY);
ReleaseDC(pDC);
这种方法很好地解决了刷新闪烁的问题,图像拖动时很平稳且无闪烁。
#1
BOOL CFlickerView::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
{
return FALSE;
}
#2
回复人: hnyyy(前进) ( ) 信誉:111 2003-02-16 14:24:00 得分:0
BOOL CFlickerView::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
这样一来,整个客户区的内容,除了我画的图形外,将会把它后面的图像全粘了上来???
好难看呀???
BOOL CFlickerView::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
这样一来,整个客户区的内容,除了我画的图形外,将会把它后面的图像全粘了上来???
好难看呀???
#3
在OnDraw中画背景
CRect rect;
GetClientRect(rect);
......
memBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
......
MemDC.FillSolidRect(rect, RGB(255, 255, 255));//画背景
......
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);//全铺满
......
CRect rect;
GetClientRect(rect);
......
memBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
......
MemDC.FillSolidRect(rect, RGB(255, 255, 255));//画背景
......
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);//全铺满
......
#4
原来是让我把整个客户区全部重画呀!!!
倒~~~~~
不过确实是达到了目的。
倒~~~~~
不过确实是达到了目的。
#5
发现,在窗口改变大小时,那个ToolBar也闪?
难道当初MS也没处理这个问题???????
难道当初MS也没处理这个问题???????
#6
OnEraseBkgnd中返回TRUE;
OnDraw中不要加Invalidate,这不是死循环吗!
OnDraw中不要加Invalidate,这不是死循环吗!
#7
OnDraw中不要加Invalidate,这不是死循环吗!
这样可以观测效果,免得我自己去拖动更改窗口大小来看闪烁的情况
这样可以观测效果,免得我自己去拖动更改窗口大小来看闪烁的情况
#8
窗口改变大小时闪的东西多着呢,对于改变大小这种不常发生的事情有一小点闪大概是可以接受的吧?
#9
我觉得应该屏蔽setredraw,然后操作,最后刷新,下面文章参考。
在图像的编程中,经常会遇到这样一种情况,在有限的区域中显示了一幅大图,这时要浏览图像的各个部分,这就需要用到图像的滚动。关于它的实现,许多书都有提及,但其中的关键点和难点,即拖动中的刷新和闪烁问题,却讲述的不多,这也是我写本文的目的所在,下面我将详细分析实现方法。
实现效果及实现方法:
在图像区域中按下鼠标左键,可拖动图像在某一有限区域中任意滚动。
方法为 :拖动时计算上次与本次的偏移,然后将图像显示的起始点进行变化并刷新图像区域。
实现部分:
第一步:响应WM_LBUTTONDOWN 消息,记录按下开始拖动的起始位置。
void CWingImgDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_lPicOldLeft = point.x;
m_lPicOldTop = point.y;
CDialog::OnLButtonDown(nFlags, point);
}
第二步:响应WM_MOUSEMOVE 消息,实现滚动。
void CWingImgDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
file://如果鼠标按下
if( (nFlags & MK_LBUTTON) == MK_LBUTTON )
{
m_lPicNewLeft = point.x;
m_lPicNewTop = point.y;
DWORD dwLRShift = m_lPicNewLeft - m_lPicOldLeft;
DWORD dwTBShift = m_lPicNewTop - m_lPicOldTop;
file://改变图像显示的起始点
m_lPicLeft = m_lPicLeft - dwLRShift;
m_lPicTop = m_lPicTop - dwTBShift;
file://判断边界的语句,省去。
m_lPicOldLeft = m_lPicNewLeft;
m_lPicOldTop = m_lPicNewTop;
file://进行刷新的语句,见第四步。
}
CDialog::OnMouseMove(nFlags, point);
}
第三步:在OnPaint中显示,显示的其他部分,如图像的得来等,省去。
void CWingImgDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
file://其他的显示内容,省去。
if(m_pImgInfo != NULL)
dc.BitBlt(m_wShowAdjLeft,m_wShowAdjTop,m_lWidth,m_lHeight,&m_AdjDC,
m_lPicLeft,m_lPicTop,SRCCOPY);
CDialog::OnPaint();
}
第四步:刷新处理。
最常想到的方法,当然是使用Invalidate(TRUE);//刷新整个无效区
UpdateWindow();
这时,会刷新整个程序区域的无效区,闪烁非常严重,改正如下:
InvalidateRect(&m_rtPic,TRUE); file://仅刷新图像显示区域
UpdateWindow();
此时,仅会刷新图像所在区域,闪烁有所缓解,再进一步,可使用
InvalidateRect(&m_rtPic,TRUE); file://使用快速重画
ReDrawWindow(&m_rtPic,NULL,RDW_INTERNALPAINT| RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
进行处理,此时闪烁更进一步减小,考虑到,其他部分可能影响刷新区域,干脆将OnPaint()直接使用在此处,即变为:
OnPaint();
但如果在OnPaint()中有大量的绘图语句,这种方法仍旧不可行,考虑到不能激发OnPaint()这一因素及控制刷新范围,我采用了如下非标准的方法解决,代码如下:
CDC *pDC;
pDC = GetDC();
if(m_pImgInfo != NULL)
pDC->BitBlt(m_wShowLeft,m_wShowTop,m_lWidth,m_lHeight,&m_AdjDC,m_lPicLeft,m_lPicTop,SRCCOPY);
ReleaseDC(pDC);
这种方法很好地解决了刷新闪烁的问题,图像拖动时很平稳且无闪烁。
在图像的编程中,经常会遇到这样一种情况,在有限的区域中显示了一幅大图,这时要浏览图像的各个部分,这就需要用到图像的滚动。关于它的实现,许多书都有提及,但其中的关键点和难点,即拖动中的刷新和闪烁问题,却讲述的不多,这也是我写本文的目的所在,下面我将详细分析实现方法。
实现效果及实现方法:
在图像区域中按下鼠标左键,可拖动图像在某一有限区域中任意滚动。
方法为 :拖动时计算上次与本次的偏移,然后将图像显示的起始点进行变化并刷新图像区域。
实现部分:
第一步:响应WM_LBUTTONDOWN 消息,记录按下开始拖动的起始位置。
void CWingImgDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_lPicOldLeft = point.x;
m_lPicOldTop = point.y;
CDialog::OnLButtonDown(nFlags, point);
}
第二步:响应WM_MOUSEMOVE 消息,实现滚动。
void CWingImgDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
file://如果鼠标按下
if( (nFlags & MK_LBUTTON) == MK_LBUTTON )
{
m_lPicNewLeft = point.x;
m_lPicNewTop = point.y;
DWORD dwLRShift = m_lPicNewLeft - m_lPicOldLeft;
DWORD dwTBShift = m_lPicNewTop - m_lPicOldTop;
file://改变图像显示的起始点
m_lPicLeft = m_lPicLeft - dwLRShift;
m_lPicTop = m_lPicTop - dwTBShift;
file://判断边界的语句,省去。
m_lPicOldLeft = m_lPicNewLeft;
m_lPicOldTop = m_lPicNewTop;
file://进行刷新的语句,见第四步。
}
CDialog::OnMouseMove(nFlags, point);
}
第三步:在OnPaint中显示,显示的其他部分,如图像的得来等,省去。
void CWingImgDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
file://其他的显示内容,省去。
if(m_pImgInfo != NULL)
dc.BitBlt(m_wShowAdjLeft,m_wShowAdjTop,m_lWidth,m_lHeight,&m_AdjDC,
m_lPicLeft,m_lPicTop,SRCCOPY);
CDialog::OnPaint();
}
第四步:刷新处理。
最常想到的方法,当然是使用Invalidate(TRUE);//刷新整个无效区
UpdateWindow();
这时,会刷新整个程序区域的无效区,闪烁非常严重,改正如下:
InvalidateRect(&m_rtPic,TRUE); file://仅刷新图像显示区域
UpdateWindow();
此时,仅会刷新图像所在区域,闪烁有所缓解,再进一步,可使用
InvalidateRect(&m_rtPic,TRUE); file://使用快速重画
ReDrawWindow(&m_rtPic,NULL,RDW_INTERNALPAINT| RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
进行处理,此时闪烁更进一步减小,考虑到,其他部分可能影响刷新区域,干脆将OnPaint()直接使用在此处,即变为:
OnPaint();
但如果在OnPaint()中有大量的绘图语句,这种方法仍旧不可行,考虑到不能激发OnPaint()这一因素及控制刷新范围,我采用了如下非标准的方法解决,代码如下:
CDC *pDC;
pDC = GetDC();
if(m_pImgInfo != NULL)
pDC->BitBlt(m_wShowLeft,m_wShowTop,m_lWidth,m_lHeight,&m_AdjDC,m_lPicLeft,m_lPicTop,SRCCOPY);
ReleaseDC(pDC);
这种方法很好地解决了刷新闪烁的问题,图像拖动时很平稳且无闪烁。