??xml version="1.0" encoding="utf-8" standalone="yes"?>
一个网友的提问Q提醒有必要对WingdowsXP?#8220;Regsvr32”命o作一要介l—?/font>
“Regsvr32.exe”命o是用来对“ActiveX控g”q行注册的?/font>
Regsvr32命o格式
/u 卸蝲ActiveX控g
/s 注册成功后不昄操作成功信息?br>/c 控制台输?br>/I 调用DllInstall安装函数q将可选的参数[cmdline]传给它,当?/u时调用卸载函?/font>
Regsvr32主要功能
A、修?IE 览?/font>
如果发现IE不能打开新的H口Q用”鼠标左键“点击链接没有Q何反应,用鼠标右键点击超链接Q在弹出的菜单中选择“在新H口打开”也没有Q何反应—?br> 1、单?#8220;开?->q行”Q在“q行”H口中,输入“regsvr32 actxprxy.dll”Q然?#8220;定”Q接着会出C个信息对话框“DllRegisterServer in actxprxy.dll succeeded”Q再ơ点?#8220;定”Q?br> 2、再ơ打开“q行”H口Q输?#8220;regsvr32 shdocvw.dll”Q单?#8220;定”Q?br> 3、重新启动WindowspȝQ运行IEQ就会发现——OK了?br>
B、卸载无?#8220;鸡肋”
Windows XP自带ZIP功能Q占用了很多pȝ资源Q其功能q不如第三方解压~Y件。如要卸载它—?br> 点击“开?#8594;q行”Q在q行对话框中输入“regsvr32 /u zipfldr.dll”Q单?#8220;定”后,弹出卸蝲成功信息框,完成卸载ZIP功能。恢复ZIP功能Q输?#8220;regsvr32 zipfldr.dll”卛_?br>
C、防范脚本病?/font>
当前嵌在|页中的脚本病毒很是厉害。很多脚本病毒的复制、传播都M开“FSO对象QFile System ObjectQ?#8221;Q因此禁?#8220;File System Object”p有效地控制脚本病毒的传播。方法—?br> 单击“开?->q行”Q在“q行”H口中,输入”regsvr32 /u scrrun.dll"Q就可以用FSO对象。需要用FSO对象Ӟ输入“regsvr32 scrrun.dll ”卛_?/font>
Z建立目Q请选择Win32 控制台项目(Win32 Console ApplicationQ,q且在应用程序设|标{(the advanced tabQ上Q选择DLL和空目选项。DLLs可能q不如你惛_的那样难。首先写你的头文Ӟheader fileQ;UCؓDLLTutorial.h。这个文件与其它头文件一P其中只是一些函数的原型?br>
#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream> #if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endifextern "C"
{
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
#endif
前面两行指示~译器只包含q个文g一ơ。extern "C"告诉~译器该部分可以在C/C++中用?/p>
在VC++中这里有两个Ҏ(gu)来导出函敎ͼ
1、用__declspecQ一个Microsoft定义的关键字?/p>
2、创Z个模块定义文?Module-Definition File?DEF)。第一U方法稍E比W二U方法简单些Q但两种都工作得很好?/p>
__declspec(dllexport)导出函数W号到在你的DLL中的一个存储类。当下面一行被定义时我定义DECLDIR来运行这个函敎ͼ
#define DLL_EXPORT同时也导入函数如果下面一?
#define DLL_EXPORT
没有在源文g中出现。在此情况下Q你导出函数AddQint a, int b)和Function()?/p>
现在Q你需要写一个将要称为DLLTutorial.cpp的源文g?br>
#include <iostream>q里你定义了QDLL中的Q所有函数。Int Add(int a, int b)只简单地两个数相加而void Function(void)只是在你的DLL被调用时Q将信息Q通知你。在我像你展C如何用DLL前,我想告诉你一些关于模块定义文Ӟ.defQ的内容?
#include "DLL_Tutorial.h"#define DLL_EXPORT extern "C"
{
DECLDIR int Add( int a, int b )
{
return( a + b );
} DECLDIR void Function( void )
{
std::cout << "DLL Called!" << std::endl;
} }
模块定义文gQ?defQ?/strong>
模块定义文g是一个有着.def文g扩展名的文本文g。它被用于导Z个DLL的函敎ͼ和__declspec(dllexport)很相|但是.def文gq不是Microsoft定义的。一?def文g中只有两个必需的部分:LIBRARY ?EXPORTS。让我们先看一个基本的.def文gE后我将解析之?br>
LIBRARY dll_tutorial
DESCRIPTION "our simple DLL"
EXPORTS
Add @1
Function @2
W一行,''LIBRARY''是一个必需的部分。它告诉链接器(linkerQ如何命名你的DLL。下面被标识?'DESCRIPTION''的部分ƈ不是必需的,但是我喜Ƣ把它放q去。该语句字W串写入 .rdata 节[?MSDN]Q它告诉Z谁可能用这个DLLQ这个DLL做什么或它ؓ了什么(存在Q。再下面的部分标识ؓ''EXPORTS''是另一个必需的部分;q个部分使得该函数可以被其它应用E序讉K到ƈ且它创徏一个导入库。当你生成这个项目时Q不仅是一?dll文g被创建,而且一个文件扩展名?lib的导出库也被创徏了。除了前面的部分以外Q这里还有其它四个部分标识ؓQNAME, STACKSIZE, SECTIONS, ?VERSION。我不再在本文中涉及这些内容,但是如果你在Internet上搜索,我想你将扑ֈ一些东西(译注Q?MSDN2003上对模板定义文g各部分内Ҏ(gu)详尽解释Q请参阅Q。另外,一个分?;)开始一个注解,如同''//''在C++中一栗?/p>
现在你已l创Z你的DLLQ你需要学习如何在一个应用程序中使用它了。当q个DLL被生成后Q它创徏了一?dll文g和一?lib文gQ这两个都是你需要的?/p>
隐式链接
q里有两个方法来载入一个DLLQ一个方法是捷径另一个则相比要复杂些。捷径是只链接到?lib 文gq将.dll文g|入你的新项目的路径中去。因此,创徏一个新的空的Win32控制台项目ƈd一个源文g。将你做的DLL攑օ你的新项目相同的目录下?/p>
#include <iostream>
#include <DLLTutorial.h>int main()
{
Function();
std::cout << Add(32, 58) << "\n";
return(1);
}
你必需要链接到DLLTutorial.lib文g。我在项目属性中讄了,但是你可能会用下面的语句代替Q?/p>
#pragma comment(lib, "DLLTutorial.lib")
h意我让编译器来查看我的DLL文g夹已获得.lib文g同时让它Z看下该目录中的DLL头文件。如果你不想q么做,你可以L把他们放入你的新目的目录中q?"Q引P而不?lt;>。这是载入一个DLL的简单方法?/p>
昄链接
隄的加载DLL的方法是有稍微有点复杂的。你需要函数指针和一些Windows函数。但是,通过q种载入DLLs的方法,你不需要DLL?lib或头文gQ而只需要DLL。下面列Z些代码,我稍后将解析之?/p>
#include <iostream>
#include <windows.h>
typedef int (*AddFunc)(int,int);
typedef void (*FunctionFunc)();int main()
_AddFunc = (AddFunc)GetProcAddress(hInstLibrary, "Add");
{
AddFunc _AddFunc;
FunctionFunc _FunctionFunc;
HINSTANCE hInstLibrary = LoadLibrary("DLL_Tutorial.dll"); if (hInstLibrary == NULL)
{
FreeLibrary(hInstLibrary);
}
_FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary, "Function"); if ((_AddFunc == NULL) || (_FunctionFunc == NULL))
{
FreeLibrary(hInstLibrary);
} std::cout << _AddFunc(23, 43) << std::endl;
_FunctionFunc(); std::cin.get(); FreeLibrary(hInstLibrary); return(1);
}
首先你会注意刎ͼq里包括q了文g“windows.h”同时U走?#8220;DLL_Tutorial.h”。原因很单:因ؓwindows.h包含了一些Windows函数Q当然你现在只需要其中几个而已。它也包含了一些将会用到的Windows特定变量。你可以LDLL的头文gQDLL_Tutorial.hQ因为-如我前面所_当你使用q个Ҏ(gu)载入DLL时你q不需要它?/p>
下面你会看到Q以下面形式的一块古灵_怪的代码:
typedef int (*AddFunc)(int,int);
typedef void (*FunctionFunc)();
q是函数指针。因是一个关于DLL的自学指南,深入探究函数指针出了本指南的范_因此Q现在我们只把它们当作DLL包含的函数的别名。我喜欢在尾部用“Func”命名之?int,int)部分是这个函数的参数部分Q比如,Add函数要获得两个整敎ͼ因此Q你需要它们(译注Q指(int,int)部分Q作为函数指针的参数。Function函数没有参数Q因此你让它为空。main()部分中的前面两行是声明函数指针以使得你可以认为它们等同于DLL内部的函数。我只是喜欢预先定义它们?/p>
一个HINSTANCE是一个Windows数据cdQ是一个实例的句柄Q在此情况下Q这个实例将是这个DLL。你可以通过使用函数LoadLibrary()获得DLL的实例,它获得一个名UC为参数。在调用LoadLibrary函数后,你必需查看一下函数返回是否成功。你可以通过查HINSTANCE是否{于NULLQ在Windows.h中定义ؓ0或Windows.h包含的一个头文gQ来查看其是否成功。如果其{于NULLQ该句柄是无效的,q且你必需释放q个库。换句话_你必需释放DLL获得的内存。如果函数返回成功,你的HINSTANCE包含了指向DLL的句柄?/p>
一旦你获得了指向DLL的句柄,你现在可以从DLL中重新获得函数。ؓ了这样作Q你必须使用函数GetProcAddress()Q它?yu)DLL的句柄(你可以用HINSTANCEQ和函数的名UC为参数。你可以让函数指针获得由GetProcAddress()q回的|同时你必需GetProcAddress()转换为那个函数定义的函数指针。D个例子,对于Add()函数Q你必需GetProcAddress()转换为AddFuncQ这是它知道参数及q回值的原因。现在,最好先定函数指针是否{于NULL以及它们拥有DLL的函数。这只是一个简单的if语句Q如果其中一个等于NULLQ你必需如前所q释攑ֺ?/p>
一旦函数指针拥有DLL的函敎ͼ你现在就可以使用它们了,但是q里有一个需要注意的地方Q你不能使用函数的实际名Uͼ你必需使用函数指针来调用它们。在那以后,所有你需要做的是释放库如此而已?/p>
现在你知道了DLL的一些基本知识。你知道如何创徏它们Q你也知道如何用两种不同的方法链接它们。这里仍然有更多的东襉K要我们学习,但我把它们留l你们自己探索了和更的作者来写了?/p>
例子Q?br>建立一个空的dll工程Q?br>新徏.h文g
#ifdef DLL1_API
#else
#define DLL1_API _declspec(dllimport)
#endif
extern "C" DLL1_API int add(int a, int b);
extern "C" DLL1_API int subtract(int a, int b);
class DLL1_API Point
{
public:
void outPoint(int x, int y);
};
新徏.cpp文g
#define DLL1_API _declspec(dllexport)
#include "Dll1.h"
#include <Windows.h>
#include <stdio.h>
int add(int a, int b)
{
return a + b;
}
int subtract(int a, int b)
{
return a - b;
}
void Point::outPoint(int x, int y)
{
HWND hwnd=GetForegroundWindow();
HDC hdc=GetDC(hwnd);
TCHAR buf[20];
memset(buf,0,20);
wsprintf(buf,L"x=%d,y=%d",x,y);
TextOut(hdc,0,0,buf,wcslen(buf));
ReleaseDC(hwnd,hdc);
}
~译工程Q把生成的dllQ和.lib攑ֈ应用的工E下?br>#include "Dll1.h"
#pragma comment(lib, "TestDll.lib")
应用工程和导入工E?/p>
关键字:外挂Q连q看
引言Q?/strong>
最q在朋友那搞了个q连看游戏来玩玩Q觉得还不错Q不q就是玩不过人家Q?记得以前在一本书上看到过q连看外挂的做法Q还比较单,自己q没忘,于是下定军_Q?自己做一个,然后……。哈哈,看谁q打得过我?br> 好了Q现在说下外挂的具体思\Q我假设大家都知道连q看游戏的规则)?q个外挂无非是要电(sh)脑来帮我门找到相同的囄q看他们是否q通。这里有两个问题Q一?是怎么让电(sh)脑区别不同的囄呢?q里有个单的办法Q就是在每个囄中取5个点Q然?这5个点的像素值相加做U图片的IDQ这样一般不会出现重复的IDQ如下图所CZQ?/p>
q样W一个问题就解决了,W二个问题就是怎么判断它们是否q通,q个(zhn)研I下代码O(jin)K拉?好了现在我们假设W二个问题已l解决了Q那么,我们只需要往q连看游戏的H口的两个相同且q通的囄的地方发送两个鼠标单ȝ消息 O(jin)K了或者在他们上面M个圈提示以下。下面是E序q行是的样子Q?/p>
看到没,两个相同的图片被外挂E序标记了颜艌Ӏ或者你可以直接点击“自动消除”来自动消除两 个图片?/p>
~程实现Q?/strong>
q里有个隄Q就是该q连看的游戏的背景不是单色的Q是一q图片,那我们怎么区分 到底是背景还是前景的囄呢?我这里采用了个笨办法Q就是用调试的办法去跟踪Q把每个区域?背景也生成了它们的IDQ到时比较一下就是了。这里就是我跟踪得到的数据,我把它门写到了数l里 到时候用是了。相关代码如下:
//q里Ҏ(gu)的是背景的ID int BackGround[]={83886075,83886060,59434490,82188285,83820266,65305594,83754472, 79584810,82141361,71323293,79582750,79584250,75889042,83818977,62589434, 83175162,83332551,83553749,83818467,73624378,81705626,82759346,82496174, 82100272,81070586,81468437,83754215,83885803,77729230,73148330,78524918, 77217286,83754215,68069635,83597193,80299161,81172078,83027654,83503432, 83686365,65042170,59778810,62410490,83356632,67567649,83523625,81967762, 74584570,83885803,78520804,79577810,83027658,83818467,82220538,61620986, 83820266,83687393,83555050,83818222,83886072}; m_pBackGround=new int[BK_COUNT]; for(int i=0;i< BK_COUNT;i++) { m_pBackGround[i]=BackGround[i]; }下面的函数就是根据图片的行号和列h生成囄的IDQ如果是背景囄则返回一个标志?br>
//************该函数根据由x、y指定的行列返回该位置的方块的ID? //如果是背景则q回 BACKGROUND int CLLK_CheatDlg::GetRectData(int x, int y) { CPoint ptPos[5]; //五个像素? COLORREF colorData[5]; int nRetVal=0; int basicX,basicY; //该方块左上角的坐? basicX=x*BLOCK_WIDTH; basicY=y*BLOCK_HEIGHT; //取该方块?个点判断 ptPos[0].x=basicX+BLOCK_WIDTH/2; //中间? ptPos[0].y=basicY+BLOCK_HEIGHT/2; ptPos[1].x=ptPos[0].x; //上边 ptPos[1].y=ptPos[0].y-5; ptPos[2].x=ptPos[0].x; ptPos[2].y=ptPos[0].y+5; //下边 ptPos[3].x=ptPos[0].x-5; ptPos[3].y=ptPos[0].y; //左边 ptPos[4].x=ptPos[0].x+5; //双 ptPos[4].y=ptPos[0].y; for(int i=0;i< 5;i++) { colorData[i] = GetPixel(m_MemDC.m_hDC,ptPos[i].x,ptPos[i].y); } for(i=0;i< 5;i++) { nRetVal+=colorData[i]; } for(i=0;i< BK_COUNT;i++) { if(nRetVal==m_pBackGround[i]) return BACKGROUND; } return nRetVal; }接下来是判断两个囄是否q通,代码如下Q?br>
BOOL CLLK_CheatDlg::IsLink(int x1, int y1, int x2, int y2) { //X直连方式 if(x1==x2) { if(X1_Link_X2(x1,y1,y2)) return TRUE; } //Y直连方式 else if(y1==y2) { if(Y1_Link_Y2(x1,x2,y1)) return TRUE; } //一个{弯直角的联通方? if(OneCornerLink(x1,y1,x2,y2)) { return TRUE; } //两个转弯直角的联通方? else if(TwoCornerLink(x1,y1,x2,y2)) { return TRUE; } return FALSE; }q下主要的工作已做的差不多了Q接下来是挨个查找相同的图片,q判断它们是否连通的Q如果是则提C或?直接消除。这样一个简单的外挂做成了Q是不是不敢怿Q?
其他的代码请查看源文件?br>
l束?/strong>
q个E序q有点小BUGQ就是有时会查不到可以消除的囄Q有可能是获取背景囄的ID时没有获?到准的值导致程序发送的消息得不到效果。如果大家有好的办法可以自己d善一下?
VC旉到的问题Q收集整理如下:
问题一Q?br>LINK : fatal error LNK1104: cannot open file "mfc42ud.lib"
~少支持Unicode的文ӞMFC安装的时候,默认是不安装支持Unicode的相x件的在vc 的安装盘上有Q在vc98\MFC\Lib\? q需要dllQ在vc98\Debug下。我把这些库打了个包Q上传了?br>
下蝲地址Q?a >http://coosign.bokee.com/inc/MFC42UD.jpg
?jpg改ؓ.rar解压。把lib攑ֈvc的mfc\lib下,dll攑ֈwindows\system32下?/p>
问题二:
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main2006-11-06 11:00引:我猜你是直接打开Q或~辑Q了一个WinmainE序Build。VC++此时假定你要建立ConsoleE序而不是GUIE序Q而ConsoleE序的Startup Code要蝲入的是main()而不是Winmain(),Dq接p|。改正的Ҏ(gu)是将菜单Project/Settings下LinkOption内的/subsystem:console改ؓ/subsystem:windows。更E_的做法是以后先New一个Win32 GUI ProjectQ再拯入你的程?再Build?/p>
在纹理合成时到q这个错误,用上q方法解决了Q?nbsp;
1、当cL板的定义及实现分(卛_在不同文件中Q时Q在其他文g中包含类模板的定义必d含其cd现文Ӟ?cpp文gQ,而不能包含类定义文gQ即.h文gQ,否则收?#8220;error LNK2001”错误?
2、若是一般的c(即不是模板类Q,在其他文件包含则必须包含头文Ӟ?h文gQ类声明文gQ,而不能包含源文gQ即.cpp文gQ类实现文gQ,否则收?#8220;error LNK2005”错误?
如:
///test.h文g
#ifndef HH
#define HH
class CTest
{
public:
CTest();
~CTest();
int get();
void set(int d);
private:
int num;
};
#endif
///test.cpp文g
#include"lll.h"
CTest::CTest()
{
};
CTest::~CTest()
{
};
int CTest::get()
{
return num;
}
void CTest::set(int d)
{
num=d;
}
///main文g
#include"test.cpp" //q里应该?include"test.h"
#include<iostream>
using namespace std;
int main()
{
CTest tt;
int n;
cin>>n;
tt.set(n);
cout<<tt.get()<<endl;
return 0;
}
以上E序收到如下错误:
main.obj : error LNK2005: "public: __thiscall CTest::CTest(void)" (??0clll@@QAE@XZ
main.obj : error LNK2005: "public: __thiscall CTest::~CTest(void)" (??1clll@@QAE@XZ
main.obj : error LNK2005: "public: int __thiscall CTest::get(void)" (?get@clll@@QAEHXZ
main.obj : error LNK2005: "public: void __thiscall CTest::set(int)" (?set@clll@@QAEXH@Z
Debug/tt.exe : fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.
又如Q?/font>
///test文gQ?
#ifndef HH
#define HH
template<class T>
class CTest
{
public:
CTest();
~CTest();
T get();
void set(T d);
private:
T num;
};
#endif
///test.cpp文g
#include"test.h"
template<class T>
CTest<T>::CTest()
{
};
template<class T>
CTest<T>::~CTest()
{
};
template<class T>
T CTest<T>::get()
{
return num;
}
template<class T>
void CTest<T>::set(T d)
{
num=d;
}
///main文gQ?
#include"test.h" //q里应改?include"test.cpp"
#include<iostream>
using namespace std;
int main()
{
CTest<int> tt;
int n;
cin>>n;
tt.set(n);
cout<<tt.get()<<endl;
return 0;
}
如上E序收到如下错误:
main.obj : error LNK2001: unresolved external symbol "public: __thiscall CTest<int>::~CTest<int>(void)" (??1?$clll@H@@QAE@XZ
main.obj : error LNK2001: unresolved external symbol "public: int __thiscall CTest<int>::get(void)" (?get@?$clll@H@@QAEHXZ
main.obj : error LNK2001: unresolved external symbol "public: void __thiscall CTest<int>::set(int)" (?set@?$clll@H@@QAEXH@Z
main.obj : error LNK2001: unresolved external symbol "public: __thiscall CTest<int>::CTest<int>(void)" (??0?$clll@H@@QAE@XZ
Debug/tt.exe : fatal error LNK1120: 4 unresolved externals
Error executing link.exe.
valarraycȝ?/span>
1. apply ?/span>valarray数组的每一个值都?/span>apply所接受到的函数q行计算
2. cshift ?/span>valarray数组的数据进行@环移动,参数为正者左UMؓ负就右移
3. max q回valarray数组的最大?/span>
4. min q回valarray数组的最?/span>
5. resize 重新讄valarray数组大小Qƈ对其q行初始?/span>
6. shift ?/span>valarray数组UdQ参Cؓ正者左U,者右U,Ud后由0填充剩余?/span>
7. size 得到数组的大?/span>
8. sum 数组求和
构造函?/span>
valarray( );
explicit valarray(size_t _Count);
valarray( const Type& _Val, size_t _Count);
valarray( const Type* _Ptr, size_t _Count);
valarray( const slice_array<Type>& _SliceArray);
valarray( const gslice_array<Type>& _GsliceArray);
valarray( const mask_array<Type>& _MaskArray);
valarray( const indirect_array<Type>& _IndArray);
slicecȝ?/span>
该类主要配合valarraycM用,可以?/span>valarray中提取子数组
slice( );
slice( size_t _StartIndex,//截取数组的开始位|?/span>
const valarray<size_t> _Len, //子数l的最大长?/span>
const valarray<size_t> _Stride//盔R多少个元素选中一?/span>
);
用法Q?/span>
int main( )
{
using namespace std;
int i;
valarray<int> va ( 20 ), vaResult;
for ( i = 0 ; i < 20 ; i+=1 )
va [ i ] = 2 * (i + 1 );
cout << "The operand valarray va is:\n( ";
for ( i = 0 ; i < 20 ; i++ )
cout << va [ i ] << " ";
cout << ")." << endl;
slice vaSlice ( 1 , 7 , 3 );
vaResult = va [ vaSlice ];
cout << "\nThe slice of valarray va is vaResult:"
<< "\nva[slice( 1, 7, 3)] = ( ";
for ( i = 0 ; i < 7 ; i++ )
cout << vaResult [ i ] << " ";
cout << ")." << endl;
}
输出l果Q?/span>
The operand valarray va is:
( 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 ).
The slice of valarray va is vaResult:
va[slice( 1, 7, 3)] = ( 4 10 16 22 28 34 40 ).
Gslicecȝ?/span>
Gslicecȝ用法?span>slice基本相同Q只是它截取的是循环子串Q当母串q行一ơ提取后的字串元素数目达不到要求Ӟgslice会将提取后的母串l箋l合q行提取直到满要求或者母串被提取完了
公共函数(Ҏ(gu)l的操作)
1.abs Ҏ(gu)l的每一个元素取l对?/span>
2.acos q回每个元素的反余u?/span>
3.asin q回每个元素的反正u?/span>
4.atan q回每个元素的正切?/span>
5.atan2 W卡正切?/span>
6.cos 余u?/span>
7.cosh 双曲U余弦?/span>
8.exp q回自然指数E^x
9.log q回自然Ҏ(gu)
10.log10 q回?span>10为底的返回自然对?/span>
11.exp q回x^y
12.sin 正u?/span>
13.sinh 双曲U正弦?/span>
14.sqrt 开?/span>
15.tan 正切?/span>
16.tanh 反正切?/span>
我们在衡量一个函数运行时_或者判断一个算法的旉效率Q或者在E序中我们需要一个定时器Q定时执行一个特定的操作Q比如在多媒体中Q比如在游戏中等Q都会用到时间函数。还比如我们通过记录函数或者算法开始和截至的时_然后利用两者之差得出函数或者算法的q行旉。编译器和操作系lؓ我们提供了很多时间函敎ͼq些旉函数的精度也是各不相同的Q所以,如果我们惛_到准的l果Q必M用合适的旉函数。现在我׃l?/span>windows下的几种常用旉函数?/span>
1Q?/span>Sleep函数
使用Q?/span>sleep(1000)Q在Windows?/span>Linux?/span>1000代表的含义ƈ不相同,Windows下的表示1000毫秒Q也是1U钟Q?/span>Linux下表C?/span>1000U,Linux下用毫U别的函数可以使用usleep?/span>
原理Q?/span>sleep函数是调用sleep函数的线E休眠,U程d攑ּ旉片。当l过指定的时间间隔后Q再启动U程Ql执行代码?/span>Sleep函数q不能v到定时的作用Q主要作用是延时。在一些多U程中可能会看到sleep(0);其主要目的是让出旉片?/span>
_ֺQ?/span>sleep函数的精度非怽Q当pȝ忙它精度也p低,有时候我们休?/span>1U,可能3U后才能l箋执行。它的精度取决于U程自n优先U、其他线E的优先U,以及U程的数量等因素?/span>
2Q?/span>MFC下的timer事g
使用Q?/span>1.调用函数SetTimer()讄定时间隔Q如SetTimer(0,100,NULL)即ؓ讄100毫秒的时间间隔;2.在应用程序中增加定时响应函数OnTimer()Qƈ在该函数中添加响应的处理语句Q用来完成时间到时的操作?/span>
原理Q同sleep函数一栗不同的?/span>timer是一个定时器Q可以指定回调函敎ͼ默认?/span>OnTimer()函数?/span>
_ֺQ?/span>timer事g的精度范围在毫米U别Q系l越忙其_ֺ也就差?/span>
3Q?/span>C语言下的Time
使用Q?/span>time_t t;time(&t);Time函数是获取当前时间?/span>
原理Q?/span>time函数主要用于获取当前旉Q比如我们做一个电(sh)子时钟程序,可以用此函数Q获取系l当前的旉?/span>
_ֺQ秒U别
4Q?/span>COM对象中的COleDateTimeQ?/span>COleDateTimeSpanc?/span>
使用Q?/span>COleDateTime start_time = COleDateTime::GetCurrentTime();
COleDateTimeSpan end_time = COleDateTime::GetCurrentTime()-start_time;
While(end_time.GetTotalSeconds() < 2)
{
// 处理延时或定时期间能处理其他的消?/span>
DoSomething()
end_time = COleDateTime::GetCurrentTime-start_time;
}
原理Q以上代表g?/span>2U,而这两秒内我们可以@环调?/span>DoSomething()Q从而实现在延时的时候我们也能够处理其他的函敎ͼ或者消息?/span>COleDateTime,COleDateTimeSpan?/span>MFC?/span>CTimeQ?/span>CTimeSpan?/span>COM中的应用Q所以,上面的方法对?/span>CTimeQ?/span>CTimeSpa同样有效?/span>
_ֺQ秒U别
5Q?/span>C语言下的旉周期clock()
使用Q?/span> clock_t start = clock();
Sleep(100);
clock_t end = clock();
double d = (double)(start - end) / CLOCKS_PER_SEC;
原理Q?/span>clock()是获取计机启动后的旉间隔?/span>
_ֺQ?/span>msU别Q对于短旉内的定时或者g时可以达?/span>msU别Q对于时间比较长的定时或者gq精度还是不够。在windows?/span>CLOCKS_PER_SEC?/span>1000?/span>
6Q?/span>Windows下的GetTickCount()
使用Q?/span> DWORD start = GetTickCount();
Sleep(100);
DWORD end = GetTickCount();
原理Q?/span>GetTickCount()是获取系l启动后的时间间隔。通过q入函数开始定Ӟ到退出函数结束定Ӟ从而可以判断出函数的执行时_q种旉也ƈ
非是函数或者算法的真实执行旉Q因为在函数和算法线E不可能一直占?/span>CPUQ对于所有判断执行时间的函数都是一P不过基本上已l很准确Q可以通过查询q行定时?/span>GetTickCount()?/span>Clock()函数是向LBIOS?/span>real time clock旉Q会有中断生,以及延迟问题?/span>
_ֺQ?/span>WindowsNT 3.5以及以后版本_ֺ?/span>10msQ它的时间精度比clock函数的要高,GetTickCount()常用于多媒体中?/span>
7Q?/span>Windows?/span>timeGetTime
使用Q需要包?/span>Mmsystem.hQ?/span>Windows.hQ加入静态库Winmm.lib.
timeBeginPeriod(1);
DWORD start = timeGetTime();
Sleep(100);
DWORD end = timeGetTime();
timeEndPeriod(1);
原理Q?/span>timeGetTime也时常用于多媒体定时器中Q可以通过查询q行定时。通过查询q行定时Q本w也会媄响定时器的定时精度?/span>
_ֺQ毫U,?/span>GetTickCount()相当。但是和GetTickCount相比Q?/span>timeGetTime可以通过timeBeginPeriodQ?/span>timeEndPeriod讄定时器的最解析精?/span>, timeBeginPeriod,timeEndPeriod必须成对出现?/span>
8Q?/span>windows下的timeSetEvent
使用Q还记的VC下的Timer吗?Timer是一个定时器Q而以上我们提到几U时间函数或者类型,实现定时功能只能通过轮训来实玎ͼ也就是必d外创Z个线E单独处理,q样会媄响定时精度,好在windows提供了内|的定时?/span>timeSetEventQ函数原型ؓ
MMRESULT timeSetEventQ?/span> UINT uDelay, //以毫U指定事件的周期
UINT uResolution, //以毫U指定g时的_ֺQ数D定时器事g分L率越高。缺省gؓ1ms
LPTIMECALLBACK lpTimeProc, //指向一个回调函?/span>
WORD dwUser, //存放用户提供的回调数?/span>
UINT fuEvent Q?/span>// 标志参数Q?/span>TIME_ONESHOTQ执行一ơ;TIME_PERIODICQ周期性执?/span>
具体应用Ӟ可以通过调用timeSetEvent()函数Q将需要周期性执行的d定义?/span> lpFunction回调函数?/span>(如:定时采样、控制等)Q从而完成所需处理的事件。需要注意的是:d处理的时间不能大于周期间隔时间。另外,在定
时器使用完毕后,应及时调?/span>timeKillEvent()之释放?/span>
原理Q可以理解ؓ代回调函数的timeGetTime
_ֺQ毫U,timeSetEvent可以通过timeBeginPeriodQ?/span>timeEndPeriod讄定时器的最解析精?/span>, timeBeginPeriod,timeEndPeriod必须成对出现?/span>
9Q高_ֺ时控函数QueryPerformanceFrequencyQ?/span>QueryPerformanceCounter
使用Q?/span>LARGE_INTEGER m_nFreq;
LARGE_INTEGER m_nBeginTime;
LARGE_INTEGER nEndTime;
QueryPerformanceFrequency(&m_nFreq); // 获取旉周期
QueryPerformanceCounter(&m_nBeginTime); // 获取旉计数
Sleep(100);
QueryPerformanceCounter(&nEndTime);
cout << (nEndTime.QuadPart-m_nBeginTime.QuadPart)*1000/m_nFreq.QuadPart << endl;
原理Q?/span>CPU上也有一个计数器Q以机器?/span>clock为单位,可以通过rdtscdQ而不用中断,因此其精度与pȝ旉相当?/span>
_ֺQ计机获取g支持Q精度比较高Q可以通过它判断其他时间函数的_ֺ范围?/span>
10结Q以上提到常用的9U时间函敎ͼ׃他们的用处不同,所以他们的_ֺ也不相同,所以如果简单的延时可以?/span>sleep函数Q稍微准的延时可以使用clock函数Q?/span>GetTickCount函数Q更高的实?/span>timeGetTime函数Q简单的定时事g可以?/span>TimerQ准地可以?/span>timeSetEventQ或取一般系l时间可以?/span>timeQ或?/span>CTimeQ或?/span>COleDateTimeQ获取准的旉可以?/span>clockQ或?/span>GetTickCount函数Q或?/span>timeGetTime函数Q而获取准地pȝ旉要用硬件支持的QueryPerformanceFrequency函数Q?/span>QueryPerformanceCounter函数?br>
CStopwatch.h