Timer, TimerWnd

有时候, 你需要一个定时器. 可能你在这个线程里还没有属于自己的窗口. 你当然也可以不创建窗口而直接使用线程里的定时器消息. 就象这样(以 CWinThread 的一个派生类为例)

CYourThread::InitInstance()
{
 m_nTimerID = ::SetTimer(NULL, NULL, 1000/*ms*/,  NULL);
 ...
}

BEGIN_MESSAGE_MAP()
 ON_WM_TIMER()
 ...
END_MESSAGE_MAP

CYourThread::OnTimer(UINT nID)
{
 if (nID == m_nTimerID)
 {
  // do your work here
 }
}
 
这个方法的缺点在于. 如果你不用 CWinThread 的派生类. 可能添加 WM_TIMER 的消息处理函数比较麻烦. 甚至不能实现

所以, 还是回到老办法, 创建一个辅助窗口. 写自己的 WM_TIMER 处理函数.
但如果使用 MFC 的 CWnd 的派生类. 会遇到这样的问题. 你可能不能跨线程来关闭这个窗口. 或者一些其他的窗口操作. 又是由于 MFC 里臭名昭著的大量的 map, 这些 map 都是线程相关的.
既然我们这里的应用只是一个定时器的辅助窗口. 我们完全可以自己实现一个 TimerWnd. 就像这样:

 

//  TimerWnd.h start here -------------------------------------------------

/* Nico 06-8-14 1124 
 a simple HWND encapsulation for timer 
*/


#ifndef _TIMERWND_H_
#define  _TIMERWND_H_

class  TimerWnd
{
public:
 TimerWnd()
{Initialize();}

private:
    
static  LRESULT CALLBACK
    WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
    
{
  
if (uiMsg == WM_TIMER)
  
{
   TimerWnd 
*that = (TimerWnd *)GetWindowLong(hwnd, GWL_USERDATA);
   that
->OnTimer(wParam);
   
return 0;
  }

        
return DefWindowProc(hwnd, uiMsg, wParam, lParam);
    }


 
virtual void OnTimer(UINT uID)
 
{
  OutputDebugString(
"TimerWnd::OnTimer  ");
 }

    
    
static BOOL Initialize()
    
{
        WNDCLASSW wc 
= {0, WndProc, 0000000, L"TimerWndClass"};
   
        
if (!RegisterClassW(&wc)) return FALSE;
  
return TRUE;
    }

    
public:
    BOOL Create()
    
{
        HWND hwnd 
= CreateWindowW(
            L
"TimerWndClass",                      /* Class Name */
            L
"TimerWnd",                      /* Title */
            WS_OVERLAPPED,            
/* Style */
            CW_USEDEFAULT, CW_USEDEFAULT,   
/* Position */
            CW_USEDEFAULT, CW_USEDEFAULT,   
/* Size */
            NULL,                           
/* Parent */
            NULL,                           
/* No menu */
            NULL,                          
/* Instance */
            
0);                             /* No special parameters */

  
if (hwnd == NULL) return FALSE;
  SetWindowLong(hwnd, GWL_USERDATA, (
long)this);
        m_hwnd 
= hwnd;
  
return TRUE;
    }


 BOOL DestroyWindow()
 
{
  
return ::DestroyWindow(m_hwnd);
 }


 UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT uElapse)
 
{
  
return ::SetTimer(m_hwnd, nIDEvent, uElapse, NULL);
 }


 BOOL KillTimer(UINT_PTR uIDEvent)
 
{
  
return ::KillTimer(m_hwnd, uIDEvent);
 }

    
    HWND m_hwnd;
}
;

#endif   //  _TIMERWND_H_

//  TimerWnd.h end here -------------------------------------------------

使用起来很简单, 从 TimerWnd 派生一个窗口类. 重载 OnTimer(), 在初始化的时候调用 Create() 创建即可.. 使用简单, 不用记住繁琐的 Create 参数. 没有 MFC 的烦人的 map. 可以跨线程操作.

说说实现上的几个细节.
. 使用了宽字符版本的 API, 从理论上讲, 效率能高一点.
. 从窗口句柄转换为对象, 使用的是简单的 Set/GetWindowLong, 因为只处理 WM_TIMER, 效率不成问题, 没有使用 MFC 繁琐的 map, 也没有用 ATL 的高深的 thunk.
. 没有使用 .cpp, 直接 include 即可. 

你可能感兴趣的:(timer,api,null,Class,mfc,include)