pascal之windows api简明教程未完成_第1页
pascal之windows api简明教程未完成_第2页
pascal之windows api简明教程未完成_第3页
pascal之windows api简明教程未完成_第4页
pascal之windows api简明教程未完成_第5页
已阅读5页,还剩60页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Pascal之Windows

API简明教程制作:ax_poklQQ:395838203不积跬步,无以至千里;不积小流,无以成江海。前言学习本教程之前请先精通英语和Pascal中有关单元库、类型、子程序、指针等内容,并且先初步了解关于计算机硬件组成原理、汇编语言、离散数学、高等代数、数字电路分析,电磁学,量子力学等计算机学基础知识。本教程为用Pascal写游戏和简单窗体程序的同学所写。本教程不涉及任何有关NOIP和算法有关的内容,所以也适合学过C语言的同学们观看。本教程编译器以fpc为准,学习教程之前请先学会熟练运用至少一款fpc的IDE(或者学会用磁铁操作硬盘)。由于本人对API的了解不是很深,仅给同学们API的一个大致印象。内容肤浅,水平极渣,错误颇多,敬请谅解。目录第一章Windows

API基本常识第二章Windows

API基础知识第三章Windows

API实例第一章Windows

API基本常识什么是程序?什么是动态链接库?如何使用动态链接库?如何编写动态链接库?什么是Windows

API?如何使用MSDN获取帮助?什么是程序?程序是语句的集合。语句是调用一段程序。主程序(program),unit(单元库),子程序(subrotine)——函数(function)和过程(procedure),甚至操作符(operator)都是程序。例如i:=i+1;可以写成:=(i,+(i,1));程序里可以包含很多程序。例如一个program里含有一个function和一个procedure。程序可以有一个返回值。什么是动态链接库?库是子程序的集合。通过声明单元库,可以调用单元库中的子程序,但这仅局限于Pascal语言和指定的编译器。链接库是编译好的子程序集合,用于不同语言之间子程序的互相调用,分为静态链接库(lib)和动态链接库(dll)。静态链接库被引用后,程序在编译链接时会把库中的代码直接拷贝到可执行文件(exe)中。动态链接库被引用后,程序在链接时不会拷贝代码。待程序执行时会寻找引用的动态链接库并载入内存。如何使用动态链接库?使用external和name关键字声明一个外部子程序:function

GetTickCount():longint;external

'kernel32.dll'

name

'GetTickCount';external关键字声明外部子程序的dll路径。name关键字申明外部子程序在dll中的名称。接着就可以使用这个外部子程序了:writeln(GetTickCount());如果找不到dll或者这个dll里没有这个子程序,程序执行的时候就会报错。子程序声明名称和外部子程序在dll种的名称可以不同。如何编写动态链接库?类似写一个程序,将program关键字改成library关键字:library

lib1;接着写子程序,注意申明调用约定:function

inc(i:longint):longint;stdcall;begin

inc:=i+1;end;所有子程序写完后,用exports关键字导出子程序:exports

inc;类似写一个单元库,如需在调用dll的时候初始化,则最后写一段begin

end.,否则直接以end.结束。编译后一个dll就生成了。如何编写动态链接库?类似于单元库,在没有接口(interface)的情况下,子程序即使有实现(implementation),别的程序也是不能使用这个子程序的。但是在单元库内部,这些写在implementation里的子程序是可以互相调用的。同样道理,没有导出(exports)的子程序在dll里也是找不到入口的。但是在dll内部则可以互相调用没有导出的子程序。所以,library更像是一个unit。关于程序的链接,可以看这个:什么是Windows

API?Windows

API(应用程序编程接口)是Windows操作系统中所有

dll的集合。在Windows操作系统中,除了fpc的132个内部子程序以外,所有的子程序最终都是通过调用Windows

API中的子程序来实现的,不妨用EXeScope软件查看一下你编译后程序用到过的dll。Windows

API的所有子程序都是stdcall的。绝大多数的Windows

API都已经在Windows单元库中定义好了,只需要uses

Windows即可使用。如果子程序名称有冲突,可以强制用Windows.子程序名();,例如Windows.sleep(20);和delay(20);其实是一样的。Windows单元库中定义的子程序请参阅附录func.inc。Windows

API大全请参阅附录。如何使用MSDN获取帮助?以GetSystemTime为例。通过搜索引擎找到该子程序的页面:当然,如果百度百科有翻译过的条目就再好不过了。页面中的function指的是子程序而不是函数,因为C++语言中的过程是有返回值VOID(空类型)的。大字后是关于子程序的解释。可以用谷歌翻译一下。Syntax一栏中有C++语言关于这个子程序的定义。VOID是子程序类型(这里是空类型,即子程序是过程);WINAPI是子程序的调用约定,即stdcall;;_In_代表参数是一个值参,_Out_则是变参即Pascal中的var参,_opt_是可选参数(可设为零)。大写的

