我做了一个对话框应用程序,我使用OnTimer()函数设置计时器,并有SetTimer(1,750,NULL);但是为什么运行程序时,对话框会偶尔的跳动几下(有点频繁),看起来很不稳定。还有使用了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);
}
{
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);
}
没调用一次Invalidate,画面控件都会重画的
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;}
ThreadRecvFromACUFlag = FALSE;
改为
ThreadFlag = FALSE;
换成InvalidateRect试
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调用之后的语句。
2.贴你的绘图相关的代码,OnPaint中的代码
不要用 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)
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);
改成
Invalidate(FALSE); // 重绘时不擦除背景
就不闪了