《Windows API每日一练》7.2 计时器的三种使用方法

news2024/11/26 13:52:41

如果程序在整个运行过程中需要一个计时器,在WinMain函数中或窗口过程处理WM_CREATE 消息时,调用SetTimer函数创建一个计时器。在离开WinMain函数时或是处理WM_DESTROY消息时,调用KillTimer函数销毁计时器。基于调用SetTimer参数的不同,可采取三种不同的方法使用计时器。

本节必须掌握的知识点:

        第43练:使用计时器方法一

        第44练:使用计时器方法二

        使用计时器方法三

7.2.1 第43练:使用计时器方法一

/*------------------------------------------------------------------

043  WIN32 API 每日一练

     第43个例子BEEPER1.C:使用计时器方法一

     WM_TIMER消息

     SetTimer函数:WM_CREATE时创建计时器

     KillTimer函数:WM_DESTORY时销毁

(c) www.bcdaren.com, 2020

----------------------------------------------------------------*/

#include <windows.h>

#define ID_TIMER 1

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

 PSTR szCmdLine, int iCmdShow)

{

     static TCHAR szAppName[] = TEXT("Beeper1");

    (略)

     return msg.wParam;

}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)

{

     static BOOL fFlipFlop = FALSE;//标记值

     HBRUSH hBrush;

     PAINTSTRUCT ps;

     RECT rect;

     HDC hdc;

     switch (message)

     {

     case WM_CREATE:

          //创建计时器,间隔1秒发送一次WM_TIMER

          SetTimer(hwnd,ID_TIMER,1000,NULL);

          return 0;

     case WM_TIMER:

          MessageBeep(-1);//响铃

          fFlipFlop = !fFlipFlop;//标记值取反

          InvalidateRect(hwnd,NULL,FALSE);//重绘窗口

          return 0;

     case WM_PAINT:

          hdc = BeginPaint(hwnd,&ps);

          //选择画刷

          hBrush = CreateSolidBrush(fFlipFlop ? RGB(0,0,255) : RGB(255,0,0));

          GetClientRect(hwnd,&rect);

          //绘制并填充矩形

          FillRect(hdc,&rect,hBrush);

          EndPaint(hwnd,&ps);

          DeleteObject(hBrush);

          return 0;

     case WM_DESTROY:

          //销毁计时器

          KillTimer(hwnd,ID_TIMER);

          PostQuitMessage(0);

          return 0;

     }

     return DefWindowProc(hwnd,message,wParam,lParam);

}

/******************************************************************************

WM_TIMER消息:计时器到期时,将其发布到安装线程的消息队列中

wParam [输入]计时器标识符。

lParam [输入]指向应用程序定义的回调函数的指针,该指针在安装计时器时传递给SetTimer函数。

*******************************************************************************

SetTimer函数:用指定的超时值创建一个计时器

UINT_PTR SetTimer(

  HWND      hWnd,   //与计时器关联的窗口的句柄

  UINT_PTR  nIDEvent,//非零计时器标识符

  UINT      uElapse,//超时值--间隔时间,以毫秒为单位。

  TIMERPROC lpTimerFunc//当超时值过去时,指向要通知的回调函数指针

);

*******************************************************************************

KillTimer函数:销毁指定的计时器

BOOL KillTimer(

  HWND     hWnd,

  UINT_PTR uIDEvent//计时器ID

);

*/

       运行结果:

图7-1 使用计时器方法一

 

总结

  1. 实例BEEPER1.C的实现非常简单。首先窗口过程在处理WM_CREATE消息时,调用SetTimer函数创建了一个计时器:

SetTimer(hwnd,ID_TIMER,1000,NULL);

参数ID_TIMER为计时器ID。参数1000以毫秒为单位,1000毫秒等于1秒,即每间隔1秒向窗口消息队列发送一次WM_TIMER消息。最后一个参数为计时器回调函数,NULL表示未设置回调函数。这是使用计时器方法一的典型特征,通过处理WM_TIMER消息响应计时器,而不是使用计时器回调函数。

       2.接着处理WM_TIMER消息时,响铃的同时,将标志值fFlipFlop取反,然后调用InvalidateRect函数重绘窗口客户区。

       3.处理WM_PAINT消息时,创建一个蓝红不断切换的画刷(每接收到一次WM_TIMER消息切换一次,即大约每秒切换一次),填充矩形。

       4.处理WM_DESTROY消息时,调用KillTimer函数销毁计时器:

