⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lc_bcb_37.txt

📁 c++ builder 的一些txt文档
💻 TXT
字号:

定 时 器 
时 器 
一、精确计时 
 BCB的定时器控件Timer计时精度为55ms,且定时器的消息在多任务操作系统中的优先级很低,不能得到及时响应,往往不能满足实时控制环境下的应用。不过微软公司在 
Win32 API函数库中已经为用户提供了一组用于高精度计时的底层函数,如果用户使用得当,计时精度可到1ms。这个计时精度,对于一般的实时系统控制完全可以满足要求。现将由BCB提供的重新封装后的一组与时间相关的主要接口函数(函数名、参数、功能与Win32 
API基本相同)说明如下: 
 1.DWORD timeGetTime(void) 
 返回从Windows启动开始经过的毫秒数。最大值为2的32次方,约49.71天。 
 2.MMRESULT timeSetEvent(UINT uDelay,UINT 
uResolution,LPTIMECALLBACK lpTimeProc,DWORD dwUser,UINTfuEvent) 
 
该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数,成功后返回事件的标识代码,否则返回NULL.参数说明如下: 
 uDelay:以毫秒制定事件的周期。 
 UResolution:以毫秒指定延时的精度,数值越小定时器事件分辩率越高。缺省值为1ms. 
 LpTimeProc:指向一个回调函数。 
 DwUser:存放用户提供的回调数据。 
 FuEvent:指定定时器事件类型:TIME_ONESHOT:uDelay毫秒后只产生一次事件。 
 
TIME_PERIODIC:每隔uDelay毫秒周期性地产生事件。 
 3.MMRESULT timeKillEvent(UINT uTimerID) 
 
该函数取消一个指定的定时器回调事件。uTimerID标识要取消的事件(由timeSetEvent函数返回的标识符)。如果定时器时间不存在则返回MMSYSERR_INVALPARAM。 
 void CALLBACK TimeProc(UINT uID,UINT uMsg,DWORD 
dwUser,DWORD dw1,DWORD dw2); 
 
该函数是一个应用程序定义的回调函数,出现定时器事件时该函数被调用。TimeProc是应用程序定义的函数名的占位符。使用该函数时要注意的是,它只能调用以下有限的几组API函数:PostMessage, 
timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, 
midiOutLongMsg, OutputDebugString。同时也不要使用完成时间很长的API函数,程序尽可能简短。 
 
使用以上一组函数就可以完成毫秒级精度的计时和控制(在BCB使用时要将头文件mmsystem.h加到程序中)。由于将定时控制精确到几毫秒,定时器事件将占用大量的CPU时间和系统资源,所以在满足控制要求的前提下,应尽量将参数uResolution的数值增大。而且定时器实时控制功能完成后要尽快释放。 
二、Windows 95 中 的 定 时 器 的 应 用 (李 振) 
 在windows95 编 程 中 有 时 要 用 到 定 时 器 的 功 能, 
大 家 常 用 的 是 通 过SetTimer 函 数 设 置 一 个 定 时 器, 在 事 件WM_TIMER 
响 应 函 数 中 处 理, 然 后 用KillTimer 函 数 取 消 此 定 时 器。 但 
此 种 方 式 的 定 时 器 只 能 精 确 到 大 约55 毫 秒, 对 于55 毫 秒 
以 下 的 时 间 精 度 便 无 能 为 力。 
 笔 者 在 这 里 向 大 家 提 供 一 个 可 以 精 确 到1 毫 秒 
的 定 时 器 — — 多 媒 体 定 时 器。 它 主 要 通 过 以 下 函 数 来 
实 现: 
---- timeBeginPeriod — — 建 立 应 用 程 序 使 用 的 定 时 器 分 辨 
率; 
---- timeEndPeriod — — 清 除 前 面 用timeBeginPeriod 函 数 建 立 的 最 
小 定 时 器 分 辨 率; 
---- timeSetEvent — — 产 生 一 个 在 指 定 的 时 间 或 时 间 周 期 间 
隔 内 执 行 的 定 时 器 事 件; 
---- timeKillEvent — — 删 除 前 面 用timeSetEvent 产 生 的 定 时 器 事 
件; 
---- timeGetDevCaps — — 返 回 关 于 定 时 器 服 务 能 力 的 信 息。 
---- 下 面 就 结 合 一 段 程 序 来 具 体 说 明 它 的 用 法。 这 段 
程 序 的 主 要 功 能 是: 设 置 两 个 时 钟 定 时 器, 一 个 间 隔 
是1 毫 秒, 一 个 间 隔 是2 秒,每 执 行 一 次, 输 出 当 前 系 统 
时 钟 值 到 文 件 “cure.out”, 以 比 较 此 定 时 器 的 精 确 
度。( 此 程 序 在 中 文windows95 及Microsoft VC5.0 编 译 通 过。 只 节 
取 与 定 时 器 有 关 的 部 分 程 序。) 
 
#include < stdio.h > 
 
//包含所用系统函数的头文件, 
如果编译有问题,可调整此语句的位置 
 
#include < mmsystem.h > 
 
