Delphi7升级到Delphi 2010、Delphi XE、Delphi XE2总结 .
Delphi7升级到Delphi 2010、Delphi XE、Delphi XE2总结
1,PChar
因为Delphi不支持无类型指针的算术运算,很多程序员使用 PChar来代替Pointer,即使指针指向目标并不是PAnsiChar。
考虑如下代码:
<p><span class="kwd">var</span> <span class="pln"> P</span><span class="pun">:</span><span class="typ">PChar</span><span class="pun">;</span> <span class="pln"> </span><span class="typ">Buffer</span><span class="pun">:</span><span class="typ">Pointer</span><span class="pun">;</span> <span class="kwd">begin</span> <span class="pln"> </span><span class="typ">GetMem</span><span class="pun">(</span><span class="typ">Buffer</span><span class="pun">,</span><span class="lit">255</span><span class="pun">);</span> <span class="pln"> P</span><span class="pun">:=</span><span class="typ">Buffer</span><span class="pun">;</span> <span class="pln"> p</span><span class="pun">^:=</span><span class="com">#1;</span> <span class="pln"> </span><span class="typ">Inc</span><span class="pun">(</span><span class="pln">P</span><span class="pun">);</span> <span class="pln"> p</span><span class="pun">^:=</span><span class="com">#2;</span> <span class="pln"> </span><span class="typ">FreeMem</span><span class="pun">(</span><span class="typ">Buffer</span><span class="pun">,</span><span class="lit">255</span><span class="pun">);</span> <span class="kwd">end</span><span class="pun">;</span></p>
在2010中PChar已经不再表示PAnsiChar而是表示PWideChar,如果依然这样写,运行时很可能会得到一个内存访问错误。因为每 次Inc(P),实际上指针向前移动了2字节,因为SizeOf(WideChar)=2,Inc(P)相当于 P:=P+SizeOf(WideChar)。
解决方法是把PChar替换成PAnsiChar
2,Move FillChar CopyMemory
这些函数依赖的是字节长度,往往我们直接使用Length(Str)来获取,这是行不通的。
考虑如下代码:
<p><span class="kwd">var</span> <span class="pln"> P1</span><span class="pun">,</span><span class="pln">P2</span><span class="pun">:</span><span class="typ">String</span><span class="pun">;</span> <span class="kwd">begin</span> <span class="pln"> P1</span><span class="pun">:=</span><span class="str">'test'</span><span class="pun">;</span> <span class="pln"> </span><span class="typ">SetLength</span><span class="pun">(</span><span class="pln">P2</span><span class="pun">,</span><span class="typ">Length</span><span class="pun">(</span><span class="pln">P1</span><span class="pun">));</span> <span class="pln"> </span><span class="typ">Move</span><span class="pun">(</span><span class="pln">P1</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="pln">P2</span><span class="pun">[</span><span class="lit">1</span><span class="pun">],</span><span class="typ">Length</span><span class="pun">(</span><span class="pln">P1</span><span class="pun">));</span></p><p><span class="kwd">end</span> </p>
在2010中String默认映射到UnicodeString,单个字符是2字节,所以上文中P1实际占用了8字节内存,而传给Move函数的长 度只有4字节,最终结果是P2="te"。
解决办法1:
修改String为AnsiString,该方案虽然可行,但你的程序就享受不到Unicode待遇了。
解决办法2:
SetLength 函数不要修改,因为他的长度参数是字符长度,而不是字节长度。
Move函数的最后一个参数 Length(P1) 修改成 Length(P1)*SizeOf(Char)。
注意:不要偷懒使用万一老师说的ByteLength函数,该函数并没有For AnsiString的重载,编译器会 把参数隐式转化为UnicodeString然后,ByteLength函数计算UnicodeString的长度。例如:一旦你不小心传入了一个 AnsiString类型长度为4的字符串,函数会返回8,而不是你期望的长度4。
3,Key in ['a'..'z','B','C']
这类代码最好替换成CharInSet(Key,['a'..'z','B','C']) 不然会当作AnsiChar处理。
4,WideString
代码中的所有WideString都考虑替换成String,现在 WideString只是为了与COM兼容而存在,且没有引用计数,性能低下。
5,Tnt控件
如果你的工程使用了Tnt控件或以前的WideTextPos WideStringReplace之类的东西都替换成标准的吧,不用曲线救国了。
---------经过修改,可以在Delphi2010下运作的第三方组件--------------
1,PNGDelphi
2,EmbeddedWB
3,SynEdit的语法高亮组件 unihighlighter
4,JEDI Win32API Header
这些组件现在可以在Delphi2010下运作了。
6,引用AnsiStrings单元
如果你有必要使用 AnsiLowerCase AnsiCompareStr之类的函数,一定要引用AnsiStrings单元。
如果你不引用该单元,即便编译不报错,你实际上是用的还是Unicode版本的函数,会有隐式的转化。不信你打开参数自动完成,看看IDE提示给你的类型是什么?天啊AnsiLowerCase参数竟然还是String,而不是AnsiString。看来Delphi2010太迫切的要抛弃Ansi字符串了,以至于你不引用AnsiStrings单元,所有Ansixxxx函数实际上还是Unicode版本。
7,AnsiCopy AnsiPos AnsiDelete
不要用AnsiCopy AnsiPos AnsiDelete,因为Copy Pos Delete三个函数已经有了For Ansi的重载。
8,把Char转化为小写用什么?
答案:试试看Character单元的新函数 ToUpper ToLower。以前我都是用System里面的UpCase函数,现在依然可用不过却找不到LowCase DownCase之类的函数,困扰我好久好久。索性全使用Character单元提供的新函数吧。
9,编译期警告:[DCC Warning] Unit1.pas(31): W1057 Implicit string cast from 'AnsiString' to 'string'
如果你的代码中包含了两种字符串(Unicode、Ansi)之间进行隐式转化的时候就会出现该提示。
如下代码就会触发该警告:
var Unicode:String; Ansi:AnsiString; begin Ansi:='test..'; Unicode:=Ansi;
把旧版本的Delphi项目升级到2010,我通常都是借助编译警告来快速寻找需要改动的部分。通常你可以把赋值双方都声明为String(默认影射到UnicodeString),就可以避免该警告。但如果你确定必须在此处保留Ansi并进行转化的时候,建议你显式的转化他们(例如:Unicode:=String(Ansi);),这样可以避免该警告,方便你在升级过程中继续寻找其他需要修改的地方。
10,Readln Writeln 写入文件时候要注意
如果你传给Writeln一个AnsiString,那么它也会在文件中写入AnsiString,那么你读取得时候就必须传给Readln一个AnsiString的类型,否则就是乱码。例如旧工程的配置文件是Ansi的,而你已经把相关读取配置的代码升级为支持Unicode,那么运行工程前你首先要用记事本之类的工具把配置文件另存为成Unicode编码。当然你还要注意跳过Unicode文件头的两个字节FE FF。
11,别再用String来操作二进制数据了
一定要记住String只是字符串,不要把它当作缓冲区、内存流使用。我的项目中,有很多地方是使用字符串来处理二进制数据,导致在本次升级中颇为费脑。如果当时用TBytes或TStream就好了。
反面教材:
var Int1,Int2,Int3,Int4:Integer; Buf:String; begin SetLength(Buf,12); Move(Int1,Buf[1],SizeOf(Integer)); Move(Int1,Buf[5],SizeOf(Integer)); Move(Int1,Buf[9],SizeOf(Integer)); Buf:=Buf+'前面有3个Integer。';
12,还是PChar
注意在2010中是这样的:
PChar= Pointer to a WideChar array;
PAnsiChar = Pointer to a AnsiChar array;
如果你还像是在Delphi 7中那样:PChar(AnsiString)那后果过是很严重的。
unit
ReCode;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
Function
JiaMi(Src:
String
; Key:
String
):
String
;
Function
JieMi(Src:
String
; Key:
String
):
String
;
implementation
Function
JiaMi(Src:
String
; Key:
String
):
String
;
var
KeyLen :
Integer
;
KeyPos :
Integer
;
offset :
Integer
;
dest :
String
;
SrcPos :
Integer
;
SrcAsc :
Integer
;
Range :
Integer
;
begin
KeyLen:=Length(Key);
KeyPos:=
0
;
Range:=
1
;
Randomize;
offset:=Random(Range);
dest:=format(
'%1.2x'
,[offset]);
for
SrcPos :=
1
to
Length(Src)
do
begin
SrcAsc:=(Ord(Src[SrcPos]) + offset)
MOD
255
;
if
KeyPos < KeyLen
then
KeyPos:= KeyPos +
1
else
KeyPos:=
1
;
SrcAsc:= SrcAsc
xor
Ord(Key[KeyPos]);
dest:=dest + format(
'%1.2x'
,[SrcAsc]);
offset:=SrcAsc;
end
;
Result:=Dest;
end
;
//解密函数
Function
JieMi (Src:
String
; Key:
String
):
String
;
var
KeyLen :
Integer
;
KeyPos :
Integer
;
offset :
Integer
;
dest :
String
;
SrcPos :
Integer
;
SrcAsc :
Integer
;
TmpSrcAsc :
Integer
;
Range :
Integer
;
begin
KeyLen:=Length(Key);
if
KeyLen =
0
then
key:=
'starlin'
;
KeyPos:=
0
;
SrcPos:=
0
;
SrcAsc:=
0
;
Range:=
1
;
offset:=StrToInt(
'$'
+ copy(src,
1
,
2
));
SrcPos:=
3
;
repeat
try
SrcAsc:=StrToInt(
'$'
+ copy(src,SrcPos,
2
));
except
SrcAsc:=StrToInt(
'$00'
);
end
;
if
KeyPos < KeyLen
Then
KeyPos := KeyPos +
1
else
KeyPos :=
1
;
TmpSrcAsc := SrcAsc
xor
Ord(Key[KeyPos]);
if
TmpSrcAsc <= offset
then
TmpSrcAsc :=
255
+ TmpSrcAsc - offset
else
TmpSrcAsc := TmpSrcAsc - offset;
dest := dest + chr(TmpSrcAsc);
offset:=srcAsc;
SrcPos:=SrcPos +
2
;
until
SrcPos >= Length(Src);
Result:=Dest;
Result:=Copy(Result,
1
,Length(Result)-
1
);
end
;
end
.
unit
ReCode;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,AnsiStrings;
Function
JiaMi(Src:
String
; Key:
String
):
String
;
Function
JieMi(Src:
String
; Key:
String
):
String
;
implementation
Function
JiaMi(Src:
String
; Key:
String
):
String
;
var
KeyLen :
Integer
;
KeyPos :
Integer
;
offset :
Integer
;
dest :
String
;
SrcPos :
Integer
;
SrcAsc :
Integer
;
Range :
Integer
;
IntTemp:
integer
;
SrcAnsi:
PAnsiChar
;
begin
KeyLen:=Length(Key);
KeyPos:=
0
;
Range:=
1
;
Randomize;
offset:=Random(Range);
dest:=format(
'%1.2x'
,[offset]);
SrcAnsi:=
PAnsiChar
(
AnsiString
(Src));
IntTemp:= Length(SrcAnsi);
for
SrcPos :=
1
to
IntTemp
do
begin
SrcAsc:=(Ord(SrcAnsi[SrcPos-
1
]) + offset)
MOD
255
;
if
KeyPos < KeyLen
then
KeyPos:= KeyPos +
1
else
KeyPos:=
1
;
SrcAsc:= SrcAsc
xor
Ord(Key[KeyPos]);
dest:=dest + format(
'%1.2x'
,[SrcAsc]);
offset:=SrcAsc;
end
;
Result:=Dest;
end
;
//解密函数
Function
JieMi (Src:
String
; Key:
String
):
String
;
var
KeyLen :
Integer
;
KeyPos :
Integer
;
offset :
Integer
;
dest :
String
;
SrcPos :
Integer
;
SrcAsc :
Integer
;
TmpSrcAsc :
Integer
;
Range :
Integer
;
SrcAnsi:
PAnsiChar
;
IntTemp,i:
Integer
;
ByteArray:
array
of
Byte
;
begin
KeyLen:=Length(Key);
if
KeyLen =
0
then
key:=
'starlin'
;
KeyPos:=
0
;
SrcPos:=
0
;
SrcAsc:=
0
;
Range:=
1
;
offset:=StrToInt(
'$'
+ copy(src,
1
,
2
));
SrcPos:=
3
;
IntTemp:=Length(Src)
div
2
;
setlength(ByteArray,IntTemp);
i:=
0
;
repeat
try
SrcAsc:=StrToInt(
'$'
+ copy(src,SrcPos,
2
));
except
SrcAsc:=StrToInt(
'$00'
);
end
;
if
KeyPos < KeyLen
Then
KeyPos := KeyPos +
1
else
KeyPos :=
1
;
TmpSrcAsc := SrcAsc
xor
Ord(Key[KeyPos]);
if
TmpSrcAsc <= offset
then
TmpSrcAsc :=
255
+ TmpSrcAsc - offset
else
TmpSrcAsc := TmpSrcAsc - offset;
ByteArray[i]:=TmpSrcAsc;
i:=i+
1
;
offset:=srcAsc;
SrcPos:=SrcPos +
2
;
until
SrcPos >= Length(Src);
CopyMemory(@SrcAnsi[
0
],@ByteArray[
0
],IntTemp);
dest:=
string
(AnsiStrings
.
strpas(SrcAnsi));
Result:=Dest;
end
;
end
.
Delphi7升级到Delphi 2010、Delphi XE、Delphi XE2总结 .相关推荐
- [转]Delphi 2010 3513正式版破解
原文地址: http://www.cnblogs.com/tc310/archive/2010/05/08/1730300.html http://www.kucol.com/html/NEws/ye ...
- RAD Studio/Delphi 2010 3615下载+破解
RAD Studio/Delphi 2010 3615下载+破解 官方下载地址: http://altd.embarcadero.com/download/RADStudio2010/delphicb ...
- Delphi 2010 安装及调试
呵呵,毫不客气地说,Delphi 2010 这个版本可以算是 Delphi 的一个"里程碑",为什么这么说?因为这个版本实现了几个 Delphi 应该有却一直没有的功能 Delph ...
- Delphi 2010 refactor / refactoring 重构不能使用的原因以及解决
delphi 2010 refactor / refactoring 重构不能使用. 经过实验的确是DelphiDistiller上的设置贴心的过头的原因. 一切的罪魁祸首就是"Don't ...
- Delphi 2010安装及使用UniDAC安装和使用笔记
Delphi 2010安装及使用UniDAC安装过程: 1.进入"...\unidac40src\Source\Delphi14"文件夹(注意不同delphi版本可能source下 ...
- Delphi 2010的好消息
从橙子那里得到了Delphi 2010的好消息. 首先是一个类似于E/R Studio的东西被集成了进去,或许以后用它来做数据库程序会方便很多,"据说"是会有原生的ORM框架,来帮 ...
- 从 Delphi 7 到 Delphi 2010
从 Delphi 7 到 Delphi 2010 ( 一 )基本数据类型的变化2010-06-30 12:47 -------------------------------------------- ...
- 下载delphi 5 至 delphi 2010
Delphi Distiller 是delphi爱好者都知晓的一个小工具. 从1.70版本开始,增加了下载页,包括delphi 5 至 delphi 2010 的每个版本和更新. 昨天因为换了硬盘,需 ...
- Delphi - 2010下安装IOComp
原文地址:Delphi - 2010下安装IOComp - HuangJacky - 博客园http://www.cnblogs.com/huangjacky/archive/2010/01/18/1 ...
最新文章
- device tree --- #address-cells and #size-cells property【转】
- php cms帮助文档,phpcms手册
- 设为首页加入收藏代码
- android 渲染流程
- 升级安装linux ssh 升级安装
- Linux服务器上的oracle数据导入和导出
- Oracle 随机获取N条数据
- python 全局_全局关键字,带Python示例
- 苹果付费app共享公众号_娄底共享云店铺公众号
- 32位和64位操作系统,二者有何区别?是否64位更快?
- “”和“”的你真的理解吗?
- Tomcat中server.xml配置及Context的配置说明
- android 点击屏幕事件_Android 事件分发机制
- android.net.http.AndroidHttpClient Android6.0 API23以后失效
- python判断文字是否是中文
- 传智黑马java基础学习——day10(继承、抽象类)
- java无损压缩图片
- 基于CAN总线的汽车诊断协议--Windows上位机设计
- 基于JAVA的城市公交查询系统毕业论文
- 360断网急救箱-网络连接配置有问题