LPSYSTEMTIME是参数的类型,LP说明是一个长指针类型,指向SYSTEMTIME的记录结构,lpSystemTime是参数名称。如何使用MSDN获取帮助?Parameters一栏是关于参数的具体解释,这里解释了

lpSystemTime是一个指向SYSTEMTIME结构体(struct,即

Pascal的record)的指针变量。点开SYSTEMTIME,可以看到这个结构体的定义。可以看到这是一个8个WORD组成的record。从变量名称也可以看出来是

WORD类型,因为都是w开头的。然后后面可以看到各种解释啊,包括C++中的栗子和使用方法(GetSystemTime和GetLocalTime子程序有用到)。ReturnValue一栏解释了返回值的用途。一般是void或者BOOL或者DWORD或者HANDLE之类的东西,例如GetTickCount返回的就是一个DWORD。如何使用MSDN获取帮助?Remark就是备注了,这里是说这个子程序在Windows

Phone

8上也支持-_-。(好吧,只玩PC的路过)Example就是具体的使用方法。好吧,因为子程序太简单都没有栗子了。可以参考这个SYSTEMTIME

structure的栗子:Requirement是使用这个子程序所需的条件,说到至少是

windows

2000系统以上才能用。然后这个子程序位于

Kernel32.dll。Seealso可以参考其它相关的子程序,例如想设置时间可以用

SetSystemTime。第二章Windows

API基础知识获取错误信息(GetLastError)句柄(Handle)指针记录(^record)指针字符数组(PChar)缓冲区(Buffer)设备上下文(Device

Contexts)Windows编程命名规则获取错误信息(GetLastError)有时候,一个Windows

API子程序并不一定返回的是错误码(可能是一个句柄)。如果执行一个子程序出错了,这时候需要知道错误出在哪,就得用上GetLastError();。任何时候都可以调用GetLastError();子程序获得调用的上一个Windows

API子程序的错误信息。由于Windows

API是外部子程序无法跟踪步入(属于系统领空),所以无法得知调用子程序时出了什么错误(具体哪个参数不对),于是调用GetLastError();获取错误信息就显得非常重要。错误代码请参阅附录。句柄(Handle)句柄是一种类型,相当于longword,用来标识系统中的一个对象。例如一个窗口,一个文件。简单来说,句柄就是一个数字标号。一个窗口(窗口类型的变量)可以有高度,宽度,标题文字等详细信息(属性,即记录中的成员类型),但这个窗口类型的变量通常是不可见的。传递句柄可以让Windows

API子程序知道调用的是哪个对象。例如:窗口句柄HWND只是一个数字,并不包含结构等详细的信息。但是如果知道了这个数字,就可以通过一些子程序如

GetWindowText();来获取窗口的标题文字等信息了。指针记录(^record)以下为照抄Windows单元库中struct.inc中的定义。typeSYSTEMTIME

=

recordwYear

:

WORD; wMonth

:

WORD;wDayOfWeek

:

WORD;

wDay

:

WORD;wMinute

:

WORD;wMilliseconds

:

WORD;wHour

:

WORD;wSecond

:

WORD;end;LPSYSTEMTIME

=

^SYSTEMTIME;PSYSTEMTIME

=^SYSTEMTIME;_SYSTEMTIME

=

SYSTEMTIME;TSYSTEMTIME=

SYSTEMTIME;指针记录(^record)指针记录类型的参数是Windows

API中极为常用的东西。Windows

API的返回值通常只是用来标识子程序调用的错误代码的。如果需要返回一些数据,则需要用到指针记录变量。GetSystemTime(lpSystemTime:LPSYSTEMTIME);中的

LPSYSTEMTIME就是一个指针记录类型,lpSystemTime就是一个指针记录类型的参数。这个LPSYSTEMTIME类型是一个指向

SYSTEMTIME类型的指针类型,而SYSTEMTIME类型则是一个记录类型。在使用这个子程序之前先定义一个LPSYSTEMTIME类型的变量,例如var

st:LPSYSTEMTIME;然后再调用这个子程序。此时st所指向的记录已发生改变,通过writeln(st^.wHour);就可输出当前时钟小时数。(C++语言中,->即^.相当于取类型的成员对象)指针字符数组(PChar)PChar是Windows

API中最常见的字符串类型,它是一个指向一段内存(字符数组)的指针变量,即^Char。在内存中,PChar所指向的内存单元存储第一个字符数据,之后的每一个字节存储后面的字符,最后以#0结束。String和PChar不同。String虽然也是指针,但指向的内存单元(字节)存储整个String的长度,随后的n个字节存储String的字符数据,因此String的长度最多是255字节。将一个String转为PChar,可以先将#0添加到String末尾,然后再将PChar指向String的第一个字符,实现如下:var

s:

String;

pc:

PChar;

s

:=

s

+

#0;

pc

:=

@s[1];一个PChar可以隐式的转为String,即:s:=pc;Windows

API文献(C++)中,PChar又叫做LPCSTR,只要

Uses

Windows一下就都可以用了。缓冲区(Buffer)缓冲区是Windows

API返回大量数据时存放数据的地方。一般来说缓冲区定义成一个定长字节数组array

of

byte[]或者一个字符串PChar,例如var

buf:array[1..256]of

byte;然后调用某个API的时候,将这个buf变量和长度n传递进去,API就会修改这个buf。接着你就可以得到API返回的信息了,例如你可以writeln(buf[1]);。如果缓存区是一个指针,使用前可能需要清空内存,可以用freemem(buf,sizeof(buf));来完成这个动作。注意传递进去的是指针还是变量,如果是变量,可能要用@buf或者pointer(buf)。一般来说API只接受指针变量,因为API参数长度是固定的。设备上下文(Device

Contexts)Windows编程命名规则常量c_静态s_句柄h无符号u短整n计数c双精d双字dw字符ch无效vWindows编程使用使用匈牙利命名

属性:法。

全局g_类型和常量使用全大写的形式。

成员m_函数名单词名称之间无符号,单词

类型:为首字母大写剩余部分小写。

指针p变量名如同函数名,但需要在开头

整型I增加属性,类型和描述前缀。长整l即变量名=属性+类型+描述+名称。布尔b描述:单精f字w字串sz函数fn最大Max初始化Init源对象Src最小Min临时Temp目的对象Dest第三章Windows

API实例第一节简单API第二节文件API第三节窗口API第四节内存API第五节管道API第六节网络API第一节简单APISleep();Sound();timeGetTime();mouse_event();mciSendString();CreateThread();Sleep();延迟一段时间,以毫秒为单位。usesWindows;后就可以使用了。效果和CRT单元库中的Delay();一样。参数类型是longword。可以用Windows.Sleep();以免混淆重载的Sleep();。Sound();在一段时间内发出一个固定频率的声响。这个子程序有两个参数都是longword类型。前一个参数是频率,后一个参数是延迟时间。如同Sleep();,这个子程序直到声音停止后才会返回。CRT单元库中的Beep();子程序是用Sound();实现的。注意频率的取值范围,过高或过低可能会导致延迟时间不正确。timeGetTime();获取开机到现在时间,以毫秒计。这是一个外部子程序,必须先声明才能使用:function

timeGetTime():longword;external

'winmm.dll';注意子程序的调用约定。这个子程序属于Windows多媒体API的一部分,所以返回的值较为精确。可以使用GetTickCount();子程序替代。该子程序返回较快,但是精度不如timeGetTime();高。GetTickCount();是randomize();子程序的一部分(RandSeed:=GetTickCount();)。mouse_event();模拟鼠标动作。该子程序没有返回值。参数较多,有dwFlags,dx,dy,dwData,dwExtraInfo。除了dwExtraInfo为指针外,其余四个为longword。dwFlags为动作类型,dx、dy为移动的距离,dwData为滚轮滚动距离,dwExtraInfo为返回的附加信息,一般设为nil即可。dwFlags可直接使用Windows单元库预设好的值,例如MOUSEEVENTF_ABSOLUTE、

MOUSEEVENTF_LEFTDOWN等,具体参看MSDN。mciSendString();winmm.dll中的子程序,用以给MCI发送一条指令。lpszCommand,lpszReturnString,cchReturn,hwndCallback,分别为发送的指令、返回的指令、返回指令的长度、回调子程序的入口句柄。指令都为PChar类型,返回值为MCIERROR类型。回调子程序入口句柄可设为0。鉴于处理PChar比较麻烦,返回的指令可用字符数组接收后再转换成String,具体参见第二章相关内容。可用mciExecute();替代,仅一个参数pszCommand。MCI指令可参考这个:(v=vs.85).aspxCreateThread();用以创建一个线程,返回值为线程句柄。线程营造了“多个子程序在同时运行”的假象,本质上并不能加快程序的运行速度。子程序的同时运行会引发很多问题,同时访问同一个

内存单元会发生错误,所以不能同时给一个变量赋值。因此在没有必要使用的时候不要使用多线程。例如使用Sound(1000,5000);发出一个1000Hz的5秒的声音,在声音停止之前程序是不会继续执行下去的。如果想在Sound();的时候同时readln();,那么可以建立一个Sound();的线程,这样子程序会立刻返回(主程序)。CreateThread();参数较多,比较重要的有两个,其余可以用nil或0替代。lpStartAddress为子程序入口地址,为指针类型。例如用@Sound或者pointer(Sound)代表Sound();子程序。lpParameter为传递给子程序的参数,为指针类型。由于传递的参数只有一个,所以当子程序的参数多余一个(Sound(hz,t:longword);)时,可以定义一个记录类型(TSound=record

hz,t:longword;end;),然后重载一个同名的子程序(Sound(para:^TSound);),并在这个重载的子程序中调用(Sound(para^.hz,para^.t);)。第二节文件APICreateFile();ReadFile();GetFileSize();GetFileInformationByHandle();CreateFile();该子程序不仅限于创建文件,还可用于打开文件,设置文件访问权限,设置文件属性等操作。文件的定义不仅限于磁盘文件,还包括控制台,输入输出流,目录,磁盘驱动器,管道等。事实上,文件是一个具有特定结构的对象。子程序有7个参数。lpFileName为文件名称,

dwDesiredAccess为文件的访问权限(是否可读可

写),dwShareMode为共享模式(允许别的程序读写文件),dwCreationDisposition为创建并文件打开方式(是否清除原内容)。操作成功后则返回文件句柄。ReadFile();正如其名,该子程序用来读取文件内容。我们一般读取一个类型文件(例如fileofbyte)时都是一个byte一个byte读的,这样会导致读取十分缓慢。

ReadFile();就给了我们一个快速读取文件内容的办法。首先你需要一个缓冲区用以存放数据。用CreateFile();打开文件以后,使用返回的文件句柄就可以将文件内容读到缓冲区里了。文件读取分为同步和异步两种方式。如果文件是管道或者I/O,那么同步读取时可能会卡住直到有数据输入到管道或是I/O里。ReadFile();五个参数分别为:HANDLEhFile文件句柄,

LPVOIDlpBuffer缓冲区指针,

DWORDnNumberOfBytesToRead写入缓冲区的字节数,

LPDWORDlpNumberOfBytesRead剩余的字节数,

LPOVERLAPPEDlpOverlapped同步或异步标识。写到缓冲区是需要时间的。异步模式下读完就会返回,于是LPDWORDlpNumberOfBytesRead(var参)会显示还没读取的剩余字节数。返回值为布尔类型。如果需要写入缓冲区的字节超过了文件剩余大小(读到文件尾),那么GestLastError();不会是零。GetFileSize();获取文件大小(字节为单位)。第一个参数为文件句柄,返回值为文件大小。如果文件大小超过4G,那么使用第二个参数(var参)来获取高位双字的文件大小,否则设为nil即可。(这个子程序额外的简单)GetFileInformationByHandle();有时候我们不满足于只获取文件大小,我们还想知道文件属性,修改时间等其它信息。没关系,这个子程序就能满足你。你以为参数会很多?这个子程序只有两个参数,而且返回值只是个布尔类型(用以标记是否调用成功)。如同GetFilesize();,第一个参数是文件句柄。第二个参数是一个BY_HANDLE_FILE_INFORMATION记录类型指针类型的var参。类型具体成员变量的用途MSDN里讲了。时间类型FILETIME是两个DWORD组成的记录,标识1601年1月1日到现在100ns时间单位数量。还有一种常用时间类型称为

SYSTEMTIME,这种就是用年月日星期时分秒毫秒记的。两种类型可以用FileTimeToSystemTime();和SystemTimeToFileTime();子程序转换,具体用法参看MSDN吧。第三节窗口APICreateWindow();正如其名,窗口是Windows操作系统中最重要的东西。有了窗口,我们就可以同时运行并操控多个程序。窗口的产生标识着操作系统从单线程到多线程的转变。要创建窗口,我们必须用RegisterClass();子程序在系统中注册一个窗口对象。注册的时候,我们必须提供窗口名、进程句柄、画笔颜色、光标类型、程序缩略图以及回调子程序等信息,这个过程就如同在网站上注册一个帐号一样。注册窗口以后,我们就可以创建窗口了。为了让系统知道创建的是哪个窗口,我们必须提

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论