KillTimer(hwnd,ID_TIMER);

7.2.2 第44练:使用计时器方法二

/*------------------------------------------------------------------

044.C -- A daily practice

     第44个例子BEEPER2.C:使用计时器方法二

     CALLBACK TimerProc 回调函数

(c) www.bcdaren.com, 2020

----------------------------------------------------------------*/

#include <windows.h>

#define ID_TIMER 1

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

void CALLBACK TimerProc (HWND, UINT, UINT, DWORD) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

 PSTR szCmdLine, int iCmdShow)

{

     static TCHAR szAppName[] = TEXT("Beeper2");

    (略)

     return msg.wParam;

}

//计时器回调函数

void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID,DWORD dwTime)

{

     static BOOL fFlipFlop = FALSE;

     HBRUSH hBrush;

     RECT rect;

     HDC hdc;

     MessageBeep(-1);//响铃

     fFlipFlop = !fFlipFlop;//取反

     GetClientRect(hwnd, &rect);//获取客户区矩形参数

     hdc = GetDC(hwnd);

     //创建红色或蓝色画刷

     hBrush = CreateSolidBrush(fFlipFlop ? RGB(0, 0, 255) : RGB(255, 0, 0));

     FillRect(hdc, &rect, hBrush);//填充矩形框

     ReleaseDC(hwnd,hdc);//释放DC

     DeleteObject(hBrush);//删除画刷

}

//窗口过程

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)

{

     switch (message)

     {

     case WM_CREATE:

          //创建计时器,TimerProc为计时器回调函数

          SetTimer(hwnd,ID_TIMER,1000,TimerProc);

          return 0;

     case WM_DESTROY:

          //销毁计时器

          KillTimer(hwnd,ID_TIMER);

          PostQuitMessage(0);

          return 0;

     }

     return DefWindowProc(hwnd,message,wParam,lParam);

}

/******************************************************************************

CALLBACK TimerProc 回调函数

函数定义

void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID,DWORD dwTime)

hwnd参数:调用SetTimer时指定的窗口句柄。

UINT message参数:Windows只发送 WM_TIMER消息到TimeerProc,所以消息参数总是WM_TIMER。

UINT iTimerID参数:计时器的 ID。

DWORD dwTime:从GetTickCount函数返回的值,它记录了自从Windows启动到现在所逝去的毫秒数,最长为49.7天。

函数调用

SetTimer(hwnd,ID_TIMER,1000,TimerProc);//创建计时器

SetTimer函数的第四个参数必须设定为回调函数的地址

*/

       运行结果:

图7-2 使用计时器方法二

 

总结

计时器回调函数是在计时器事件发生时被调用的函数,用于执行特定的操作或触发相应的事件。

实例BEEPER2.C的窗口过程在处理WM_CREATE消息时,调用SetTimer函数创建计时器的前三个参数与实例BEEPER1.C完全相同,只是最后一个参数计时器的回调函数不再是NULL,而是TimerProc。

SetTimer(hwnd,ID_TIMER,1000,TimerProc);

与此相应,窗口过程不再需要处理WM_TIMER消息。窗口过程对WM_TIMER消息和WM_PAINT消息的处理放到了计时器回调函数TimerProc中,仅此而已。

7.2.3 使用计时器方法三

第三种设置计时器的方法与第二种方法相似,只不过SetTimer的hwnd参数被设置为 NULL,而且第二个参数(正常情况下是计时器的ID)也被忽略了。此外,这个函数会返回计时器的ID:

iTimerlD = SetTimer (NULL, 0, wMsecInterval, TimerProc);

如果SetTimer函数返回的iTimerlD为0,表示没有可用的计时器,这样的情况是极罕见的。

