SetTimer不一定要有窗体才能用的吧。
比如我的主程序没有窗体,想每隔5秒弹出一个对话框,我尝试着这样写:
#include "stdafx.h"
LRESULT CALLBACK TimerProc(HWND,UINT,UINT,DWORD);
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
// TODO: Place code here.
SetTimer(NULL,                // handle to main window 
NULL,               // timer identifier 
2000,                     //  interval 
(TIMERPROC) TimerProc); // timer callback 
while(1)
{
}

return 0;
}LRESULT CALLBACK TimerProc(void)
{
MessageBox(NULL,"xxx","xxx",MB_OK);
return 0;
}
当然不行(不要嘲笑我啊:)。应该怎样改?

解决方案 »

  1.   

    创建一个线程。
    DWORD WINAPI TimerThread(LPVOID lpVoid)
    {
       for (;;)
       {
         //do your things
        
         //then
         Sleep(2000);  //sleep interval
       }在WinMain中CreateThread
    }
      

  2.   

    做个循环用GetSystemTime()取得时间保存在变量里。
    和下一次的相减,看时间是否大于5秒,是的话输出对话框。
      

  3.   

    非窗口类中使用定时器的方法(一)    jemmylau(原作)  
      
    关键字     Visual C++ MFC 类 定时器 静态函数静态成员函数 静态数据成员 回调函数 映射类 
        
    非窗口类中使用定时器的方法作者:刘辉(网进科技 江苏 昆山 Email:[email protected] 完成时间:2003年3月12日)    摘  要  本文主要通过一些简单的例子,介绍了如何在Visual C++的窗口和非窗口类中使用定时器。重点介绍了如何用静态成员函数和静态数据成员在非窗口类中使用定时器,同时,又介绍了与定时器相关的知识,例如回调函数,C++类中的静态成员,以及模板类中的映射类等。关键字  C++ 类 定时器 静态函数静态成员函数 静态数据成员 回调函数 映射类    摘  要:This page introduce how to use timer in window class and none window class of Visual C++ by some simple samples. Use timer in none window class with static member variable and static member function is the important point. At the same time, it also tell about of some knowledge such as about timer, callback function, static member of C++ class and map class CMap of template class.关键字:C++ Class Timer static CALLBACK CMap1. 引言    定时器在Windows 的程序中的作用不可忽略,也随处可见。设定一个时间间隔每0.5秒或者1秒钟刷新一次时钟,这样就可以完成一个简单的电子钟程序。在不同的编程工具中定时器的用法也不同,Visual C++中也给我们提供了实现这种功能的方法,而且方法不只一种。在窗口类中是使用定时器比较很简单,用SetTimer()设置了定时器之后,并在Class Wizard中添加了OnTimer消息映射后,您就可以在映射函数OnTimer()中添加代码实现,来定时完成您的任务,而且还支持任意多个定时器,这种方法大家可能都会用。但是在非窗口的类中,使用定时器就没那么简单了,在类消息映射中就找不到OnTimer()方法了,类中也没有hWnd这个属性,SetTimer()也不能象原来那样使用了,下面给出了一种既不破坏类的完整性的同时又能巧妙的使用定时器的方法。2. 相关知识    在非窗口类中使用定时器,需要了解的知识比较多。首先非窗口类中没有消息映射,也没有象CWnd类具有的SetTimer()方法来设置定时器。没有消息映射,就只能靠我们自己定义的回调函数来处理定时器的消息,因此大家有必要了解一下回调函数的概念。因为回调函数只能用全局函数或者静态成员函数来实现,为了维持类的完整性,使用类的静态成员函数来作为回调函数,所以我们又需要了解一下静态数据成员和静态成员函数的性质。又因为定时器是在我们的程序中产生的,这又需要来管理定时器,所以又用到了映射表类CMap,因此介绍一下CMap的简单用法也是必不可少的。2.1 回调函数所谓回调函数就是按照一定的形式由你定义并编写实现内容,当发生某种事件时,而由系统或其它函数来调用的函数。使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己编写的一个函数(也就是回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,也就是某种事情发生的时候,利用传递的函数地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。回调函数只能是全局函数,或者是静态函数,因为这个函数只是在这个类中使用,所以为了维护类的完整性,我们用类的静态成员函数来做回调函数。2.2 C++类中的静态成员在C语言中,声明一个数据为静态类型,意味着该变量的生存周期是静态的,即在程序的开始时即分配,到程序终止时才释放。但在C++中,声明一个类中的成员为静态类型,则意味着该类的所有实例只有该成员的一个拷贝。也就是说,不管应用程序中创建了这个类的多少个对象,其静态成员只有一个副本,该副本为这个类的所有对象实例所共享,而对于非静态成员,每个类对象实例都有自己的拷贝。例如:class CPerson{public:    CString szName;    static CString szCompanyName;    CPerson();    virtual ~CPerson();};    接着用该类声明一个实例 CPerson me;    对于同一家公司员工,每个人都有不同的姓名,但是他们的公司名字是一样的,所以就可以用一个静态类型来保存,这样所有的员工都共享这个公司名称,只要一位员工更新了公司名称,则所有员工的公司名称就被更新了。静态成员被当作该类类型的全局对象,可以把一个静态数据成员和静态成员函数当成全局变量和函数那样去存储和访问,但又被隐藏在类的内部,并且清楚地与这个类相联系但又不是全局对象,同全局对象相比,使用静态成员有两个优势:    (1) 静态成员没有进入程序的全局名字空间,它属于类,它的名字只在类的范围内有效,因此不存在与程序中其他全局名字冲突的可能性。    (2) 可以实现信息隐藏,并可以保持类的完整性,可以是private(私有的)成员、public(公有的)成员或者protected(保护的)成员,而全局对象不能。2.2.1 静态数据成员
      

  4.   

    标题     非窗口类中使用定时器的方法(二)    jemmylau(原作)  
      
    关键字     Visual C++ MFC 类 定时器 静态函数静态成员函数 静态数据成员 回调函数 映射类 
        
    4. 使用定时器    Windows提供了定时器,帮助我们编写定期发送消息的程序。定时器一般通过一下两中方式通知应用程序间隔时间已到。    ⑴ 给指定窗口发送WM_TIMER消息,也就是下面的给出在窗口类中使用的方法。    ⑵ 调用一个应用程序定义的回调函数,也就是在非窗口类中使用方法。4.1 在窗口类中使用定时器    在窗口类中使用定时器比较简单。假如我们想让这个窗口上放置一个电子钟,这样我们必须每1秒或者0.5秒钟去更新显示显见。按照下面的步骤,就可以完成这个电子钟程序,并且知道如何在窗口类中使用定时器:    首先做在我们新建项目的主窗口上添加一个Label控件,用来显示时间。接着    ⑴ 用函数SetTimer设置一个定时器,函数格式如下:    UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD));这个函数是CWnd类的一个成员函数,其参数意义如下:nIDEvent: 为设定的定时器指定的定时器标志值,设置多个定时器的时候,每个定时器的值都不同,消息处理函数就是通过这个参数来判断是哪个定时器的。这里我们设定为1。nElapse: 指定发送消息的时间间隔,单位是毫秒。这里我们设定为1000,也就是一秒。lpfnTimer: 指定定时器消息由哪个回调函数来执行,如果为空,WM_TIMER将加入到应用程序的消息队列中,并由CWnd类来处理。这里我们设定为NULL。最后代码如下:SetTimer(1,1000,NULL);    ⑵ 通过Class Wizard给主窗口类添加一个WM_TIMER消息的映射函数,默认为OnTimer(UINT nIDEvent)。    ⑶ 然后我们就可以在OnTimer(UINT nIDEvent)的函数实现中添加我们的代码了。参数nIDEvent就是我们先前设定定时器时指定的标志值,在这里我们就可以通过它来区别不同的定时器,而作出不同的处理。添加的代码如下:    switch(nIDEvent)    {    case 1:        CTime m_SysTime = CTime::GetCurrentTime();        SetDlgItemText(IDC_STATIC_TIME,m_SysTime.Format("%Y年%m月%d日 %H:%M:%S"));        break;    }    代码中的IDC_STATIC_TIME就是我们先前添加的Label控件的ID。    至此,我们的电子钟的程序就完成了。
      

  5.   

    SetTimer(NULL,NULL,...)
    本身没问题
      

  6.   

    4.2 在非窗口类中使用定时器    在非窗口类中使用定时器就要用到前面我们介绍到的所有知识了。因为是无窗口类,所以我们不能使用在窗口类中用消息映射的方法来设置定时器,这时候就必须要用到回调函数。又因为回调函数是具有一定格式的,它的参数不能由我们自己来决定,所以我们没办法利用参数将this传递进去。可是静态成员函数是可以访问静态成员变量的,因此我们可以把this保存在一个静态成员变量中,在静态成员函数中就可以使用该指针,对于只有一个实例的指针,这种方法还是行的通的,由于在一个类中该静态成员变量只有一个拷贝,对于有多个实例的类,我们就不能用区分了。解决的办法就是把定时器标志值作为关键字,类实例的指针作为项,保存在一个静态映射表中,因为是标志值是唯一的,用它就可以快速检索出映射表中对应的该实例的指针,因为是静态的,所以回调函数是可以访问他们的。    首先介绍一下用于设置定时的函数:    UINT SetTimer(              HWND hWnd,              // handle of window for timer messages              UINT nIDEvent,          // timer identifier              UINT uElapse,           // time-out value              TIMERPROC lpTimerFunc   // address of timer procedure              );其中的参数意义如下:hWnd: 指定与定时器相关联的窗口的句柄。这里我们设为NULL。nIDEvent: 定时器标志值,如果hWnd参数为NULL,它将会被跳过,所以我们也设定为NULL。uElapse: 指定发送消息的时间间隔,单位是毫秒。这里我们不指定,用参数传入。lpTimerFunc: 指定当间隔时间到的时候被统治的函数的地址,也就是这里的回调函数。这个函数的格式必须为以下格式:VOID CALLBACK TimerProc(                        HWND hwnd,     // handle of window for timer messages                        UINT uMsg,     // WM_TIMER message                        UINT idEvent,  // timer identifier                        DWORD dwTime   // current system time                        );其中的参数意义如下:hwnd: 与定时器相关联的窗口的句柄。uMsg: WM_TIMER消息。idEvent: 定时器标志值。deTime: 系统启动后所以经过的时间,单位毫秒。   最后设定定时器的代码为:    m_nTimerID = SetTimer(NULL,NULL,nElapse,MyTimerProc);先通过Class Wizard创建一个无窗口类,选择Generic Class类类型,类名称为CMyTimer,该类的作用是每隔一段时间提醒我们做某件事情,然后用这个类创建三个实例,每个实例以不同的时间间隔提醒我们做不同的事情。MyTimer.h#include <afxtempl.h> class CMyTimer;//用模板类中的映射表类定义一种数据类型typedef CMap<UINT,UINT,CMyTimer*,CMyTimer*> CTimerMap; class CMyTimer  {public:         //设置定时器,nElapse表示时间间隔,sz表示要提示的内容         void SetMyTimer(UINT nElapse,CString sz);         //销毁该实例的定时器         void KillMyTimer();         //保存该实例的定时器标志值         UINT m_nTimerID;         //静态数据成员要提示的内容         CString szContent;         //声明静态数据成员,映射表类,用于保存所有的定时器信息         static CTimerMap m_sTimeMap;         //静态成员函数,用于处理定时器的消息         static void CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);         CMyTimer();         virtual ~CMyTimer();};MyTimer.cpp#include "stdafx.h"#include "MyTimer.h" //必须要在外部定义一下静态数据成员CTimerMap CMyTimer::m_sTimeMap; CMyTimer::CMyTimer(){         m_nTimerID = 0;} CMyTimer::~CMyTimer(){} void CALLBACK CMyTimer::MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime){         CString sz;         sz.Format("%d号定时器:%s",                   idEvent,                   m_sTimeMap[idEvent]->szContent);         AfxMessageBox(sz);} void CMyTimer::SetMyTimer(UINT nElapse,CString sz){         szContent = sz;         m_nTimerID = SetTimer(NULL,NULL,nElapse,MyTimerProc);         m_sTimeMap[m_nTimerID] = this;} void CMyTimer::KillMyTimer(){         KillTimer(NULL,m_nTimerID);         m_sTimeMap.RemoveKey(m_nTimerID);}    这样就完成了在非窗口类中使用定时器的方法。以上这些代码都在Windwos 2000 Professional 和 Visual C++ 6.0中编译通过。5. 结论    通过以上的介绍,大家应该知道如何在静态成员函数中访问非静态数据成员和非静态成员函数,并了解了如何在非窗口类中使用定时器。当然这只是解决这个问题的一种方法,相信还有更好的解决办法。这个种方法有一定的灵活性,可以在很多地方用到,例如网络程序中的连接超时以及定时刷新等需要自己来控制,就可以使用这种方法。
      

  7.   

    #include <windows.h>void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
    MSG msg;
    SetTimer(NULL, 0, 2000, (TIMERPROC)TimerProc);

    while(GetMessage(&msg, NULL, 0, 0))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    return msg.wParam;
    }void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
    MessageBox(NULL, "Timer 1000 Milliseconds", "Timer", MB_OK);
    PostQuitMessage(0);
    }