效果图如下。
自定义计时器,不依赖窗口类,封装计时器的生成和释放。
MyTimer.h如下。
/* 非窗口类实现定时器 参考: http://blog.csdn.net/bookish_2010_prj/article/details/6631938 http://blog.sina.com.cn/s/blog_4dbcd2730100xc69.html */ #pragma once #include <map> using namespace std; class CMyTimerUseDlg; typedef map<UINT, CMyTimerUseDlg*> COwnerMap; class CMyTimer { public: CMyTimer(); virtual ~CMyTimer(); //设置定时器,nElapse表示时间间隔 void SetMyTimer(UINT nElapse, CMyTimerUseDlg* pOwner); //销毁该实例的定时器 void KillMyTimer(); //获取定时器ID UINT GetTimerID(); private: //静态成员函数,用于处理定时器的消息 static void CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime); private: //静态数据成员,映射表类,用于保存定时器拥有者 static COwnerMap m_sTimeMap; //保存该实例的定时器标志值 UINT m_nTimerID; };
#include "StdAfx.h" #include "MyTimer.h" #include "MyTimerUseDlg.h" COwnerMap CMyTimer::m_sTimeMap; CMyTimer::CMyTimer() : m_nTimerID(-1) { } CMyTimer::~CMyTimer() { } void CALLBACK CMyTimer::MyTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime) { CMyTimerUseDlg* pOwner = m_sTimeMap[idEvent]; if (pOwner != NULL) { pOwner->RefreshTime(idEvent); } } void CMyTimer::SetMyTimer(UINT nElapse, CMyTimerUseDlg* pOwner) { if (m_nTimerID != -1) { //定时器已经设置则返回 return; } m_nTimerID = (UINT)SetTimer(NULL,NULL,nElapse,MyTimerProc); m_sTimeMap[m_nTimerID] = pOwner; } void CMyTimer::KillMyTimer() { KillTimer(NULL, m_nTimerID); COwnerMap::iterator mFindPos = m_sTimeMap.find(m_nTimerID); if (mFindPos != m_sTimeMap.end()) { m_sTimeMap.erase(mFindPos); } m_nTimerID = -1; } UINT CMyTimer::GetTimerID() { return m_nTimerID; }
// MyTimerUseDlg.h : header file // #pragma once #include "MyTimer.h" #include "resource.h" // CMyTimerUseDlg dialog class CMyTimerUseDlg : public CDialog { // Construction public: CMyTimerUseDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data enum { IDD = IDD_MYTIMERUSE_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation public: void RefreshTime(UINT idEvent); protected: HICON m_hIcon; // Generated message map functions virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnBnClickedStart(); afx_msg void OnBnClickedEnd(); DECLARE_MESSAGE_MAP() private: CMyTimer m_ChinaTimer; CMyTimer m_USATimer; };
// MyTimerUseDlg.cpp : implementation file // #include "stdafx.h" #include "MyTimerUse.h" #include "MyTimerUseDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMyTimerUseDlg dialog CMyTimerUseDlg::CMyTimerUseDlg(CWnd* pParent /*=NULL*/) : CDialog(CMyTimerUseDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CMyTimerUseDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CMyTimerUseDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_BTN_START, &CMyTimerUseDlg::OnBnClickedStart) ON_BN_CLICKED(IDC_BTN_END, &CMyTimerUseDlg::OnBnClickedEnd) END_MESSAGE_MAP() // CMyTimerUseDlg message handlers BOOL CMyTimerUseDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control } void CMyTimerUseDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CMyTimerUseDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CMyTimerUseDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CMyTimerUseDlg::OnBnClickedStart() { m_ChinaTimer.SetMyTimer(1000, this); m_USATimer.SetMyTimer(1000, this); } void CMyTimerUseDlg::OnBnClickedEnd() { m_ChinaTimer.KillMyTimer(); m_USATimer.KillMyTimer(); } void CMyTimerUseDlg::RefreshTime(UINT idEvent) { UINT nChinaID = m_ChinaTimer.GetTimerID(); UINT nUSAID = m_USATimer.GetTimerID(); if (idEvent == nChinaID) { CTime sysTime = CTime::GetCurrentTime(); SetDlgItemText(IDC_CHINA_TIME, sysTime.Format(_T("%Y-%m-%d %H:%M:%S"))); } else if (idEvent == nUSAID) { //太平洋时间与北京时间,15个小时时差 CTime sysTime = CTime::GetCurrentTime(); CTimeSpan timeSpan = CTimeSpan(0, 15, 0, 0); sysTime -= timeSpan; SetDlgItemText(IDC_USA_TIME, sysTime.Format(_T("%Y-%m-%d %H:%M:%S"))); } }