开发资源库delphi版帮助语法基础_第1页
开发资源库delphi版帮助语法基础_第2页
开发资源库delphi版帮助语法基础_第3页
开发资源库delphi版帮助语法基础_第4页
开发资源库delphi版帮助语法基础_第5页
已阅读5页,还剩55页未读 继续免费阅读

下载本文档

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

文档简介

在Pascal中,注释括在大括号中或带星号的圆括号中。Delphi也认可C++风格的注释,把注释放在双斜线后。例{thisisa(*thisisanothercomment//thisisacommentuptotheendofthe第一种注释方式较简略,使用也较为普遍;第二种方式在欧洲使用较广,因为欧洲的C+32位版本的Delphi中可用,它在给一行代码加短注释时非常有用。{...{comment,creating...code{...//thiscommentis...code{$X+}。Pascal编译器(不象其他语言的编译器)不考虑字符的大小写,因此标识符MynameMyNamemyname、myNameMYNAME是完全相同的。总体上来说,这是然而大小写不敏感也有不便之处:第一,你必须注意大小写不一致的标识符实际上是相同大写使用的一致性不是编译器强制要求的,但是保持大写使用的一致性是值得提倡的好习此外,编译器不编译代码中的空格、空行和Tab键空格,这些元素通称为空白,它们只用1不同于BASIC,Pascal允许语句分行的缺点(至少对许多BASIC程序员不同于BASIC,Pascal允许语句分行的缺点(至少对许多BASIC程序员)是:语句结束时不能忘了加分号,更确切地Delphi代码编辑器中有一条竖线叫右边线(RightMargin),你可以把右边线设置在或70个字符处。如果以这条线为基准,代码不超过这条界限,那么打印到纸上的代码关于代码编写风格的最后一条建议是:尽量使用空白优化版面。这一条很容易做到if...if...if...if...Letters=setofName:{longcommentandlongstatement,goingoninthefollowinglineandindentedtwospaces}MessageDlg('Thisisa2mtInformation,[mbOk],关键字是ObjectPascalmtInformation,[mbOk],关键字是ObjectPascal2.1是面向对象Pascal言(Delphi4)中特殊标识符的完整列表,其中包括关键字及表2.1:面向对象语言中的关键字及保留3指令(变量指令(方法运算符(布运算符向后汇语句(异常访问类别符运算符(集指令(属性dispinterface界面类别语句(4指令(方法语句if或语句(异常向后类指令(函数向后类语句(异常4指令(方法语句if或语句(异常向后类指令(函数向后类语句(异常指令(属性运算符(集合)-工程结指令(dipinterface界面向后兼容(见运算符指令(方法运算符(数指令(函数向后类指令(属性运算符(布5向后类语句语句(异常运算符(布指令(参数程序结构(控件包指令(记录访问类别符访问类5向后类语句语句(异常运算符(布指令(参数程序结构(控件包指令(记录访问类别符访问类别符访问类别符访问类别符语句(异常dispatch界面类别程序结构(控件包指令(函数运算符(数运算符(数指令(属性建立表达式没有通用的方法,因为要取决于所用的运算符,Pascal包括有逻辑运算符、算建立表达式没有通用的方法,因为要取决于所用的运算符,Pascal包括有逻辑运算符、算而不是标识符本身进行运算。如果你以前写过程序,那么你已经知道表达式是什么了。这里我专门讲一下Pascal 运算符的特殊部分:运算符的优先级。表2.2中按优先级分组列出了Pascal语言的运算符。 可以计算两个数字的和连接两个字符串、求两个集合的并集、甚至给PChar指针加一个偏移量。然而,你不能象在另一个特殊的运算符是divPascal中,你能用/计算两个数字(实数或整数)的商,而且你总能得到一个实型结果。如果计算两个整数的商并想要一个整型结果,那么就需要用div6与大多数编程语言相反,Pascal语言中and和or运算符的优先级比关系运算符高。因此,如果你的代码为a<bandc<d,编译器首先会编译and运算符,由此导致编译出错。为此你应该把每个<表达式用小括号括起来:(a<b)and(c<d)。语句(语句(语句(异常指令(方法dispatch界面类别运算符(布表2.2:Pascal语言中的运算符及其优7单目运算符(最高优先级@*/取模(整数相除的余数表2.2:Pascal语言中的运算符及其优7单目运算符(最高优先级@*/取模(整数相除的余数程序运行阶段类型转换(RTTI运算符+-=<>判断对象是否类型兼容(又一个RTTI运算一个元素添加到集合中,你可以采用集合并运算。下面是一个选择字体的Style:=Style+一个元素添加到集合中,你可以采用集合并运算。下面是一个选择字体的Style:=Style+Style:=Style+[fsBold,fsItalic]-另一种方法是利用标准过程类型属性,因为只能操纵一个元素Include(Style,和Exclude,它们效率更高(Value:Integer;A,B:Char;关键字var可以在许多地方使用,例如放在函数或过程的开始部分,用来声明函数或过程的局部变量;也可以放在单元中,用于声明全程变量。var关键字之后是一组变量名列表,每个变量一旦变量的类型被指定,你只能对变量执行该变量类型支持的操作。例如,在判断操作中用布尔值,在数字表达式中用整型值,你不能将布尔值和整型值混用(在C语言中可以这样)。Value:=10;Value:=IsCorrect;//在DelpiIcmpatetypes:'Integer'and‘ee的值赋给一个整型变量没有什么意义。你不该责怪DelpiDelpi当然要提出警告。在Value:Integer=10;Correct:Boolean=True;8对于在程序运行期间保持不变的值Thousand=对于在程序运行期间保持不变的值Thousand=Pi=AuthorName='MarcoDelphi根据常量的值来决定它的数据类型。上例中的Thousand变量,Delphi会选用Thousand:Integer=AuthorName='Marco从Delphi3开始,你可以用另一种方式写AuthorName='Marco者的实现过程却不同,用resourtrigResStr你可了解资源串的实际作用,例子中设置了一个按钮,相应代码如下:rrsrgAuthorName='MarcoCantù';BookName='EssentialprocedureTForm1.Button1Click(Sender:ShowMessage(BookName+#13+以上代码中的两个字符串将分两行输出显示,因为字符串被分行 意味着字符串并没有进入编译代码,而是保存在执行文件(EXE文件)的一个单独区域。9注意:16位的Delphi允许你在程序运行期间改变已定义的常量值,就象一个变量一样。32位的Delphi为了向后兼容仍容许这种操作,只要你附加$J编译指令,或选择工程选项对话框中Compiler(编译器)页的Assignabletypedconstants复选框就行。 中有多种预定义的数据类型,它们可分为三大类: 中有多种预定义的数据类型,它们可分为三大类:有序数据类型,实数类型和字Delphi还包括一种无类型的可变数据类型,称作variant,variant无需类型检测的数据类型,它在Delphi2中引入,用于处理OLEAutomation(OLE自动化)。有序类型是建立在概念“顺序”或“序列”基础上的数据类型。你不仅可比较两个有序值的小,而且可以求取给定有序值的前驱及后继,或者计算它们的最大或最小值三种最重要的(Itgr,Boola,hr根据其内部表示和取值范围不同又可进一步细.1列出了表示数字的有序数据类型。表3.1:表示数字的有序数据类从表中可看到,不同数据类型与不同的数据表示法相对应,这要取决于数据值的数位和中说明了每种类型的实际取值范围表中最后一组类型标志着16/32,它表明其数值表示方法在16位和32位Delphi中不同,该组的Integer及Cardinal类型比较常用,因为它们与CPU内部的数字表示法相对应。布尔值不同于布尔类型,平时很少用到。ByteBoolWordBool和LongBool三种布尔类型的布尔值比较特殊,只在WindowsAPI函数中才用到它们。在Delphi3中,为了与VisualBasic和OLEAutomation修改ByteBool、WordBoolLongBoolTRUE1,FALSE值仍0;Boolean大 有符号值 无符号值8-128to0to16-32768to0to32-2,147,483,648toLongWordDelphi4)0to4,294,967,2956416/32注意:简而言之,采用资源的好处一方面可让Windows来完成有效的内存处理,另一方面不用更改源代码就可实现程序的本地化(把字符串翻译成不同的语言)。尔值保持不变(TRUE为1,FALSE为0)。如果在Delphi2代码中使用了布尔值显式类型转换,那么在以后的Delphi中可能会出错。字符有两种不同的尔值保持不变(TRUE为1,FALSE为0)。如果在Delphi2代码中使用了布尔值显式类型转换,那么在以后的Delphi中可能会出错。字符有两种不同的ANSIChar和WideChar。第一种类型代表8位的字符,Windows一直沿用的ANSI(美国国家标准协会)字符集相应;第二种类型代表16位的字符,与WindowsNT、Windows9598持的双字节字符(Unicode)相Delphi3中,Char类型字符与ANSIChar一致。切记,不管在什么环境,前256个Unicode字符与ANSI常量字符可用代表它们的符号表示,如‘k’也可用数字符号表示,如#78。后者还可用函数表示为Chr(78),用Ord函数可作相反的转换Ord(k)#9跳格(Tab键)#10#13回车(EnterPascal语言和DelphiSystem单元中定义了一系列有序类型操作例程,见表3.2。程序员会注意Inc例程,它可与++和+=运算符对应(Dec例程也同样)表3.2:有序类型系统例,设定浮点类型,占8个字节;Extended浮点类型,占10例 作将例程中的参数值递减1将例程中的参数值增加1或一个特定的值与IEEE(电气和电子工程师协会)标与IEEE(电气和电子工程师协会)标准的浮点数表示法一致,并且CPU数字协处理器直接Real类型在Delphi2和Delphi3中的定义与16位版本一样,都占6个字节。不过Borland公司一直不提倡使用这种类型,而建议Single、Double、Extended类型代替。这是由于Real这种6字节的旧格式既不受IntelCPU的支持,又没有列IEEE实型中。为了完全解决这一问题,Delphi4不得不修改Real类型的定义,将其改成标准的8字节了兼容性问题,不过如果有必要,你可以采用下面编译指令克服兼容性问题,恢复Delphi2和Delphi3的Real类型定义:另外还有两种奇怪的数据类型:Comp类型Currency类型,Comp8字节描述非常大的整数(这种类型可支持带有18位小数的数字);Currency类型16位版的一样也占8个字节。正如名字所示,Currency数据类型是为了操作很精确的四位小数货币数对实型数据,我们没办法编一个类似Range的程序,因为igh、Low及Ord函数不能因此,如Char类型字符w的顺序位置是有意义的,但同样的问题对浮点类型探究给定的实数前到底有多少个实型数(这是函数的作用),实型类型在用户界面编程中用得不多,但是Delphi从各方面支持实型类型,包括在数据库方面的支持。由于支持IEEE浮点数运算标准,ObjectPascal语言完全适合于各类数值计算编程。如果对这部分感兴趣,你可以参Delphi在System中提供的算术函数(详细DelphiDelphi也用实型数表示日期和时间数据。但为了更准确起见,Delphi特别定义TDateTime数据类型,这是一个浮点类型,因为这个类型必须足够宽,使变量能容纳年、月、日、时、分和秒、甚至毫秒。日期值按天计数1899-12-30开始,放在TDateTime类型的整TDateTime不是编译器可直接识别的预定义类型,它在System单元定义:注意:Delphi带有一个Math(如ArcCosh函数、金融函数(InterestPayment函数)和统计函数(MeanAndStdDev过程)MomentSkewKurtosis例程,它是作什么用的呢?还注意3,你能确定23后面的数是什么,因为整型数是有限的,它们有确定的值域范围及排列顺序。而浮点数即使在一个很小的值域范围内也无23和24哪个值是2.6后面的值?34723.461,或者23.4601TDateTime=type表3.3:TDateTime类型系统例TDateTime=type表3.3:TDateTime类型系统例正如所知,你不能把一个变量赋给另一个不同类型的变量,如果你需要这么做,有两种方供选择。第一种方法是采用类型映射(ypastng),它使用一个带有目标数据类型名的函数符号:C:Char;B:N:=Integer例 作FormatDateTime函数将TDateTime值的日期部分转为字符串将TDateTime值的时间部分转为字符串将带有日期和时间信息的字符串转换为TdateTime类型值,如串有误将引将带有日期信息的字符串转换为TDateTime类型格式将带有时间信息的字符串转换为TDateTime类型格式组合年、月、日值为TDateTime类型值组合时、分、秒、毫秒值为TDateTime类型值C:=CharB:=BooleanC:=CharB:=Boolean第二种方法是使用类型转换例程。表3.4中总结了各种类型转换例程。注意表中没有包括特殊类型(如TDateTime和variant)的转换例程,也没包括用于格式化处理的特殊例程,如Format和FormatFloat例程。表3.4:类型转换系统例例 作将一个有序数据转换为一个ANSI字符将字符串转换为一个数字(传统TurboPascal例程用于向后兼容将数字转换为格式化字符串(传统TurboPascal例程用于向后兼容将零终止字符串转换为Pascal类型字符串,在32位Delphi中这种类型转换Pascal类型字符串到一个零终止字符32位Delphi种类拷贝Pascal语言的一个重要特征是它能自定义语言的一个重要特征是它能自定义数据类型。通过各种类型构造器,你可以定义己的数据类型,如子界类型、数组类型、记录类型、枚举类型、指针类型和集合类型。最要的用户定义数据类型是类(class),类是ObjectPascal面向对象扩展部分必须将代码放在特定的type区,如下所示://subrangeUppercase=//arrayTemperatures=array[1..24]ofDate=recordMonth:Byte;Day:Byte;//enumeratedtypeColors=(Red,Yellow,Green,Cyan,Blue,//setLetters=setofDecemberTemperature:array[1..31]ofByte;ColorCode:array[Red..Violet]ofWord;Palette:setofColors;将一个Pascal字符串转换为浮点数注意:在最近版本的DelphiPascal编译器中,Round函数是以CPU的FPU点部件基础的。这种处理器采用了所谓的"银行家舍入法",即对中5.5、6.5)实施Round函数时,处理器根据小数点前数字的奇、偶性来确定舍入与否,如5.5Round结果为6,而6.5Round结果也为6,因为6是偶数。子界类子界子界类子界类型定义了某种类型的取值范围(因此定 subrange)。你可定义整数类型的子界型,如取值从1到10或从100到1000,或者定义字符类型的子界类型,如下所示Ten=Uppercase='A'..'Z';如定义一个子界变量,那么赋给该变量的值必须是子界定义范围内的值。下面代码是正UppLetter:UppLetter:=UppLetter:UppLetter:='e';//compile-time以上代码将导致一个编译错误:ntntpressionviolatesseonds。UppLetter:Uppercase;Letter:Char;Letter:='e';Delphi编译会通过,但在运行时,如果你开启了范围检查编译选项(在工程选项对话框的编译器页设置),你将得到Rangecheckerror(范围检测错误)信息。用于声名同一类型的其他变量。实际上,Pascal的类型兼容规则是基于类型名的,而不是基于实Colors=Colors=(Red,Yellow,Green,Cyan,Blue,Violet);Suit=(Club,Diamond,Heart,Spade);序列中每个值都对应一个序号,序号从0Ord函数,即可得到一个枚举类型值的序号。例如,Ord(Diamond)返回值1。多,一般为枚举类型或子界类型。如果子界类型取值为1..3,那么基于它的集合类型值可以是1、或2、或3、或1和2、或1和3、或2和3、或取所有3个数、或一个数也没有。Letters=setofvLetters1,Letters2,Letters3:Letters1:=['A','B',Letters3:=[];在Delphi中,集合一般用于表示有多种选择的标记。例如下面两行代码(摘自Delphi库)TBorderIcon=(biSystemMenu,biMinimize,biMaximize,biHelp);TBorderIcons=setofTBorderIcon;实际上,给定的窗口中可以没有图标,也可以有一个或多个图标。用ObjectInspector设置时(见图4.3),双击属性名,或单击属性左边的加号,自行选择,从而添加或删除集合中的值值,则16位表示法。还有32位表示C、C++库兼容时会用到。使用$Z编图4.3:Object图4.3:ObjectInspector中的集合类型属Font.Style:=[];//noFont.Style:=[fsBold];//boldstyleFont.Style:=[fsBold,fsItalic];//two或更准):Font.Style:=OldStyle+[fsUnderline];//two数组类型定义了一组指定类型的元素序列,在方括号中填入下标值就可访问数组中的元素。义数组时,方括号也用来指定可能的下标值。例如,下面的代码中定义了一个有24整数的数DayTemperatures=array[1..24]of在数组定义时,你需要在方括号中填入一个子界类型的值,或者用两个有序类型的常量定义CC++、AVA由于数组下标基于子界类型,因Delphi能够对它们进行范围检查。不合法的常量子界类型使用上述数组定义方法,定义一个DayTemperaturesDayTemperatures=array[1..24]ofprocedureDayTemp1[1]:=DayTemp1DayTemp1[1]:=DayTemp1[2]:=DayTemp1[24]:=DayTemp1[25]:=67;//compile-timeMonthTemps=array[1..24,1..31]ofInteger;YearTemps=array[1..24,1..31,Jan..Dec]ofInteger;MonthTemps=array[1..31]ofDayTemperatures;YearTemps=array[Jan..Dec]ofMonthTemps;ThisYear[Feb]:=你也能定义下标从零开始的数组,不过这似乎不太合逻辑,因为你需要用下标2来访问数,Windos(因为它是基于C语言的并且Delpi控使用数组时,你总要用标准函Low和High来检测它的边界,Low和High返回下标的下界和上界。强烈建议使用Low和High操作数组,特别是在循环中,因为这样能使代码与数组范围无关,如果你改变数组下标的范围声明,Low和High代码不会受影响;否则,如果代码中有一个数组下标循环体,那么当数组大小改变时你就不得不更新循环体的代码。Low和HighDelphi主要以数组属性的形式使用数组。注意:Delphi4的ObjectPascal中增加了动态数组,所谓动态数组是在运行时动态分配内存注意:顺便提一下,使用Low和High不会增加系统运行额外开销。因为在编译时,他们已被Date=recordMonth:Date=recordMonth:Byte;Day:Byte;BirthDay.Year:=BirthDay.Month:=BirthDay.Day:=API中定义了许多记录类型。记录类型中允许包含variant域,它表示多个域能公用同一内存区,而且域可以是不这相应于C语言中的联合unionrint中同一个内存位置,但是各个值仍需区别对待。arant类型主要用来存贮相似但又不同的数typcating(自从typcting引入Paca到这种方法了。虽然Dphiarantvariant指针是存放指定类型(或未定义类型)变量内存地址的变量,因此指针间接引用一个值定义指针不需用特定的关键字,而用一个特殊字符,这个特殊字符是脱字符号(^),见下例PointerToInt=X:Integer;P:=//changethevalueintwodifferentX:=P^:=如果定义了一个指针P,那么P表示指针所指向的内存地址,而P^表示内存所存储的实际内容。因此,在上面的代码中,P^与X相等。除了表示除了表示已分配内存的地址外,指针还能通过 例程在堆中动态分配内存,不过当你需要这个指针时,你也必须调用 例程释放你动态分配的内存P://New//P^:=ShowMessage(IntToStr//Dispose如果指针没有值,你可以把nil赋给它。这样,你可以通过检查指针是否为nil判断指针当FP:=ShowMessage(IntToStr(P^));通过运行例GPF,或者看 4.4nil针引起的系统错将上面程序加以修改,访问数据就安全了。现在将一个已存在的局procedureTFormGPF.BtnSafeClick(Sender:P:X:P:=P:X:P:=X:=ifP<>nilShowMessage(IntToStr如果你使用无类型指针,你应该用GetMem例程New例程,因GetMem例程能实际上Delphi对象模型,理解指针是很重要的,因为Delphi对象模型在幕后使另一个Pascal(file)Pascal语言的一个特殊类型。按下面的方式,你可以定义一个新的数据类IntFile=fileofPascal文件类型的使用很直观,而且Delphi一些控件用于文件保存和装载,X:=Y+Z;// //procedure用begin和end将简单语句括起来即组成复复合语句用法Pascal语句A:=C:=A*end注意Dphi(rfrncs。每A:=CA:=C:=A*这两种写法都是正确的。第一种多了一个无用(但也无害)语句,也就是说,是一个没有代码的语句。有时,空语句可用在循环体或其他特殊情况中。在Pascal语言中赋值语句用冒号-等号操作符:=对使用其他语言的编程人员来说这是个奇怪的符号。在其他语言中用作赋值符号的“=”在Pascal中用作关系运算符,用于判断是否条件语句通过条件检测,判断是否执行该条件语句中包含的语句。条件语句可有两种基形式:if语句和case语句。If对i-then仅当条件满足时,语句才执i-then-lseif语句在两条语句中选择一条执行。条件用布尔表达式建立,这里通过一个简单的Dlphi例子来示范如何写条件fom上面放两个复(kbx)和四个按(butt),不要改变复选框和按钮的名字,双击按钮为其OnClick事件添加响应程序。下面是第一个按钮事件代码中一条简单的if语句:procedureTForm1.Button1Click(Sender://simpleififCheckBox1.CheckedShowMessage('CheckBox1is当点击button1,如果第一个复选框中有复选标记,那么这个程序将显示一条消息(见图5.1)。我用了ShowMessage函数,因为它是Delphi中最简单的短信息显示函数。图5.1:例IfTest示注意Pascal编译器(象C编译器一样)能更快解译源代此在第二个按钮的代码中,我用了if-then-else语句:procedureTForm1.Button2Click(Sender://if-then-elseifCheckBox2.CheckedShowMessage('CheckBox2isShowMessage('CheckBox2isNOT要注意的是,不能在第一句之后、if以很复杂,句子中的条件部分可以是一系列条件(and、ornot等布尔操作符联接起来),if句又可以嵌套另一ifIfTest它两个按钮的示范代码:procedureTForm1.Button3Click(Sender:TObject);//statementwithadoubleifCheckBox1.CheckedandCheckBox2.CheckedShowMessage('BothcheckboxesareprocedureTForm1.Button4Click(Sender:ifCheckBox1.CheckedifCheckBox2.CheckedShowMessage('CheckBox1and2areShowMessage('OnlyShowMessage('OnlyCheckBox1is'Checkbox1isnotchecked,whocaresforCase如果你的if语句变得非常复杂,有时可以用case语句代替它。case语句包括用来选值的达式、可能值序列或一个取值范围。这些值应该是常量,并且它们必须唯一,而且应属于有序类ase语句最后可以带一个lse语句,当没有一个标签与选择器的值一致时,执行lse语句。下面是两个简单的例子:caseNumber1:Text:=2:Text:=3:Text:=caseMyChar'+':Text:='Plus'-':Text:='Minus'*','/':Text:='Multiplicationordivision';'0'..'9':Text:='Number';'a'..'z':Text:='Lowercase'A'..'Z':Text:='UppercaseText:='UnknownPascal语for、while和repeat句。如果你用过其他编程语言,你会发现Pascal中的循环语句没什么特别的,因此这里只作简要ForPascal中的for循环严格地建立在计数器基础上,循环每执行一次,计数器不是增加一值就是减小一个值。下面是一个for语句的简例,用来将前十个数加起来K,I:K:=K,I:K:=forI:=1to10K:=K+同样的for语句可以用正好相反的计数器来写:K,I:K:=forI:=10downto1K:=K+Pascal中的for循环语句其灵活性比其他语言小(它不能指定1的步长),不过简单也容易理解。如果需判断的条件比较复杂,或想自定义计数器,你可以while语句repeat语句,而不是for循环语句。whilerepeatwhile-do循环语句和repeat-untilwhile(I<=100)and(J<=100)do//useIandJtocomputeI:=I+1;J:=J+//useIandJtocomputeI:=I+1;J:=J+until(I>100)or(J>从上可见即使I或J的初始值大于100,repeat-until循环中的代码也仍会执行一注意:两种循环另一个关键的不同点是,repeat-until循环的条件是反向的条件,只要不满足这注意:for循环计数器不必非是数字,它可以是任何有序类型的值,例如一个字符或一个枚举类型为了探究循环的细节,让我们看一个Delphi简例,这为了探究循环的细节,让我们看一个Delphi简例,这个循环随机计数器循环之间的差别。建一个新的工程,在主窗体上放一个istbox和两个button,通过设置ObjectIpector中的me属性分别命名buttnre。你还可以&后面把Caption性中的Btn去掉,或甚至加上objectForm1:TForm1Caption='Loops'objectListBox1:TListBoxobjectBtnFor:TButtonCaption='&For'OnClick=objectBtnWhile:TButtonCaption='&While'OnClick=5.2For钮后显示的结现在,我们分别给两个button添加OnClick事件代码。第一个button用一个简单的for循环来显示一列数字,结果如图5.2。这个循环向listbox中的Items属性添加一系列字符串。在执行循环之前,需要清除listbox中的内容。程序如下:procedureTForm1.BtnForClick(Sender:I:forforI:=1to20Listbox1.Items.Add('String'+IntToStr第二button代码稍微复杂点。本例中让while循环基于一个随机增长的计数器。为实现它,我调用了Randomize过程,用它来重置随机数发生器,还调用了Random函数,其取值范围为100,即函数返回0至99之间的随机数,随机数序列控制while循环的执行次数。procedureTForm1.BtnWhileClick(Sender:TObject);I:I:=I:=I+RandomListbox1.Items.Add('RandomNumber:'+IntToStr每次点击Whle5.3显示了两次点击的结果,可看到不仅每次产生的数字不同,而且数据项数也不同。也就是说,这个while5.3:按While钮后显示的结With要讲的最后一种Pascal语句是WithWith要讲的最后一种Pascal语句是With语句,它在Delphi程序设计中很有用。With语句就不必每次重复变量的名字。例如对于以下的记录类型代码Date=recordMonth:Byte;Day:Byte;注意:用Break和Continue系统过程可以改变循环执行的标准流程。Break中断循环;Continue直接跳至循环测试句,或使计数器增加一个步长,然后继续循环(除非条件为空或计数器达到最大值)。还有两个系统过程Exit和Halt,让你立即从函数或过程中返回,或者终BirthDay.Year:=BirthDay.Year:=BirthDay.Month:=BirthDay.Day:=可以用with语句改进后半部分代码,如下:withBirthDaydoYear:=Month:=Day:=在Delphi程序中,这种方法能用于访问控件和类变量。现在通过procedureTForm1.WhileButtonClick(Sender:I:withListBox1.ItemsdoClear;//I:=0;I:=I+Random//Add('RandomNumber:'+IntToStr当你使用控件或类时,with语句通常能简化你的代码,尤其对嵌套域。例如,你要改变窗Form1.Canvas.Pen.Width:=2;Form1.Canvas.Pen.Color:=clRed;但如果用With语句代码会更简单:withForm1.Canvas.PendoWidth:=2;当编写的代码很复杂时 语句会当编写的代码很复杂时 语句会很有用,也可省去一些临时变量。但是这样做也有更严重的是,使用with语句可能会在代码中融入微妙的逻辑错误,甚至连编译器都难以发withButton1Width:=Caption:='NewCaption';Color:=clRed;这段代码改变了按Caption和Width改变了窗体的Color属性,而不是按钮的颜色!其原因是TButton控件没Color性又由于执行的代码是针对窗体对(我Button1.Width:=200;Button1.Caption:='NewCaption';Button1.Color:=clRed;//error!with(就象上面的这段代码wth语句,因为wth然而,你应该避免使用多个withwithListBox1,Button1if...end;//PascalPascal中的例程有两种形式:过程和函数。理论上说,过程是你要求计算机执行的操作,(这种参数称为引用,下一部分会讲到)。注意:说到可读性,要知道Pascalendifendcase语句if语句有一begin-end块,那么end标志语句结束;另外,case语句也总是以end。所end语句,常常是一个接一个,使代码难以理解,只有通过缩排跟end应的语句。解决这个问题的一个通用办法,也是使代码更可读的办法,是在end后面加注释,如下例:procedureShowMessage('HelloprocedureShowMessage('HellofunctionDouble(Value:Integer):Double:=Value*//or,asanfunctionDouble2(Value:Integer):Result:=Value*流行的做法是用procedureTForm1.Button1Click(Sender:procedureTForm1.Button2Click(Sender:X,Y:X:=Double(StrToInt(Edit1.Text));Y:=Double(X);ShowMessage(IntToStr提示:当调用一个现有的Delphi函数、过程或任何VCL方法时,你应该记住参数的个数及其数据类型。不过,只要键入函数或过程名及左括号,Delphi编辑器中会出现即时提示条,列出函数或过程的参数表供参考。这一特性被称为代码参数(CodeParameters),是代码识别技术的一(避免拷贝值压栈一般能加快程序执行速度(避免拷贝值压栈一般能加快程序执行速度ar下面是利用引用传递参数的例子,引用参数用varprocedureDoubleTheValue(varValue:Value:=Value*X:X:=DoubleTheValuex变量的值变成了20,因为过程通过引用访问了X的原始存储单元,由此改变了X总是通过值来传递对象,因为Delphi(除了极特殊的情况),Dlphi除了引用参数外,还有一种参数叫常量参数。由于不允许在例程中给常量参数赋新值++术语中的常量引用)事实上,如果编译下面有点可笑的代码,DelphifunctionDoubleTheValue(constValue:Integer):Integer;Result:=Value;//compilerDelphi3out。out参数没有初始值,只是用来返回一个值。out参数应Mvar参数与var参数相同。与C语言不同,Pascal与C语言不同,Pascal需要通过开放数组来实现参数传递functionSum(constA:arrayofInteger):I:Result:=forI:=Low(A)toHigh(A)Result:=Result+也就是说,参数类型已定义,但是上面High(A)获取数组的大小,注意其中函数返回Result的应用Result来X:=Sum([10,Y,也可以通Slice函数,只传递数组的一部分元素(传递元素个数由Slice函数的第二个参数指List:array[1..10]ofInteger;X,I:Integer;//initializetheforI:=Low(List)toHigh(List)List[I]:=I*//X:=Sum如果你只传递数组的一部分,可使用Slice函数,如下:X:=Sum(Slice(List,图6.1:单击PartialSlice按钮显示的除了类型固定的开放数组外技术上,arrayofconst除了类型固定的开放数组外技术上,arrayofconstFormat函数的定义:functionFormat(constFormat:constArgs:arrayofconst):N:=S:=Label1.Caption:=Format('Total:%d',[N]);Label3.Caption:=Format('%s%d',[S,N*2]);arRe类型元素兼容。TVarReccaseByteof(VInteger:Integer;VType:型用途不同,而且互不兼容。甚至可容纳的数据类型也不同,因为TVarRec支持Delphi数据类型,而TVarData支持OLE数据类型。在Delphi 4中,给定类型的开放数组与动态数组完全兼容。动态数组的语法与开放数组相同,区别在于你可以用诸如arrayofInteger指令定义变量,而不仅仅是传递参数。(VBoolean:Boolean);(VChar:Char);(VExtended:(VBoolean:Boolean);(VChar:Char);(VExtended:PExtended);(VString:PShortString);(VPointer:Pointer);(VPChar:PChar);(VObject:TObject);(VClass:TClass);(VWideChar:WideChar);vtPWideChar:(VPWideChar:PWideChar);vtAnsiString:(VAnsiString:Pointer);(VVariant:PVariant);(VInterface:Pointer);每种记录都有一个 域,乍一看不容易发现,因为它与实际意义的整型类型数据(常是一个引用或一个指针)SmAl函数,通过把字符串转成整数、字符转成相应的序号、rue布尔值加一,计算不同类型数据的和。这段代码以一个asefunctionSumAll(constArgs:arrayofconst):I:Result:=forI:=Low(Args)toHigh(Args)docaseArgs[I].VTypeofvtInteger:ResultifArgs[I].VBooleanResult:=Result+Ord(Args[I].VChar);Result:=Result+Args[I].VExtended^;vtString,vtAnsiString:Result:=Result+StrToIntDef((Args[I].VString^),0);Result:=Result+Ord(ArgsResultResult:=Result+Argsend;//Delphi调用协定32位的Delphi增加了新的参数传递方法,称为fastcall:只要有可能CPU存器的参数能多达三个,使函数调用操作更快。这种快速调用协定(Delphi3确省方式)可register关键字标示问题是这种快速调Windows不兼容,Win32API函数必须声明stdcall调用协定。这种协定是Win16API使用的原Pascal调用协定和Ccdecl调用协定除非你要调用外部Windows函数或定义Windows回调函数,否则你没有理由不用新增如果你使用Delphi或读过Delphi手册,大概已经听说过“方法”这个术语。方法是一特殊的函数或过程,它与类这一数据类型相对应。在Delphi中,每处理一个事件,都需要定义一下面是Delphi自动添加到窗体源代码中的一个procedureTForm1.Button1Click(Sender:{heregoesyourForward声明当使用一个标识符(任何类型)通常需要在例程使用之前提供一个完整的声明。然而在某些情况下可能做不到这一点,例A调用过程B,而过程B又调用过程A,那么你写过程代码时,不得不调用编译器尚未看到其声欲声明一个过程或函数,而且只给出它的名字和参数,不列出其实现代码,需要在句尾forward关键字procedureHello;子没什么实际意义,看过后你会对上述概念有所认procedureDoubleHello;procedureifMessageDlgifMessageDlg('DoyouwantadoublemtConfirmation,[mbYes,mbNo],0)=mrYesShowMessageprocedure上述方法可用来写递归调用:即DoubleHello调用Hello,而HelloDoubleHello。当然,必须设置条件终止这个递归,避免栈的溢尽管forward过程声明在Delphi中不常见,但是有一个类似的情况却经常出现。当你在一个单元(关于单元的更多内容见下一章)的interface部分声明一个过程或一个函数时,它被认为是一个forward声明,即使没有forward关键字也一样。实际上你不可能把整个例程的代码放在interface部分,不过你必须在同一单元中提供所声明例程的实现。类内部的方法声明forward当你给窗体或其组件添加事件Delphi会自动产生相应的代码。在TForm类中声明的事件是forward声明,事件代码放在单元的实现部分。下面摘录的源代码中有一个Button1Click方法声明:TForm1=class(TForm)ListBox1:TListBox;Button1:TButton;ObjectPascalDelphi程序员不会经常用到Pascal中的过程类型与C语言中的函数指针相似。过程类型的声明只需要参数列表;如果IntProc=procedure(varNum:这个过程类型与任何参数完全相同的例程兼容(或用C语言行话来说,具有相同的函数特procedureDoubleTheValue(varValue:Value:=Value*针)针)X:IP:=DoubleTheValue;X:=5;IPX:X:=DoubleTheValue上面第一段代码明显要复杂一些,那么我们为什么要用它呢?因为在某些情况下,调用什么Proype接近实际应用。如图6.3所示,新建一个工程,在上面放两个radio按钮和一个push按钮。例中有两个过程,一个过程使参数的值加倍,与前面的DoubleTheValue过程相似;另一个过程使参数的值变图6.3:例ProcType窗体procedureTripleTheValue(varValue:Value:=Value*ShowMessage('Valuetripled:'+IntToStr注意:在16位Delphi中,如果要将例程用作过程类型的实际值,必须用far指令声明该例程。当用户按Apply按钮,程序会根据radio按钮状态选择执行的过程。实际上,当窗体中有两个radio按钮时,你只能选择一个,因此你只需要在Apply按钮的OnClick事件中添加代码检测radio钮的值,就能实现程序要求。不过为了演示过程类型的使用,我舍近求远选择了麻烦但有趣的方法:只要用户选中其中一个radio按钮,按钮对应的过程就会存入过程变量:procedureTForm1.DoubleRadioButtonClick(Sender:TObject);IP:=当用户按Apply按钮,程序就执行过程变量保存的过程:procedureTForm1.ApplyButtonClick(Sender:TObject);IPIP和X变量,需要使变量在整个窗体单元中可见,因此不能TForm1={PrivatedeclarationsIP:X:下面是从VCL的数学单元(MathUnit)functionMin(A,B:Integer):Integer;overload;functionMin(A,B:Int64):Int64;overload;functionMin(A,B:Single):Single;overload;functionMin(A,B:Double):Double;overload;functionMin(A,B:Extended):Extended;overload;当调用方式为Min(10,20)时,编译器很容易就能判定你调用的是上列第一个函数,因此每个例程声明后面必须添加overload下面是ShowMsg下面是ShowMsg过程的三个重载过程。我已把它们添加到例OverDef中(一个说明载和确省参数的应用程序procedureShowMsg(str:string);overload;MessageDlg(str,mtInformation,[mbOK],Params:arrayofconst);overload;MessageDlg(Format(FormatStr,Params),mtInformation,[mbOK],0);procedureShowMsg(I:Integer;Str:string);ShowMsg(IntToStr(I)+''+ShowMsgShowMsg('Total=%d.',[100]);ShowMsg(10,'MBytes');Dlphi.4符串时,DphihowMsg例程参数列表,滤掉了第一个参数为整数的例程。图6.4:窗口中代码参数提示条显示的重载例程重载例程必须用overload关键字明确标示,你不能在同一单元中重载没有重载例程必须用overload关键字明确标示,你不能在同一单元中重载没有overload标示的例程,否则会出现错误信息:"Previousdeclarationof'<name>'wasnotmarkedwiththe'overload'directive."。不过你可以重载在其他单元中声明的例程,这是为了与以前的Delphi版本兼容,以前的Delphi版本允许不同的单元重用相同的例程名。无论如何,这是例程procedureMessageDlg(str:string);overload;Dialogs.MessageDlg(str,mtInformation,[mbOK],这段代码并没有真正重载原始的MessageDlg例程,实际上如果键入:MessageDlg VCL的唯一途径OverDefF.MessageDlgDelphi允许你给函数的参数设定确省值,这样调用函数时该参数可以加上,也可以省略。例把应用程序全程对象的MessageBox方法重新包装了一下,用PChar替代字符串,并设定procedureMessBox(Msg:string;Caption:string='Warning';Flags:LongInt=mb_OKorPChar(Caption),Flags);MessBoxPChar(Caption),Flags);MessBox('SomethingwrongMessBox('Somethingwronghere!','Attention');MessBox('Hello','Message',mb_OK);从图6.5中可以看到,Delphi的代码参数提示条会用不同的风格显示确省值参数,这样你图Delphi代码参数提示条用方括号标示确省值参数,调用时可以省略该注意一点不产生任何支持确省参数的特殊代码,也不创建例程的多份拷贝,缺参数是由编译器在编译时添加到调用例程的代码中使用确省参数有一重要限定:你不能“”MessBox('Hello',mb_OK);//始进行省略,换句话说,如果你确省参数的使用规则还包括确省值必须是常量。显动态数组和界面类型的确省参数值只能是i;至于记录类型,则根本不能用作确省参数。确省参数必须通过值参或常参传递。引用参 var不能有缺省值前ShowMsg过程改前ShowMsg过程改成procedureShowMsg(Str:string;I:Integer=0);overload;MessageDlg(Str+':'+IntToStr(I),mtInformation,[mbOK],0);ShowMsg编译器会显示Ambiguousoverloadedcallto'ShowMsg'.(不明确重载调用无法调用ShowMsg过程,因为编译器搞不清楚你是要调用只带字符串参数的ShowMsg过在Borland公司的TurboPascal和16位Delphi中,传统的字符串类型是一个字符序255(确省最大值为255),当然你也可以声明更短的字符串以节约存储空间为克服传统Pascal字符串的局限性,32位Delphi增加了对长字符串的支持。这样共有三ShortString短字符串类型也就是前面所述的传统Pascal字符串类型。这类字符串多只能有255个字符,与16位Delphi中的字符串相同。短字符串中的每个字符都属于ANSIChar类型(标准字符类型)。ANSIString长字符串类型就是新增的可变长字符串类型。这类字符串的内存动态分配用计数,并使用了更新前拷贝(copy-on-write)技术。这类字符串长度没有限制(可以存储多达20亿个字符!),其字符类型也是ANSIChar类型。WideStringANSIString类型相似,只是它基WideChar类型,WideChar字符为双字节Unicode字符。如果只简单地用String定义字符串,那么该字符串可能是短字符串也可能是ANSI长字串,这取决于$H的值,$H+(确省)代表长字符串(ANSIString类型)。长字符串是Delphi库中控件使用的字符串。 已没有扩展的余地,这时字符串必须被完整地拷贝到另一个存储单元。当这种情况发生时,D 已没有扩展的余地,这时字符串必须被完整地拷贝到另一个存储单元。当这种情况发生时,DphiStLngthSetLength(String1,SetLength过程只是完成一个内存请求,并没有实际分配内存。它只是把将来所需的内存预留出来,实际上并没有使用这段内存。这一技术源Windows操作系统,现被Delphi用来动态分一般不需要设置字符串的长度,不过当需要把长字符串作为参数传递给类型转换后),你必须用SetLength为该字符串预留内存空间。函数时(为了帮你更好地理解字符串的内存管理细节,在程序中声明了两个全程字符串:Str1和Str1:='Hello';Str2:=Str1;除了字符串操作外,程序还用下面的functionStringStatus(constStr:string):Result:='Address:'+IntToStr(Integer(Str))',Length:'+IntToStr(Length(Str))',References:'+IntToStr(PInteger(Integer(Str)-8)^)',Value:'+在StingStatus函数中,用常量参数传递字符串至关重要。用拷贝方式(值参)传递会引起副作用,因为函数执行过程中会产生一个对字符串的额外引用;与此相反,通过引用(ar)或为获取字符串内存地址(了同一内存区通过类型映射把字符串类型强行转换为整型。字符串实际上是引用,也就是指通过运行这个例子,你会看到两个串内容相同、内存位置相同、引用记数为2,如图7.1中列这是copy-on-write术的结果。图7.1:例StrRef显示两个串的内部状态,包括当前引用第二个按钮(Change)的OnClick第二个按钮(Change)的OnClick事件代码如下,结果如图7.1列表框第二部分所示:procedureTFormStrRef.BtnChangeClick(Sender:Str1[2]:=ListBox1.Items.Add('Str1[2]:=''a''');ListBox1.Items.Add('Str1-'+StringStatus(Str1));ListBox1.Items.Add('Str2-'+StringStatus(Str2));注意,BtnChangeClick能在执行完BtnAssignClick后才能执行。为此,程序启动后第二个按钮不能用(按钮的Enabled属性设成False);第一个方法结束后激活第二个按钮。你可以自由地扩展这个例子,用StringStatus函数探究其它情况下长字符串的特性。Delphi字符串与WindowsPChar长字符串为零终止串,这意味着长字符串完全与Windows使用的C语言零终止串兼容nl)结尾。零终止串在Delphi中可用下标从零开始的字符数组表示,C语言就是用这种数组类型定义WidowsAPI函数(C语言)Pascal长字符串与CWindowsAPI函数时,你可以直接把长字符串映射为PChar类型。下例把一个窗体的标题拷贝给PChar字符串(用API函数GetWindowText),然后再把它拷贝给按钮的Caption属性,代码如下:procedureTForm1.Button1Click(Sender:S1:SetLength(S1,GetWindowTextGetWindowText(Handle,PChar(S1),LengthButton1.Caption:=注意:代码中用StngthPhr类型传递值(),那么代码会很ab(标签)控件的aptin属性作为参数传递给了PIPhrStWnowt(Hndl,Phar(Lab.apton));当需要把WideStringWindows兼容类型时,你必PWideChar代替PChar进行转换,WideString常用于OLE和COM程序。刚才展现了长字符串的优点,现在谈谈它的弊端。当你把长字符串转换为PChar类型时能会引发一些问题,问题根本在于:转换以后字符串及其内容将由你来负责,Delphi不再管了。现在把上面Button1Click代码稍作修改:procedureTForm1.Button2Click(Sender:S1:SetLength(S1,GetWindowText(Handle,PChar(S1),Length(S1));S1:=S1+'isthetitle';//thiswon'tworkButton1.Caption:=S1;程序编译通过,但执行结果会令你惊讶,因为按钮的标题并没变,所加的常量字符串没有添加到按钮标题中。问题原因是Widows写字符串时(在GetWindowTextAPI调用中),Windows没有正确设置Pascal长字符串的长度。Dephi仍可以输出该字符串,并能通过零怎么解决这个问题呢?解决方法是告诉系统把GetWindowTextAPI函数返回的字符串再转换成Pascal字符串。然而,如果你用以下代码:S1:=Stringi的Pascal长字符串,需要你把字符串重新映射为一个PChar字符串,然后让Dlphi再把它S1:=String(PChar(S1:=PCharS1));,因为在Delphi中Pchar转换到stringprocedureTForm1.Button3Click(Sender:S1:SetLength(S1,GetWindowText(Handle,PChar(S1),Length(S1));S1:=String(PChar(S1));S1:=S1+'istheGetWindowText(Handle,PChar(S1),Length(S1));S1:=String(PChar(S1));S1:=S1+'isthetitle';Button3.Caption:=S1;另一个办法是用PChar字符串的长度重新设定Delphi字符串长度,可以SetLength(S1,StrLen(PChar在例ongStr中你可以看到三种方法的结果,分别由三个按钮执行。如果只想访问窗体标题,仅需要用到窗体对象本身的CptonWindowsPI另有一种方法能格式化数字、货币值和其他字符串,这就是功能强大的Format函数参数包括:一个基本文本字符串、一些占位符(通常由%符号标出)和一个数Format('First%d,Second%d',[n1,n2]);其中n1和n2是两个整数值,第一个占位符由第一个值替代,第二个占位符由第二个值替产生一个运行时间错误,因此设置编译时间类型检查会有利于除了%d外,Format函数还定义了许多占位符,见表7.1。这些占位符定义了相应数据类Format('%8d',该句把数字n1转换成有8(-)。表占位 说dpse传统的 语言其数组大小是预先确定的,当你用数组结构声明数据类型时,你必须传统的 语言其数组大小是预先确定的,当你用数组结构声明数据类型时,你必须i中增加了非常简单的动态数组实现方法,实现过程效仿前面讲过的动态长字符串。cop-o-write技术。这不是个大问题,因为你可以把变量值设置为nl释放数组内存。大小的内存,SetLength过程还可以改变数组大小而不影响其内容,除此外还有一些字符串过程也可用于数组,如Copy函数。procedureTForm1.Button1Click(Sender:Array1:arrayofArray1[1]:=100;//SetLength(Array1,Array1[99]:=100;//如果你只定义一个数组元素个数,那么索引总是从0开始。Pascal中的普通数组既能用不过Length、High和Low函数了解到动态数组的状况,不过对于动态数组,Low函数返回值总是0,High函数返回数组大小减1,这意味着空的动态数组其函数High返回值是-1,这是一个很怪的值,因为它比Low的返回值还小。图8.1:例DynArr窗体gnmDelphi帮助文件的Currencyanddate/timeformattingvariables主以上作了简短的介绍,现在举个简例,例名DynArr,见图8.1以上作了简短的介绍,现在举个简例,例名DynArr,见图8.1个全程数组并在OnCreate事件中初始化了第一个数组:Array1,Array2:arrayofprocedureTForm1.FormCreate(Sender://SetLength(Array1,这样就把数组所有值设置为0。完成这段代码你马上就能读写数组元素的值,而不用害怕内存procedureTForm1.btnFillClick(Sender:I:forI:=Low(Array1)toHigh(Array1)Array1[I]:=Grow钮用于修改数组大小,但并不影响数组内容。单击Grow按钮后,你可以Getvalue按钮进行检验:procedureTForm1.btnGrowClick(Sender://growkeepingexistingSetLength(Array1,procedureTForm1.btnGetClick(Sender://Caption:=IntToStr(Array1is按钮的OnCck(一个新变量,但引用内存中同一数组。从中可见,如果你改procedureTForm1.btnAliasClick(Sender://Array2Array2:=//changeone(bothArray2[99]:=//showtheCaption:=IntToStr(Array1在btnAliasick事件中增加了两部分操作内容。第一部分是数组等同测试,不过并不是测rocedureTFom.btnAliasicSend:TObject);ifArray1=Array2Array1:=Copy(Array2,0,btnislckopyrray1所引用的是11Gtlue和Stlue(除非你把范围检查rang-chcing。虽然如此,FilWindows句柄DelphiWindows引入了不少数据类型,其中句柄最重要。这种数据类型名为该类Windows单元中定义THandle=句柄数据类型通过数字实现,但并不当数字用。在Windows中,句柄是一个系统内部数据结构的引用。例如,当你操作一个窗口,或说是一个Delphi窗体时,系统会给你一个该窗口的句柄,系统会通知你:你正在操作142号窗口,就此,你的应用程序就能要求系统对142号窗口进把句柄作为它的第一个参数,如GDI(

温馨提示

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

评论

0/150

提交评论