//定义1毫秒和2秒时钟间隔,以毫秒为单位 
 
#define ONE_MILLI_SECOND1 
 
#define TWO_SECOND 2000 
 
//定义时钟分辨率,以毫秒为单位 
 
#define TIMER_ACCURACY1 
 
UINT wTimerRes_1ms,wTimerRes_2s; //定义时间间隔 
 
UINT wAccuracy;//定义分辨率 
 
UINT TimerID_1ms,TimerID_2s;//定义定时器句柄 
 
CCureApp::CCureApp(): fout("cure.out", ios::out)//打开输出文件“cure.out” 
 
{ 
 
// TODO: add construction code here, 
 
// Place all significant 
 
initialization in InitInstance 
 
//给时间间隔变量赋值 
 
wTimerRes_1ms = ONE_MILLI_SECOND ; 
 
wTimerRes_2s = TWO_SECOND; 
 
TIMECAPS tc; 
 
//通过函数timeGetDevCaps取出系统的分辨率取值范围(对intel系统, 
 
1~16毫秒),//如果无错则继续 
 
if(timeGetDevCaps(&tc, sizeof(TIMECAPS))== TIMERR_NOERROR) 
 
{ 
 
//分辨率的值不能超出系统的取值范围 
 
wAccuracy = min(max(tc.wPeriodMin, 
 
TIMER_ACCURACY),tc.wPeriodMax); 
 
//调用timeBeginPeriod函数设置定时器的分辨率,类似于for循环的步长 
 
timeBeginPeriod(wAccuracy); 
 
//设置定时器 
 
InitializeTimer(); 
 
} 
 
} 
 
CCureApp::~CCureApp() 
 
{ 
 
//结束时钟 
 
fout < < "结束时钟" < < endl; 
 
//删除两个定时器 
 
timeKillEvent(TimerID_1ms); 
 
timeKillEvent(TimerID_2s); 
 
//删除设置的分辨率 
 
timeEndPeriod(wAccuracy); 
 
} 
注:使用完的定时器及分辨率一定要删除,否则系统会越来越慢。 
 
void CCureApp::InitializeTimer() 
 
{ 
 
StartOneMilliSecondTimer(); 
 
StartTwoSecondTimer(); 
 
} 
 
//一毫秒定时器的回调函数,类似于中断处理程序 
 
voidPASCAL//一定要声明为全局PASCAL函数,否则编译会有问题 
 
OneMilliSecondProc(UINT wTimerID, UINT msg, 
 
DWORD dwUser, DWORD dw1, DWORD dw2) 
 
{ 
 
static int ms = 0;//定义计数器 
 
CCureApp *app = (CCureApp *)dwUser; 
 
//取得系统时间以毫秒为单位 
 
DWORD osBinaryTime = GetTickCount(); 
 
//输出计数器值和当前系统时间到文件 
 
app- >fout < < ++ms < < ": 1ms : " 
 
< < osBinaryTime < < endl; 
 
} 
 
//加装1毫秒定时器 
 
void CCureApp::StartOneMilliSecondTimer() 
 
{ 
 
if((TimerID_1ms = timeSetEvent(wTimerRes_1ms, wAccuracy, 
 
(LPTIMECALLBACK) OneMilliSecondProc,//回调函数 
 
(DWORD)this,//用户自传送到回调函数的数据 
 
/*周期调用,只使用一次用TIME_ONESHOT*/ 
 
TIME_PERIODIC)) == 0) 
 
{ 
 
AfxMessageBox("不能计时", MB_OK | MB_ICONASTERISK); 
 
} 
 
else//不等于0表明加装成功,返回此定时器的句柄 
 
fout < < "16ms计时:" < < endl; 
 
} 
 以下为2秒定时器的回调函数和加装函数,与1毫秒的类似; 
 
void PASCAL TwoSecondProc(UINT wTimerID, 
UINT msg, 
 
DWORD dwUser, DWORD dw1, DWORD dw2) 
 
{ 
 
static int s = 0; 
 
CCureApp *app = (CCureApp *)dwUser; 
 
DWORD osBinaryTime = GetTickCount(); 
 
app- >fout < < "***********************" < < endl; 
 
app- >fout < < ++s < < ": 2s : " < < 
osBinaryTime < < endl; 
 
} 
 
void CCureApp::StartTwoSecondTimer() 
 
{ 
 
if((TimerID_2s = timeSetEvent(wTimerRes_2s, wAccuracy, 
 
(LPTIMECALLBACK) TwoSecondProc, (DWORD)this, 
 
TIME_PERIODIC)) == 0) 
 
{ 
 
AfxMessageBox("不能计时", MB_OK | MB_ICONASTERISK); 
 
} 
 
else 
 
fout < < "2s计时:" < < endl; 
 
} 
三、(网友 
leex2000 关于定时器的回答) 
用 Win95 的 VxD 中的VTD_Get_Real_Time 调用, 你能获得 0.8 微秒的计数.这是我所知道 
Win95 能给出的最小时间间隔, Win95 的定时器是没有用的, 
因为定时器消息的优先权很低, 最多到 0.5 毫秒,再低就没戏了. 
 
返回
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -