Хотя таймер и не оперирует такими понятиями, как потоки, среда, создаваемая с помощью сообщений WM_TIMER, весьма напоминает многозадачную среду. Вся работа с таймером в MFC основана на двух методах: SetTimer и KillTimer класса CWnd. UINT_PTR SetTimer ( UINT_PTR nIDEvent, UINT nELAPSE, void (CALLBACK* lpfnTimer) ) Метод, при успешном завершении возвращает номер создаваемого таймера. Первый параметр - номер создаваемого таймера. Второй параметр - количество миллисекунд, через которое срабатывает таймер. Третий параметр может быть либо равен NULL, либо указывать на некоторую функцию. В первом случае сообщение WM_TIMER посылает на функцию окна и, следовательно, обработчик должен быть включён в карту сообщений. Если третий параметр отличен от NULL, то он должен указывать на некоторую функцию. Вот её структура: void CALLBACK EXPORT TimerProc ( HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime ) - hWnd - дескриптор окна
- nMsg - сообщение WM_TIMER
- nIDEvent - индификатор таймера
- dwTime - системное время
Уничтожить таймер можно с помощью метода KillTimer(UINT_PTR nIDEvent), аргументом которого является идентификатор таймера. Следует заметить что точность таймера не слишком велика. При задержке сообщения в очереди новые сообщения таймера не накапливаются, а аннулируются. Далее я приведу простую программу с двумя таймерами. Её смысл очень прост. В диалоговом окне имеется дополнительная кнопка, с помощью которой можно либо создать, либо уничтожить таймеры. Первый таймер каждую секунду формирует заголовок окна, увеличивая его длину на один символ. Второй таймер раз в 25 секунд очищает строку заголовка и посылает звуковой сигнал. Вот файл Timer1Dlg.cpp: #include "stdafx.h" #include "Timer1.h" #include "Timer1Dlg.h"
#ifdef _DEBUG #define new DEBUG_NEW #endif
extern CTimer1Dlg * dlg;
void CALLBACK EXPORT OnTimer1(HWND, UINT, UINT, DWORD);
CTimer1Dlg::CTimer1Dlg(CWnd* pParent /*=NULL*/) : CDialog(CTimer1Dlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_timer=0; s=""; }
void CTimer1Dlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_BUTTON1, m_button); }
BEGIN_MESSAGE_MAP(CTimer1Dlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1) ON_WM_TIMER() END_MESSAGE_MAP()
BOOL CTimer1Dlg::OnInitDialog() { CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE); SetIcon(m_hIcon, FALSE);
return TRUE; }
void CTimer1Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
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;
dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } }
HCURSOR CTimer1Dlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); }
void CTimer1Dlg::OnBnClickedButton1() { if(!m_timer) { SetTimer(1,1000,NULL); SetTimer(2,25000,OnTimer1); m_button.SetWindowText("Удалить"); m_timer=1; }else { KillTimer(1); KillTimer(2); m_button.SetWindowText("Таймеры"); m_timer=0; } }
void CTimer1Dlg::OnTimer(UINT nIDEvent) { CDialog::OnTimer(nIDEvent); s=s+"*"; SetWindowText(s); }
void CALLBACK EXPORT OnTimer1(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime) { dlg->s=""; dlg->SetWindowText(dlg->s); ::MessageBeep(0xFFFFFFFF); } Вот файл Timer1Dlg.h #pragma once
class CTimer1Dlg : public CDialog {
public: CTimer1Dlg(CWnd* pParent = NULL);
enum { IDD = IDD_TIMER1_DIALOG };
protected: virtual void DoDataExchange(CDataExchange* pDX);
protected: HICON m_hIcon;
virtual BOOL OnInitDialog(); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() public: CButton m_button; int m_timer; CString s; afx_msg void OnBnClickedButton1(); afx_msg void OnTimer(UINT nIDEvent); }; Файл Timer1.cpp: #include "stdafx.h" #include "Timer1.h" #include "Timer1Dlg.h"
#ifdef _DEBUG #define new DEBUG_NEW #endif
CTimer1Dlg * dlg;
BEGIN_MESSAGE_MAP(CTimer1App, CWinApp) ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP()
CTimer1App::CTimer1App() {
}
CTimer1App theApp;
BOOL CTimer1App::InitInstance() {
InitCommonControls();
CWinApp::InitInstance();
dlg = new CTimer1Dlg; m_pMainWnd = dlg; INT_PTR nResponse = dlg->DoModal(); if (nResponse == IDOK) {
} else if (nResponse == IDCANCEL) {
}
return FALSE; } Модуль Timer1.cpp содержит запускающую часть проекта. Обратите внимание на способ задания диалогового окна. Объявление указателя на диалоговое окно позволяет упростить глобальный доступ из других модулей. |