不用WM_TIMER消息,通过标准回调函数实现双计时器协同工作
彻底弄请window计时器原理
//by dengpeiyou 2020.12.11
// MFCCallBaockProDlg.cpp: 实现文件
#include “pch.h”
#include “framework.h”
#include “MFCCallBaockPro.h”
#include “MFCCallBaockProDlg.h”
#include “afxdialogex.h”
#include “resource.h”
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMFCCallBaockProDlg 对话框
-
CMFCCallBaockProDlg::CMFCCallBaockProDlg(CWnd* pParent /
=nullptr/)
-
CDialog(IDD_MFCCALLBAOCKPRO_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFCCallBaockProDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMFCCallBaockProDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_SETTIMER, &CMFCCallBaockProDlg::OnBnClickedBtnSettimer)
ON_BN_CLICKED(IDC_BTN_KILLTIMER, &CMFCCallBaockProDlg::OnBnClickedBtnKilltimer)
END_MESSAGE_MAP()
// CMFCCallBaockProDlg 消息处理程序
BOOL CMFCCallBaockProDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CMFCCallBaockProDlg::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 CMFCCallBaockProDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
//全局公用回调函数(自定义)
void CALLBACK TimeProc(HWND hWnd, UINT nMsg, UINT nTimerid, DWORD dwTime)
{
//1.UINT nMsg:#define WM_TIMER 0x0113=275(这个回调只捕获WM_TIMER消息)
static long long StartTime = dwTime/1000;
unsigned int MsgInt = nMsg;
CString TotalTime;
//2.UINT nTimerid:计时器的标识符,即哪个计时器触发了这个回调
//3.当系统有多个计时器时,只能用这一个回调,要分别处理只用switch(nTimerid) {case:1}这样的语句进行处理
//4.DWORD dwTime:自系统启动以来经过的毫秒数。这是GetTickCount函数返回的值。
switch(nTimerid)
{
case 1:
//MessageBox(hWnd, L"回调动作", L"提示", MB_OK);
SetDlgItemText(hWnd,IDC_EDIT_TIP,L"1号定时器回调动作");
TotalTime.Format(L"计时器触发持续时间%d秒…", dwTime/1000- StartTime);
SetDlgItemText(hWnd,IDC_EDIT_TIP2, TotalTime);
break;
case 2:
//MessageBox(hWnd, L"二号定时器回调动作", L"提示", MB_OK);
SetDlgItemText(hWnd, IDC_EDIT_TIP, L"2号随后调皮动作");
break;
default:
break;
}
}
//设置2个计时器和回调函数
void CMFCCallBaockProDlg::OnBnClickedBtnSettimer()
{
void(CALLBACK *pTime)(HWND hWnd, UINT nMsg, UINT nTimerid, DWORD dwTime); //定义指向函数的指针
pTime = TimeProc; //回用调函数地址初始化指针(函数名即地址)
//1.第一个默认参数就是this指针,即hWnd.这里是窗口类的成员函数.
//2.第二个参数是计时器序号;
//3.第三个参数是时间间隔(毫秒)
//4.第四个是回调函数指针(指向函数的指针)
SetTimer(1, 1200, &TimeProc);
SetTimer(2, 3000, &TimeProc);
}
//停止两个计时器
void CMFCCallBaockProDlg::OnBnClickedBtnKilltimer()
{
// TODO: 停止两个定时器
KillTimer(1);
KillTimer(2);
SetDlgItemText(IDC_EDIT_TIP, L"计时器已停止工作");
SetDlgItemText(IDC_EDIT_TIP2, L"");
}