MFC中SetTimer()的用法???

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC中SetTimer()的用法???相关的知识,希望对你有一定的参考价值。

运行起来用方向建(w a s d)按一下为什么圆会一直向着按的方向运动而不是动一下 然后继续按照ontimer 里的路线运动??

代码如下:
void CKeydownView::OnDraw(CDC* pDC)


CKeydownDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CBrush *oldb,newb;
CPen newp;
if (newp.CreatePen(PS_SOLID,10,RGB(0,0,0)))
pDC->SelectObject(&newp);
if (newb.CreateSolidBrush(RGB(255,122,0)))
oldb=pDC->SelectObject(&newb);

//pDC->Rectangle(0,0,100,100);

switch(drt)

case 1:
if (y1>=50) y1-=50; y2-=50;
break;
case 2:
if (x1>=50) x1-=50; x2-=50;
break;
case 3:
if (y1<=500) y1+=50; y2+=50;
break;
case 4:
if (x1<=850) x1+=50; x2+=50;
break;


pDC->Ellipse(x1,y1,x2,y2);

void CKeydownView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

// TODO: Add your message handler code here and/or call default
switch (nChar)

case 'W':
case 'w':
drt=1;
break;
case 'a':
case 'A':
drt=2;
break;
case 's':
case 'S':
drt=3;
break;
case 'd':
case 'D':
drt=4;
break;

Invalidate();

CView::OnChar(nChar, nRepCnt, nFlags);


void CKeydownView::OnTimer(UINT nIDEvent)

// TODO: Add your message handler code here and/or call default
if (x1<=600) x1+=2;
if (x2<=600) x2+=2;
if (y1<=500) y1+=2;
if (y2<=500) y2+=2;
Invalidate();
CView::OnTimer(nIDEvent);

void CKeydownView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

// TODO: Add your message handler code here and/or call default
switch (nChar)

case VK_UP:
case 'W':
case 'w':
drt=1;
break;
case 'a':
case VK_RIGHT:
case 'A':
drt=2;
break;
case 's':
case VK_SPACE:
case 'S':
drt=3;
break;
case 'd':
case 0x25:
case 'D':
drt=4;
break;

Invalidate();

CView::OnChar(nChar, nRepCnt, nFlags);

其他代码~ 都是由MFC向导生成的框架~~

眼都花了。楼主拿支笔自己算一下就知道问题出哪里了。

我只想说:楼主的程序模块不好,强烈要求换一下,这样自己调试也可以轻松许多。

你在OnTimer里,先计算,然后Invalidate了,这样做很不错,可进入Draw里,又让Draw负责椭圆的计算工作,是不是应该这样做:
1)定义个CRect m_rectEllipse;
2)在OnTimer中计算m_rectEllipse,在按键按下时也可以计算这个m_rectEllipse。
3)在Draw里只负责画椭圆,其他都不做。
4)程序还有可以改进的地方,如闪屏会出现吗?定时器分辨率较高时应该会吧!呵呵,说下去一大堆了。

P.S.把程序模块调整一下,然后立刻就能发现问题所在了,很好找。
参考技术A void CKeydownView::OnDraw(CDC* pDC)


CKeydownDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CBrush *oldb,newb;
CPen newp;
if (newp.CreatePen(PS_SOLID,10,RGB(0,0,0)))
pDC->SelectObject(&newp);
if (newb.CreateSolidBrush(RGB(255,122,0)))
oldb=pDC->SelectObject(&newb);

//pDC->Rectangle(0,0,100,100);

/* switch(drt) //这个删了,和OnChar的switch结合,不然会看到一直按照按键的方向运动,这个是由于OnTimer里面的Invalidate();所致

case 1:
if (y1>=50) y1-=50; y2-=50;
break;
case 2:
if (x1>=50) x1-=50; x2-=50;
break;
case 3:
if (y1<=500) y1+=50; y2+=50;
break;
case 4:
if (x1<=850) x1+=50; x2+=50;
break;

*/
pDC->Ellipse(x1,y1,x2,y2);

