??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
首先介绍两个函数Q?br>
d ini 文gQ?br>
1.1 用WM_TIMER来设|定时器
先请看SetTimerq个API函数的原?
UINT_PTR SetTimer(
HWND hWnd, // H口句柄
UINT_PTR nIDEvent, // 定时器IDQ多个定时器Ӟ可以通过该ID判断是哪个定时器
UINT uElapse, // 旉间隔,单位为毫U?br> TIMERPROC lpTimerFunc // 回调函数
);
例如
SetTimer(m_hWnd,1,1000,NULL); //一?U触发一ơ的定时?br>在MFCE序中SetTimer被封装在CWndcMQ调用就不用指定H口句柄?br>
于是SetTimer函数的原型变为:
UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD))
当用SetTimer函数的时候,׃生成一个计时器。函CnIDEvent指的是计时器的标识,也就是名字。nElapse指的是时间间隔,也就是每隔多长时间触发一ơ事件。第三个参数是一个回调函敎ͼ在这个函数里Q放入你惌做的事情的代码,你可以将它设定ؓNULLQ也是使用pȝ默认的回调函敎ͼpȝ默认认的是onTime函数。这个函数怎么生成的呢Q你需要在需要计时器的类的生成onTime函数Q在ClassWizard里,选择需要计时器的类Q添加WM_TIME消息映射Q就自动生成onTime函数了。然后在函数里添加代码,让代码实现功能。每隔一D|间就会自动执行一ơ?
例:
SetTimer(1,1000,NULL);
1:计时器的名称Q?
1000Q时间间隔,单位是毫U;
NULL:使用onTime函数?
当不需要计时器的时候调用KillTimer(nIDEvent);
例如QKillTimer(1);
1.2 调用回调函数
此方法首先写一个如下格式的回调函数
void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);
然后再用SetTimer(1,100,TimerProc)函数来徏一个定时器Q第三个参数是回调函数地址?br>
? 或许你会问,如果我要加入两个或者两个以上的 timer怎么办?
l箋用SetTimer函数吧,上次的timer的ID?Q这ơ可以是2Q?Q?。。。?
SetTimer(2,1000,NULL);
SetTimer(3,500,NULL);
嗯,WINDOWS会协调他们的。当然onTimer函数体也要发生变化,要在函数体内d每一个timer的处理代码:
onTimer(nIDEvent)
{
switch(nIDEvent)
{
case 1:........;
break;
case 2:.......;
break;
case 3:......;
break;
}
}
什么时候我们需要用到SetTimer函数呢?当你需要每个一D|间执行一件事的的时候就需要用SetTimer函数了?使用定时器的Ҏ比较单,通常告诉WINDOWS一个时间间隔,然后WINDOWS以此旉间隔周期性触发程序。通常有两U方法来实现Q发送WM_TIMER消息和调用应用程序定义的回调函数?
1.1 用WM_TIMER来设|定时器
先请看SetTimerq个API函数的原?
UINT_PTR SetTimer(
HWND hWnd, // H口句柄
UINT_PTR nIDEvent, // 定时器IDQ多个定时器Ӟ可以通过该ID判断是哪个定时器
UINT uElapse, // 旉间隔,单位为毫U?br> TIMERPROC lpTimerFunc // 回调函数
);
例如
SetTimer(m_hWnd,1,1000,NULL); //一?U触发一ơ的定时?br>在MFCE序中SetTimer被封装在CWndcMQ调用就不用指定H口句柄?br>
于是SetTimer函数的原型变为:
UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD))
当用SetTimer函数的时候,׃生成一个计时器。函CnIDEvent指的是计时器的标识,也就是名字。nElapse指的是时间间隔,也就是每隔多长时间触发一ơ事件。第三个参数是一个回调函敎ͼ在这个函数里Q放入你惌做的事情的代码,你可以将它设定ؓNULLQ也是使用pȝ默认的回调函敎ͼpȝ默认认的是onTime函数。这个函数怎么生成的呢Q你需要在需要计时器的类的生成onTime函数Q在ClassWizard里,选择需要计时器的类Q添加WM_TIME消息映射Q就自动生成onTime函数了。然后在函数里添加代码,让代码实现功能。每隔一D|间就会自动执行一ơ?
例:
SetTimer(1,1000,NULL);
1:计时器的名称Q?
1000Q时间间隔,单位是毫U;
NULL:使用onTime函数?
当不需要计时器的时候调用KillTimer(nIDEvent);
例如QKillTimer(1);
1.2 调用回调函数
此方法首先写一个如下格式的回调函数
void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);
然后再用SetTimer(1,100,TimerProc)函数来徏一个定时器Q第三个参数是回调函数地址?br>
? 或许你会问,如果我要加入两个或者两个以上的 timer怎么办?
l箋用SetTimer函数吧,上次的timer的ID?Q这ơ可以是2Q?Q?。。。?
SetTimer(2,1000,NULL);
SetTimer(3,500,NULL);
嗯,WINDOWS会协调他们的。当然onTimer函数体也要发生变化,要在函数体内d每一个timer的处理代码:
onTimer(nIDEvent)
{
switch(nIDEvent)
{
case 1:........;
break;
case 2:.......;
break;
case 3:......;
break;
}
}
q个函数与Windows 3.1兼容。基于Win32的应用程序应该?a href="file:///I:/华奇׃?~程语言/VISUAL%20MSDN/注册表操?regapi_3wzc.htm">RegQueryValueEx函数?
LONG RegQueryValue(
HKEY hKey, // 要查询键的句?br> LPCTSTR lpSubKey,
// 要查询子键的名字
LPTSTR lpValue, // q回字符串的~存
PLONG lpcbValue // 接收q回字符串的大小
);
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
Windows NT: HKEY_PERFORMANCE_DATA
Windows 95和Windows 98: HKEY_DYN_DATA
如果lpValue是NULLq且lpcbValue不是NULLQ这个函数返回ERROR_SUCCESSQƈ取回被lpcbData指定的变量缓存的大小Q以字节为单位)。这个ؓ值的数据~存分配最好的途径?
如果?em>lpData参数指定的缓存不够大Q这个函数返回ERROR_MORE_DATA|q取回被lpcbData指定的变量缓存的大小Q以字节为单位)?
在所有的案例中,?em>lpcbValueq回的值的大小包含字符串的l束W?
如果调用成功Q返回ERROR_SUCCESS?/p>
如果调用p|Q返回一个非雉误码Q定义在WINERROR.HQ。你可以使用带有FORMAT_MESSAGE_FROM_SYSTEM标记?a href="file:///I:/华奇׃?~程语言/VISUAL%20MSDN/注册表操?strings_0sdh.htm">FormatMessage函数获得错误的普通描qC息?/p>
能被hKey参数识别的键必须被带有KEY_QUERY_VALUE存取权限打开QKEY_READ存取权限包括KEY_QUERY_VALUE存取权限Q?
如果q个函数的ANSI版本被用(明确的调?strong>RegQueryValueExA或在包含WINDOWS.H文g前不定义UNICODEQ,q个函数在复制它?em>lpValue参数l定的缓存区前,转换存贮的Unicode字符串到ANSI字符丌Ӏ?
Windows NT: 需?.1或更高版本?br> Windows: 需要Windows 95或更高版本?br> Windows CE: 不支持?br> 头文? winreg.h?br> 输入? advapi32.lib?br> Unicode: 在Windows NT中作为Unicode和ANSI执行?/p>
Registry Overview, Registry Functions, RegEnumKey, RegEnumKeyEx, RegEnumValue, RegQueryInfoKey, RegQueryValueEx, RegSetValue, RegSetValueEx
LONG RegOpenKey(
HKEY hKey, // 要打开键的句柄
LPCTSTR lpSubKey, // 要打开子键的名字的地址
PHKEY phkResult // 要打开键的句柄的地址
);
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
Windows NT: HKEY_PERFORMANCE_DATA
Windows 95和Windows 98: HKEY_DYN_DATA
?strong>RegOpenKey函数打开地键是能?em>hKey识别的子键?
如果调用成功Q返回ERROR_SUCCESS?/p>
如果调用p|Q返回一个非雉误码Q定义在WINERROR.HQ。你可以使用带有FORMAT_MESSAGE_FROM_SYSTEM标记?a href="file:///I:/华奇׃?~程语言/VISUAL%20MSDN/注册表操?strings_0sdh.htm">FormatMessage函数获得普通错误描qC息?/p>
RegOpenKey函数使用默认的安全存取掩码打开一个键。如果打开的键需要一个不同的掩码Q函数将发生错误Q返回ERROR_ACCESS_DENIED。在q种情Ş下一个应用程序应该?strong>RegOpenKeyEx函数L定存取掩码?
为像RegCreateKey函数Q如果键在数据库不存在时Q?strong>RegOpenKey不能新徏l定键?
Windows NT: 需?.1或更高版本?br> Windows: 需要Windows 95或更高版本?br> Windows CE: 不支持?br> 文g? winreg.h?br> 输入? advapi32.lib?br> Unicode: 在Windows NT中作为Unicode和ANSI执行?/p>
Registry Overview, Registry Functions, RegCloseKey, RegCreateKey, RegCreateKeyEx, RegDeleteKey, RegOpenKeyEx
LONG RegCloseKey( HKEY hKey // 要关闭键的句?strong>);
如果调用成功Q返回ERROR_SUCCESS?/p>
如果调用p|Q返回非雉误代码(定义在WINERROR.HQ。你可以使用带有FORMAT_MESSAGE_FROM_SYSTE标记 FormatMessage函数获得普通错误描qC息?/p>
q个l定键的句柄不应该在它关闭后使用Q因为它不再有效。键句柄不应该比需要的旉短?
RegCloseKey在返回之前不需要往注册表中写信息;它可以花费几U缓存到盘的缓存区。如果一个应用程序必L的写注册信息到盘Q它可以使用RegFlushKey函数?strong>RegFlushKeyQ然而用了更多的系l资源,应该在必需时才调用它?
Windows CE: RegCloseKey函数L在返回前写信息到注册表,在Windows CE去除了缓存键的需要?
Windows NT: 需?.1或更高版本?br> Windows: 需要Windows 95或更高版本?br> Windows CE: 需?.0或更高版本?br> 头文? winreg.h?br> 输入? advapi32.lib?/p>
LONG RegQueryValueEx( HKEY hKey, // 要查询键的句?strong> LPTSTR lpValueName, // 要查询值的名字的地址 LPDWORD lpReserved, // 保留 LPDWORD lpType, // 值类型缓存地址 LPBYTE lpData, // 数据~存地址 LPDWORD lpcbData // 数据~存大小地址);
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
Windows NT: HKEY_PERFORMANCE_DATA
Windows 95和Windows 98: HKEY_DYN_DATA
如果lpValueName是NULL或一个空字符Ԍ""Q,q个函数扑֛q个键的未命名或默认值的cd和数据?
Windows 95和Windows 98: 每个键有一个默认|最初的不包含数据)。在Windows 95Q这人默认值类型LREG_SZ。在Windows 98Q默认键的类型最初是REG_SZQ但可以通过RegSetValueEx指定一个默认gؓ不同的类型?
Windows NT: 键不能自动拥有一个未命名或默认的|未命名的值可以是Mcd?
?/th> | 含意 |
---|---|
REG_BINARY | 二进制数据?/td> |
REG_DWORD | 一?2位数字?/td> |
REG_DWORD_LITTLE_ENDIAN | 一个little-endian格式?2位数字。这相当于REG_DWORD?
little-endian格式Q是一个多字节值在内存中被从低字节到高字节存贮。如Q?0x12345678在little-endian格式中被存贮?0x78 0x56 0x34 0x12)?/p> Windows NT, Windows 95,和Windows 98是有意运行在little-endian计算ZpM的。例如像一些UNIXpȝQ一个用户必连接到big-endian体系的计机上? |
REG_DWORD_BIG_ENDIAN | 一个big-endian格式?2位数字?
big-endian格式Q一个多字节值在内存职被从高字节C字节存贮。如Q?x12345678在big-endian格式中被存贮?0x12 0x34 0x56 0x78)?/p> |
REG_EXPAND_SZ | 一个包含未被引用的环境变量的以I字W结束的字符?如,"%PATH%")。它是Unicode字符串还是ANSI字符串将依赖你所使用的是Unicode函数q是ANSI函数。扩展环境变量引用,使用 ExpandEnvironmentStrings函数?/td> |
REG_LINK | 一个UnicodeW号q接?/td> |
REG_MULTI_SZ | 一个以I字W结束的字符串数l,被两个null字符l束?/td> |
REG_NONE | 未定义值类型?/td> |
REG_RESOURCE_LIST | 一个设?a class=UBBWordLink target=_blank>驱动资源列表?/td> |
REG_SZ | 一个以I字W结束的字符丌Ӏ它?Unicode字符串还?ANSI字符串将依赖你所使用的是 Unicode函数q是 ANSI函数?/td> |
如果不需要类?em>lpType参数可以为空QNULLQ?
如果数据是REG_SZ、REG_MULTI_SZ或REG_EXPAND_SZcdQ那?em>lpcbDataq将包括以空字符l束的大?
如果lpData是NULLQ?em>lpcbData参数可以是NULL?
如果?em>lpData参数指定的缓存不够大Q这个函数返回ERROR_MORE_DATA|q取回被lpcbData指定的变量缓存的大小Q以字节为单位)?
如果lpData是NULLQ?em>lpcbData不是NULLQ这个函数返回ERROR_SUCCESSQƈ取回?em>lpcbData指定的变量缓存的大小Q以字节为单位)。这个ؓ值的数据~存分配最好的途径?
Window NT: 如果hKey指定?strong>HKEY_PERFORMANCE_DATAQ?/strong>q且lpData~存太小Q?strong>RegQueryValueExq回ERROR_MORE_DATAQ但?em>lpcbData不能q回必需的缓存大。这是因用数据的大小可以在调用的下一步被改变。在q种情Ş下,你必d加缓存的大小q新调?strong>RegQueryValueEx通过lpcbData 参数更新~存大小。重复直到函数成功?你需要维护一个单独的变量ȝ意缓存的大小。因lpcbDataq回的值是可不预知的?
如果q个函数成功Q返回ERROR_SUCCESS?/p>
如果调有p|Q返回一个非雉误码Q定义在WINERROR.HQ。你可以使用带有FORMAT_MESSAGE_FROM_SYSTEM标记?a href="file:///I:/华奇׃?~程语言/VISUAL%20MSDN/注册表操?strings_0sdh.htm">FormatMessage函数获得错误的普通描qC息?/p>
?em>hKey定的键必须是被带有KEY_QUERY_VALUE标记打开的。打开键,使用RegCreateKeyEx函数?a href="file:///I:/华奇׃?~程语言/VISUAL%20MSDN/注册表操?regapi_7yns.htm">RegOpenKeyEx函数?
如果值数据是REG_SZ、REG_MULTI_SZ或REG_EXPAND_SZcdQ这个函数的ANSI版本被使用Q明的调用RegQueryValueExA或在包含WINDOWS.H文g前不定义UNICODEQ,q个函数在复制它?em>lpData指定的缓存中以前Q{换存贮地Unicode字符串ؓANSI字符丌Ӏ?
Window NT: 当调?strong>RegQueryValueEx函数q?em>hKey被设|成HKEY_PERFORMANCE_DATA句柄Q给定对象的值字W串Ӟq回数据l构往往是未定义的对象。不要感到惊Ӟq是正常的。当?strong>RegQueryValueEx函数Ӟyou should always expect to walk the returned data structure to look for the requested object.
Windows NT: 需?.1或更高版本?br> Windows: 需要Windows 95或更高版本?br> Windows CE: 需?.0或更高版本?br> 头文? winreg.h?br> 输入? advapi32.lib?br> Unicode: 在Windows NT中作为Unicode或ANSI执行?/p>
Registry Overview, Registry Functions, ExpandEnvironmentStrings, RegCreateKeyEx, RegEnumKey, RegEnumKeyEx, RegEnumValue, RegOpenKeyEx, RegQueryInfoKey, RegQueryValue
LONG RegOpenKeyEx( HKEY hKey, // 要打开主键的句?strong> LPCTSTR lpSubKey, // 要打开子键的地址名字 DWORD ulOptions, // 保留 REGSAM samDesired, // 安全存取掩码 PHKEY phkResult // 要打开键句柄的地址);
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
Windows NT: HKEY_PERFORMANCE_DATA
Windows 95和Windows 98: HKEY_DYN_DATA
?/th> | 含意 |
---|---|
KEY_ALL_ACCESS | 相当于KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, KEY_CREATE_SUB_KEY, KEY_CREATE_LINK, KEY_SET_VALUE的组合?/td> |
KEY_CREATE_LINK | 允许新徏W号q接?/td> |
KEY_CREATE_SUB_KEY | 允许新徏子键?/td> |
KEY_ENUMERATE_SUB_KEYS | 允许列D子键?/td> |
KEY_EXECUTE | 允许L作?/td> |
KEY_NOTIFY | 允许修改?/td> |
KEY_QUERY_VALUE | 允许查询子键数据?/td> |
KEY_READ | 相当于KEY_QUERY_VALUEQKEY_ENUMERATE_SUB_KEYSQKEY_NOTIFY的组?/td> |
KEY_SET_VALUE | 允许讄子键数据 |
KEY_WRITE | 相当于KEY_SET_VALUE和KEY_CREATE_SUB_KEY的组合?/td> |
如果函数取得成功Q返回ERROR_SUCCESS?/p>
如果函数调用p|Q返回一个非零的错误代码Q定义在WINERROR.H文g中)。你可以使用带有FORMAT_MESSAGE_FROM_SYSTEM标记?a href="file:///I:/华奇׃?~程语言/VISUAL%20MSDN/注册表操?strings_0sdh.htm">FormatMessage函数来获得一个错误的普通描q?/p>
?strong>RegCreateKeyEx函数不同Q如果在注册表中指定的键不存?strong>RegOpenKeyEx函数不会新徏指定键?
Windows NT: 需?/strong>3.1或更高版本?br> Windows: 需?/strong>Windows 95或更高版本?br> Windows CE: 需?/strong>1.0或更高版本?br> 头文? winreg.h?br> 输入库:advapi32.lib.
Unicode: Windows NT版本中作为Unicode和ANSI执行?/p>
]]>
RegCreateKey函数新徏l定键。如果这个键在注册表中已l存在,q个函数打开它。这个函CWindows 3.1兼容。基于Win32的应用程序应该?a href="file:///I:/华奇׃?~程语言/VISUAL%20MSDN/注册表操?regapi_1woo.htm">RegCreateKeyEx函数?
LONG RegCreateKey( HKEY hKey, // 要打开键的句柄 LPCTSTR lpSubKey, // 要打开子键的名字的地址 PHKEY phkResult // 已打开句柄的缓存区的地址);
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
Windows NT: HKEY_PERFORMANCE_DATA
Windows 95和Windows 98: HKEY_DYN_DATA
?strong>RegCreateKey打开或新建的是被hKey识别的键的子键?
如果hKey是已定保留句柄g一Q?em>lpSubKey可以为NULL。在q种情Ş下,函数phkResultq回与被传递相同的句柄?
如果调用成功Q返回ERROR_SUCCESS?/p>
如果调用p|Q返回一个非雉误码Q定义在WINERROR.HQ。你可以使用带有FORMAT_MESSAGE_FROM_SYSTEM标记?a href="file:///I:/华奇׃?~程语言/VISUAL%20MSDN/注册表操?strings_0sdh.htm">FormatMessage函数获得普通错误描qC息?/p>
一个应用程序可以?strong>RegCreateKey函数一ơ新建单独键。如Q一个应用程序可以在׃旉新徏一个四U子键(包括l定键前面的三Q象以下?em>lpSubKey参数字符Ԍ
subkey1subkey2subkey3subkey4
q个能被hKey参数识别的键必须被带有KEY_CREATE_SUB_KEY存取权限打开QKEY_WRITE存取权限包括KEY_CREATE_SUB_KEY存取权限Q?
如果lpSubKey参数是一个空字符串的地址Q函数打开q传递能?em>hKey参数识别的键?/p>
Windows NT: 需?.1或更高版本?br> Windows: 需要Windows 95或更高版本?br> Windows CE: 不支持?br> 文g? winreg.h
输入? advapi32.lib.
Unicode: 在Windows NT中作为Unicode和ANSI执行?br>
pPickle<sunraiing@yahoo.com> 14:39:38
pThreadClass
The RUNTIME_CLASS of an object derived from CWinThread.
pParam
Parameter to be passed to the controlling function as shown in the parameter to the function declaration in pfnThreadProc.
nPriority
The desired priority of the thread. If 0, the same priority as the creating thread will be used. For a full list and description of the available priorities, see SetThreadPriority in the Platform SDK.
nStackSize
Specifies the size in bytes of the stack for the new thread. If 0, the stack size defaults to the same size stack as the creating thread.
dwCreateFlags
Specifies an additional flag that controls the creation of the thread. This flag can contain one of two values:
CREATE_SUSPENDED Start the thread with a suspend count of one. Use CREATE_SUSPENDED if you want to initialize any member data of the CWinThread object, such as m_bAutoDelete or any members of your derived class, before the thread starts running. Once your initialization is complete, use CWinThread::ResumeThread to start the thread running. The thread will not execute until CWinThread::ResumeThread is called.
0 Start the thread immediately after creation.
lpSecurityAttrs
Points to a SECURITY_ATTRIBUTES structure that specifies the security attributes for the thread. If NULL, the same security attributes as the creating thread will be used. For more information on this structure, see the Platform SDK.
pPickle<sunraiing@yahoo.com> 14:41:06
CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UNT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);//用于创徏工作者线E?/p>
q回? 一个指向新U程的线E对?br>pfnThreadProc : U程的入口函?声明一定要如下: UINT MyThreadFunction( LPVOID pParam );
pParam : 传递入U程的参?注意它的cd?LPVOID,所以我们可以传递一个结构体入线E?
nPriority : U程的优先,一般设|ؓ 0 .让它和主U程h共同的优先.
nStackSize : 指定新创建的U程的栈的大?如果?0,新创建的U程h和主U程一L大小的栈
dwCreateFlags : 指定创徏U程以后,U程有怎么L标志.可以指定两个?
CREATE_SUSPENDED : U程创徏以后,会处于挂L?真到调用: ResumeThread
0 : 创徏U程后就开始运?
• | They process all input messages before performing background processing, providing good response to user input. |
• | The application "idles" (waits for an input message) when no background processing needs to be done. |
// Improved PeekMessage() loop
for(;;)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (IfBackgroundProcessingRequired())
BackgroundProcessing();
else
WaitMessage(); // Will not return until a message is posted.
}
Improved PeekMessage Loop 2
// Another improved PeekMessage() loop
for (;;)
{
for (;;)
{
if (IfBackgroundProcessingRequired())
{
if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
break;
}
else
GetMessage(&msg, NULL, 0, 0, 0);
if (msg.message == WM_QUIT)
return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
BackgroundProcessing();
}
Note that calls to functions such as IsDialogMessage() and TranslateAccelerator() can be added to these loops as appropriate.
There is one case in which the loops above need additional support: if the application waits for input from a device (for example, a fax board) that does not send standard Windows messages. For the reasons outlined above, a Windows-based application should not use a PeekMessage() loop to continuously poll the device. Rather, implement an Interrupt Service Routine (ISR) in a Dynamic-Link Library (DLL). When the ISR is called, the DLL can use the PostMessage function to inform the application that the device requires service. DLL functions can safely call the PostMessage() function because the PostMessage() function is reentrant.