传给KillTimer的第一个参数(通常是窗口的句柄)也必须是NULL。计时器的ID必须是从SetTimer返回的值:

KillTimer (NULL, iTimerlD);

传给TimerProc计时器函数的hwnd参数也将是NULL。这种设置计时器的方法很少用 到。如果在程序中,需要在不同的时刻调用很多次SetTimer,但又不想记录哪些计时器ID 已经被使用过,那么这种方法可能会派上用场。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1878864.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#异常提示.mp3的文件不是一个有效的波形文件

解决方法: 使用格式工厂将mp3格式的文件转为wav格式

从笔灵到AI去痕:全方位提升内容创作与学术诚信

内容为王&#xff0c;在内容创作的世界中尤为重要。然而&#xff0c;面对写作时常常感到无从下手&#xff1a;有时缺乏灵感&#xff0c;有时难以表达清楚自己的想法。AI写作助手的出现&#xff0c;为这些问题提供了创新的解决方案&#xff0c;极大地改变了内容创作的过程。 今…

android轮播图入门1——简单无限自动轮播图

目标 目标是实现一个简单的轮播图&#xff0c;特征如下&#xff1a; 只展示本地图片可以无限轮播&#xff0c;在第一帧时也可以向前轮播可以自动轮播 code 先上代码&#xff0c;需要事先准备几张本地图片当素材 MainActivity: package com.example.loopapplication;import…

快速了解《大模型赋能下的AI2.0数字人平台》白皮书

在生成式AI和大模型的赋能下&#xff0c;数字人迎来AI 2.0时代。它能否成为每个人的“数字分身”&#xff0c;转化为新型的AI劳动力工具&#xff1f;商汤科技与上海市人工智能技术协会、零壹智库、增强现实核心技术产业联盟联合发布《大模型赋能下的AI 2.0数字人平台》。《白皮…

利用微信开放标签<wx-open-launch-weapp>在H5中跳转微信小程序报错完美的解决方案

一、报错&#xff1a; [WXTAG] [JSCORE] The slot <template> or <script type"text/wxtag-template"> of <wx-open-launch-weapp> is missing 二、源码 官方源代码如下&#xff0c;<script type"text/wxtag-template"></sc…

智能社区服务小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;房屋信息管理&#xff0c;住户信息管理&#xff0c;家政服务管理&#xff0c;家政预约管理&#xff0c;报修信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;房屋信…

# Sharding-JDBC从入门到精通(3)- Sharding-JDBC 入门程序

Sharding-JDBC从入门到精通&#xff08;3&#xff09;- Sharding-JDBC 入门程序 一、Sharding-JDBC 入门程序&#xff08;水平分表&#xff09;-环境搭建 1、需求说明 使用 Sharding-JDBC 完成对订单表的水平分表&#xff0c;通过快速入门程序的开发&#xff0c;快速体验 Sh…

Unity制作一个简单抽卡系统(简单好抄)

业务流程&#xff1a;点击抽卡——>播放动画——>显示抽卡面板——>将随机结果添加到面板中——>关闭面板 1.准备素材并导入Unity中&#xff08;包含2个抽卡动画&#xff0c;抽卡结果的图片&#xff0c;一个背景图片&#xff0c;一个你的展示图片&#xff09; 2.给…

mac电脑游戏推荐:NBA 2K24 街机版下载

NBA 2K24 街机版是一款由2K Sports开发并发行的篮球游戏&#xff0c;属于著名的NBA 2K系列。这款游戏为玩家提供了与NBA联赛中真实球员和球队互动的机会&#xff0c;体验篮球比赛的激情与紧张。街机版的NBA 2K24通常会在游戏厅、商场等公共场所设置&#xff0c;供玩家投币游玩。…

动手学深度学习(Pytorch版)代码实践 -计算机视觉-48全连接卷积神经网络(FCN)

48全连接卷积神经网络&#xff08;FCN&#xff09; 1.构造函数 import torch import torchvision from torch import nn from torch.nn import functional as F import matplotlib.pyplot as plt import liliPytorch as lp from d2l import torch as d2l# 构造模型 pretrained…

如何在 Linux 中后台运行进程?

一、后台进程 在后台运行进程是 Linux 系统中的常见要求。在后台运行进程允许您在进程独立运行时继续使用终端或执行其他命令。这对于长时间运行的任务或当您想要同时执行多个命令时特别有用。 在深入研究各种方法之前&#xff0c;让我们先了解一下什么是后台进程。在 Linux 中…

数字图像处理期末复习题1

个人名片&#xff1a; &#x1f393;作者简介&#xff1a;嵌入式领域优质创作者&#x1f310;个人主页&#xff1a;妄北y &#x1f4de;个人QQ&#xff1a;2061314755 &#x1f48c;个人邮箱&#xff1a;[mailto:2061314755qq.com] &#x1f4f1;个人微信&#xff1a;Vir2025WB…

甄选范文“论云上自动化运维及其应用”,软考高级论文,系统架构设计师论文

论文真题 云上自动化运维是传统IT运维和DevOps的延伸,通过云原生架构实现运维的再进化。云上自动化运维可以有效帮助企业降低IT运维成本,提升系统的灵活度,以及系统的交付速度,增强系统的可靠性,构建更加安全、可信、开放的业务平台。 请围绕“云上自动化运维及其应用”…

PICO 4S泄露信息更新,配备骁龙XR2 Gen 2,单眼分辨率2160×2160

根据最新的泄露信息汇总&#xff0c;PICO 4S确实有望成为一款高性能的VR头显&#xff0c;其核心规格和特性包括&#xff1a; 处理器与内存&#xff1a;搭载了高通骁龙XR2 Gen 2芯片组&#xff0c;这是针对VR/AR设备优化的高端处理器&#xff0c;能提供更强大的计算能力和效率。…

利用BFS或动态规划解决路径算法问题

最小路径和和不同路径 一、力扣64. 最小路径和1.找出DP状态2.找出DP状态转移方程3. 算法实现 二、力扣62. 不同路径思路1&#xff1a;BFS实现思路2&#xff1a;动态规划 一、力扣64. 最小路径和 给定一个包含非负整数的 m x n 网格&#xff0c;请找出一条从左上角到右下角的路…

浅谈如何在linux上部署java环境

文章目录 一、部署环境1.1、JDK1.2、Tomcat1.3、MySQL 二、将自己写的的程序部署到云服务器上 一、部署环境 为了在linux上部署 Java web 程序&#xff0c;需要安装一下环境。 1.1、JDK 直接使用 yum 命令安装 openjdk。我们 windows系统上 下载的是 oracle 官方的 jdk。而 …

Redisson框架

1. Redisson锁与Redis订阅与发布模式的联系&#xff1a; Redisson锁中&#xff0c;使用订阅发布模式去通知等待锁的客户端&#xff1a;锁已经释放&#xff0c;可以进行抢锁。 publish channel_name message&#xff1a;将消息发送到指定频道 解锁时&#xff0c;在Lua解锁脚本…

vue开发网站--关于window.print()调取打印

1.vue点击按钮调取打印 点击按钮&#xff1a; 调取打印该页面&#xff1a; <div click"clickDown()">下载</div>methods: {//下载-调取打印clickDown() {window.print()}, }<style>/* 点击打印的样式 */media print {.clickDown {display: no…

昇思25天学习打卡营第七天|模型训练

背景 提供免费算力支持&#xff0c;有交流群有值班教师答疑的华为昇思训练营进入第七天了。 今天是第七天&#xff0c;前六天的学习内容可以看链接 昇思25天学习打卡营第一天|快速入门 昇思25天学习打卡营第二天|张量 Tensor 昇思25天学习打卡营第三天|数据集Dataset 昇思25天…

Altair SimSolid无网格快速结构仿真软件

Altair SimSolid软件作为一款快速无网格划分工具&#xff0c;凭借其独特的算法和计算能力&#xff0c;简化了工程师和分析师在进行复杂结构分析时的操作。它不仅提高了分析效率&#xff0c;降低了出错的可能性&#xff0c;还为用户提供了丰富的分析功能和直观易用的操作体验。在…