void CKeydownView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

switch (nChar)

case 'W':
case 'w':
drt=1;
SetTimer(1,200,NULL);//注意看这里
if (y1>=50) y1-=50; y2-=50;
break;
case 'a':
case 'A':
drt=2;
SetTimer(1,200,NULL);
if (x1>=50) x1-=50; x2-=50;
break;
case 's':
case 'S':
drt=3;
SetTimer(1,200,NULL);
if (y1<=500) y1+=50; y2+=50;
break;
case 'd':
case 'D':
drt=4;
SetTimer(1,200,NULL);
if (x1<=850) x1+=50; x2+=50;
break;
default:
break;

Invalidate();

CView::OnChar(nChar, nRepCnt, nFlags);


void CKeydownView::OnTimer(UINT nIDEvent)

if(1 == nIDEvent)

if (x1<=600) x1+=2;
if (x2<=600) x2+=2;
if (y1<=500) y1+=2;
if (y2<=500) y2+=2;
Invalidate();

CView::OnTimer(nIDEvent);
参考技术B 代码不全。
首先看看是否有多个OnTimer,响应的ID是否正确。
然后考虑:OnDraw中的switch 是循环的,它在不停的绘制新出现的图形,而OnTimer也在以很短的时间间隔进行屏幕刷新,两个一起刷新可能会出现问题,最好在OnDraw函数中激活SetTimer,或者我的意思是,将两个刷新合并成一个刷新里面去。
如果出现闪烁,可以考虑双缓存绘制,即在内存中绘制好之后一起刷出,再用Invalidate。
参考技术C SetTimer()定时器的第一个参数是定时器标识,可用任一非0的整数,第二个参数是定时器的时间间隔,单位是毫秒.第三个参数取值可以是NULL,这时WM_TIMER的消息加入应用程序的消息队列中,由CWnd类对象处理
例如 SetTimer(1,1,NULL)的时间间隔是1毫秒
参考技术D 实在不行,可以找我.
你这代码不全,而且很难看清楚.

SetTimer()用法

不知道你的SetTimer是MFC的还是API的,所以都给你列出来

MFC中的SetTimer

CWnd::SetTimer
UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );

Return Value

The timer identifier of the new timer if the function is successful. An application passes this value to the KillTimer member function to kill the timer. Nonzero if successful; otherwise 0.

Parameters

nIDEvent

Specifies a nonzero timer identifier.

nElapse

Specifies the time-out value, in milliseconds.

lpfnTimer

Specifies the address of the application-supplied TimerProc callback function that processes the WM_TIMER messages. If this parameter is NULL, the WM_TIMER messages are placed in the application’s message queue and handled by the CWnd object.

Remarks

Installs a system timer. A time-out value is specified, and every time a time-out occurs, the system posts aWM_TIMER message to the installing application’s message queue or passes the message to an application-defined TimerProc callback function.

The lpfnTimer callback function need not be named TimerProc, but it must be defined as follows:

void CALLBACK EXPORT TimerProc(
HWND hWnd, // handle of CWnd that called SetTimer
UINT nMsg, // WM_TIMER
UINT nIDEvent // timer identification
DWORD dwTime // system time
);

Timers are a limited global resource; therefore it is important that an application check the value returned by the SetTimer member function to verify that a timer is actually available.

Example

// This example shows how to use CWnd::SetTimer, CWnd::KillTimer, and how to handle WM_TIMER messages. A timer is set up to send a WM_TIMER message to the main frame window every 2 seconds in OnStartTimer(). OnStopTimer will stop the timer by calling CWnd::KillTimer. OnTimer was set up through class wizard to handle WM_TIMER messages for the main frame window. In this example the PC speaker will beep every 2 seconds.

void CMainFrame::OnStartTimer()

m_nTimer = SetTimer(1, 2000, 0);


void CMainFrame::OnStopTimer()

KillTimer(m_nTimer);


void CMainFrame::OnTimer(UINT nIDEvent)

MessageBeep(0xFFFFFFFF); // Beep

// Call base class handler.
CMDIFrameWnd::OnTimer(nIDEvent);


Windows API中的SetTimer

SetTimer
The SetTimer function creates a timer with the specified time-out value.

UINT_PTR SetTimer(
HWND hWnd, // handle to window
UINT_PTR nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // timer procedure
);
Parameters
hWnd
[in] Handle to the window to be associated with the timer. This window must be owned by the calling thread. If this parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored.
nIDEvent
[in] Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.
If the hWnd parameter is not NULL and the window specified by hWnd already has a timer with the value nIDEvent, then the existing timer is replaced by the new timer. When SetTimer replaces a timer, the timer is reset. Therefore, a message will be sent after the current time-out value elapses, but the previously set time-out value is ignored.

uElapse
[in] Specifies the time-out value, in milliseconds.
lpTimerFunc
[in] Pointer to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc.
If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message's MSG structure contains the value of the hWnd parameter.

Return Values
If the function succeeds and the hWnd parameter is NULL, the return value is an integer identifying the new timer. An application can pass this value to the KillTimer function to destroy the timer.

If the function succeeds and the hWnd parameter is not NULL, then the return value is a nonzero integer. An application can pass the value of the nIDTimer parameter to the KillTimer function to destroy the timer.

If the function fails to create a timer, the return value is zero. To get extended error information, call GetLastError.

Remarks
An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.

The wParam parameter of the WM_TIMER message contains the value of the nIDEvent parameter.

The timer identifier, nIDEvent, is specific to the associated window. Another window can have its own timer which has the same identifier as a timer owned by another window. The timers are distinct.
参考技术A 用WM_TIMER来设置定时器SetTimer函数的原型UINT_PTR SetTimer(HWND hWnd, // 窗口句柄UINT_PTR nIDEvent, // 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器UINT nElapse, // 时间间隔,单位为毫秒TIMERPROC lpTimerFunc // 回调函数);返回值:类型:UINT_PTR如果函数成功,hWnd参数为0,则返回新建立的时钟编号,可以把这个时钟编号传递给KillTimer来销毁时钟.如果函数成功,hWnd参数为非0,则返回一个非零的整数,可以把这个非零的整数传递给KillTimer来销毁时钟.如果函数失败,返回值是零.若想获得更多的错误信息,调用GetLastError函数. 参考技术B Windows API
SetTimer(HWND,UNIT,UINT,TIMERPROC);
参数意义:
1.记时器所在窗口句柄
2.序号
3.记时周期
4.记时器响应函数

CWnd类的
CWnd::SetTimer
UINT SetTimer(
UINT nIDEvent,
UINT nElapse,
void (CALLBACK EXPORT* lpfnTimer)(
HWND, UINT, UINT, DWORD) );

CWnd类的用例:
void CMainFrame::OnStartTimer()
m_nTimer = SetTimer(1, 2000, 0);


void CMainFrame::OnStopTimer()
KillTimer(m_nTimer);


void CMainFrame::OnTimer(UINT nIDEvent)

MessageBeep(0xFFFFFFFF); // Beep
// Call base class handler.
CMDIFrameWnd::OnTimer(nIDEvent);
本回答被提问者采纳

以上是关于MFC中SetTimer()的用法???的主要内容,如果未能解决你的问题,请参考以下文章

MFC 单个SetTimer怎么用啊

MFC 中,全局SetTimer函数怎么用?

问下关于MFC中 SetTimer() 和 KillTimer() 的使用

mfc里SetTimer和Sleep有啥区别

mfc中的settimer函数是做啥的里面的参数呢

mfc 线程里设置定时器settimer,但是执行不道OnTimer里