但是为什么运行程序时,对话框会偶尔的跳动几下(有点频繁),看起来很不稳定。
还有使用了OnTimer()后,我在对话框中添加了一个List Control也不能正常运行,当所加载的Item的行数超过List Control
框的上端到下端的长度是就会,整个对话框就会跳个不停!List Control几乎就无法显示,只剩下两个滚动条在不停的闪!
下面是我对上面两个函数的应用,可以看一下!!!!!
int ChildDialog1::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
SetTimer(1, 750, NULL);
return 0;
}
void ChildDialog1::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
cir=(cir+1)%16;
Invalidate();
CDialog::OnTimer(nIDEvent);
}
18 个解决方案
#1
你就一个timer么?
#2
Ontimer里面不要调用Invalidate去刷新。
没调用一次Invalidate,画面控件都会重画的
没调用一次Invalidate,画面控件都会重画的
#3
恩,可以局部重绘
#4
开个线程吧
全局变量定义:
UINT ThreadProc(LPVOID pParam);
BOOL ThreadFlag = FALSE;
CWinThread *g_pThread = NULL;
启动线程:
ThreadFlag = TRUE;
g_pThread = AfxBeginThread(ThreadProc,NULL);
g_pThread ->m_bAutoDelete = TRUE;
线程函数:
UINT ThreadProc(LPVOID pParam)
{
while (TRUE == ThreadFlag)
{
//你的代码
}
return 0;
}
退出线程:
ThreadRecvFromACUFlag = FALSE;
if (NULL != g_pThread)
{
WaitForSingleObject(g_pThread->m_hThread,INFINITE);
g_pThread = NULL;
}
全局变量定义:
UINT ThreadProc(LPVOID pParam);
BOOL ThreadFlag = FALSE;
CWinThread *g_pThread = NULL;
启动线程:
ThreadFlag = TRUE;
g_pThread = AfxBeginThread(ThreadProc,NULL);
g_pThread ->m_bAutoDelete = TRUE;
线程函数:
UINT ThreadProc(LPVOID pParam)
{
while (TRUE == ThreadFlag)
{
//你的代码
}
return 0;
}
退出线程:
ThreadRecvFromACUFlag = FALSE;
if (NULL != g_pThread)
{
WaitForSingleObject(g_pThread->m_hThread,INFINITE);
g_pThread = NULL;
}
#5
你的 OnTimer里面的代码
#6
退出线程的:
ThreadRecvFromACUFlag = FALSE;
改为
ThreadFlag = FALSE;
ThreadRecvFromACUFlag = FALSE;
改为
ThreadFlag = FALSE;
#7
你750毫秒就刷新一次啊
#8
Invalidate();
换成InvalidateRect试
换成InvalidateRect试
#9
Invalidate()之后:(MFC的,顺便了)
OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。
Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。以为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。
Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。
InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow()只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT
如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。
OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。
Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。以为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。
Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。
InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow()只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT
如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。
#10
你时间间隔太短
#11
1.你刷新的频率太高了,
2.贴你的绘图相关的代码,OnPaint中的代码
2.贴你的绘图相关的代码,OnPaint中的代码
#12
主要是向实现动画效果。
#13
不停调用Invalidate()当然会闪烁了,整个对话框持续刷新,由于时间间隔太短,根本来不及显示就又刷新了,所以显示不出来是很正常的.不知道你的程序是干什么用的,可以改变程序显示方式,不如局部覆盖,或者用内存DC画图显示等方法.
#14
你不是问过这个问题吗?单文档、要在视图上移动一个BMP的图片?不是用BitBlt 解决了吗?
不要用 Invalidate();
贴下代码!
ball为全局变量
CBitmap ball;
ball.LoadBitmap(IDB_BITMAP1)
不要用 Invalidate();
贴下代码!
void CView::OnTimer(UINT nIDEvent)
{
cir+=1;
CDC *pDC = GetDC();
CDC& dc = *pDC;
CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();
ReleaseDC(pDC);
CView::OnTimer(nIDEvent);
}
ball为全局变量
CBitmap ball;
ball.LoadBitmap(IDB_BITMAP1)
#15
完善下,擦除影子
//擦除
RECT ret;
ret.left=cx;
ret.top=cy;
ret.right=cx+1;
ret.bottom=cy+24;
InvalidateRect(&ret);
cx+=1;
CDC *pDC = GetDC();
CDC& dc = *pDC;
CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();
ReleaseDC(pDC);
#16
Invalidate();
改成
Invalidate(FALSE); // 重绘时不擦除背景
就不闪了
改成
Invalidate(FALSE); // 重绘时不擦除背景
就不闪了
#17
OnTimer里面不断Invalidate(); 当然要闪。
用UpdateData(FALSE)就不闪了。
用UpdateData(FALSE)就不闪了。
#18
你是不是重绘之后闪的??
#1
你就一个timer么?
#2
Ontimer里面不要调用Invalidate去刷新。
没调用一次Invalidate,画面控件都会重画的
没调用一次Invalidate,画面控件都会重画的
#3
恩,可以局部重绘
#4
开个线程吧
全局变量定义:
UINT ThreadProc(LPVOID pParam);
BOOL ThreadFlag = FALSE;
CWinThread *g_pThread = NULL;
启动线程:
ThreadFlag = TRUE;
g_pThread = AfxBeginThread(ThreadProc,NULL);
g_pThread ->m_bAutoDelete = TRUE;
线程函数:
UINT ThreadProc(LPVOID pParam)
{
while (TRUE == ThreadFlag)
{
//你的代码
}
return 0;
}
退出线程:
ThreadRecvFromACUFlag = FALSE;
if (NULL != g_pThread)
{
WaitForSingleObject(g_pThread->m_hThread,INFINITE);
g_pThread = NULL;
}
全局变量定义:
UINT ThreadProc(LPVOID pParam);
BOOL ThreadFlag = FALSE;
CWinThread *g_pThread = NULL;
启动线程:
ThreadFlag = TRUE;
g_pThread = AfxBeginThread(ThreadProc,NULL);
g_pThread ->m_bAutoDelete = TRUE;
线程函数:
UINT ThreadProc(LPVOID pParam)
{
while (TRUE == ThreadFlag)
{
//你的代码
}
return 0;
}
退出线程:
ThreadRecvFromACUFlag = FALSE;
if (NULL != g_pThread)
{
WaitForSingleObject(g_pThread->m_hThread,INFINITE);
g_pThread = NULL;
}
#5
你的 OnTimer里面的代码
#6
退出线程的:
ThreadRecvFromACUFlag = FALSE;
改为
ThreadFlag = FALSE;
ThreadRecvFromACUFlag = FALSE;
改为
ThreadFlag = FALSE;
#7
你750毫秒就刷新一次啊
#8
Invalidate();
换成InvalidateRect试
换成InvalidateRect试
#9
Invalidate()之后:(MFC的,顺便了)
OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。
Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。以为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。
Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。
InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow()只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT
如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。
OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。
Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。以为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。
Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。
InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow()只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT
如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。
#10
你时间间隔太短
#11
1.你刷新的频率太高了,
2.贴你的绘图相关的代码,OnPaint中的代码
2.贴你的绘图相关的代码,OnPaint中的代码
#12
主要是向实现动画效果。
#13
不停调用Invalidate()当然会闪烁了,整个对话框持续刷新,由于时间间隔太短,根本来不及显示就又刷新了,所以显示不出来是很正常的.不知道你的程序是干什么用的,可以改变程序显示方式,不如局部覆盖,或者用内存DC画图显示等方法.
#14
你不是问过这个问题吗?单文档、要在视图上移动一个BMP的图片?不是用BitBlt 解决了吗?
不要用 Invalidate();
贴下代码!
ball为全局变量
CBitmap ball;
ball.LoadBitmap(IDB_BITMAP1)
不要用 Invalidate();
贴下代码!
void CView::OnTimer(UINT nIDEvent)
{
cir+=1;
CDC *pDC = GetDC();
CDC& dc = *pDC;
CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();
ReleaseDC(pDC);
CView::OnTimer(nIDEvent);
}
ball为全局变量
CBitmap ball;
ball.LoadBitmap(IDB_BITMAP1)
#15
完善下,擦除影子
//擦除
RECT ret;
ret.left=cx;
ret.top=cy;
ret.right=cx+1;
ret.bottom=cy+24;
InvalidateRect(&ret);
cx+=1;
CDC *pDC = GetDC();
CDC& dc = *pDC;
CDC memDc;
memDc.CreateCompatibleDC(&dc);
CBitmap* pOld=(CBitmap*)memDc.SelectObject(&ball);
dc.BitBlt(cx,cy,24,24,&memDc,0,0,SRCCOPY);
memDc.SelectObject(pOld);
memDc.DeleteDC();
ReleaseDC(pDC);
#16
Invalidate();
改成
Invalidate(FALSE); // 重绘时不擦除背景
就不闪了
改成
Invalidate(FALSE); // 重绘时不擦除背景
就不闪了
#17
OnTimer里面不断Invalidate(); 当然要闪。
用UpdateData(FALSE)就不闪了。
用UpdateData(FALSE)就不闪了。
#18
你是不是重绘之后闪的??