我现在决定将我的Delphi 7项目转换为XE4,但在我的一个代码行中我得到了一个女巫的问题我试图修复它但没有希望,所以我希望有人可以帮我修复它
问题在于:
在服务器和客户端应用程序(酒店客房管理系统)之间使用的共享单元中,我有这种记录类型:
Type
THotelClientDetails = packed record
LSize: Integer;
ClientName: array[0..25] of char;
ClientRoomN: Integer;
RWithInternet: Boolean;
RoomStatus :Integer;
//... etc
end;
PHotelClientDetails = ^THotelClientDetails;
在客户端应用程序中,我使用以下过程:
procedure TCForm.SendClientDetailsClick(Sender: TObject);
var
pClientDetails: PHotelClientDetails;
iSize: Integer;
begin
iSize:= SizeOf(THotelClientDetails)+Length(ClientNameEd.Text)+1;
GetMem(pClientDetails,iSize);
ZeroMemory(pClientDetails,iSize);
pClientDetails.LSize := iSize;
StrCopy(pClientDetails.ClientName,PChar(ClientNameEd.Text));
pClientDetails.ClientRoomN :=StrToInt(ClientNEd.text);
pClientDetails.RWithInternet:=ClientWInternet.Checked;
pClientDetails.RoomStatus :=ClientRoomStatus.ItemIndex;
StrCopy(Pointer(Cardinal(pClientDetails)+SizeOf(THotelClientDetails)),
PChar(ClientNameEd.Text));
SendClientsBuffer(pClientDetails,iSize);// to the Server for Check
FreeMem(pClientDetails);
end;
在服务器应用程序中,我使用以下过程:
Procedure TSForm.GetClientDetails(pClientDetails:PHotelClientDetails; Cntx: Pointer);
var
ClientName: string;
begin
ClientName:=PChar(Cardinal(pClientDetails)+SizeOf(THotelClientDetails));
//*** just a test to get the ClientName
ShowMessage(ClientName);
//***
end;
所以我的问题是当使用Delphi 7时,我得到客户端应用程序发送的全名: 例如,如果我想将客户端“simon”或“matthew”发送到服务器
我得到了正确的名字:
ShowMessage(ClientName);//simon or matthew
但是当在XE4中使用相同的程序时,我总是得到
simonsim 和 matthew
matt这意味着服务器没有像Delphi7项目那样接收完整的客户端名称。
虽然在两个项目中添加了单位“System.AnsiStrings;”。
那么请问我该如何解决这个问题?
非常感谢。
西蒙
答案 0 :(得分:3)
Delphi 7使用ANSI字符串(单字节字符),而2009年版本的Delphi使用Unicode字符串(多字节字符)。
对您的代码最直接的解决方法是从Char
更改为AnsiChar
,string
更改为AnsiString
,将PChar
更改为PAnsiChar
:
Type
THotelClientDetails = packed record
LSize: Integer;
ClientName: array[0..25] of AnsiChar;
ClientRoomN: Integer;
RWithInternet: Boolean;
RoomStatus :Integer;
//... etc
end;
StrCopy(pClientDetails.ClientName, PAnsiChar(ClientNameEd.Text));
// and
StrCopy(Pointer(Cardinal(pClientDetails) + SizeOf(THotelClientDetails)),
PAnsiChar(ClientNameEd.Text));
Procedure TSForm.GetClientDetails(pClientDetails:PHotelClientDetails; Cntx: Pointer);
var
ClientName: string;
begin
ClientName := PAnsiChar(Cardinal(pClientDetails)+SizeOf(THotelClientDetails));
//*** just a test to get the ClientName
ShowMessage(ClientName);
//***
end;
有几十个(如果不是数百个)有关将Delphi代码从D2007及更早版本移植到D2009及更高版本的问题。您应该花一些时间在此处浏览delphi-2009,delphi-xe和delphi-xe2标记。
答案 1 :(得分:1)
我发布这个作为答案,因为它比问题的评论更容易格式化。
关于你可能想要的事情的一些评论:
Length
将获得字符串的实际字节数。 SendClientDetailsClick
的部分移动到THotelClientDetails
THotelClientDetails.ClientName
限制为26个字节(25 AnsiChar
个字节字节加上一个空终止字节),因此不需要iSize:= SizeOf(THotelClientDetails)+Length(ClientNameEd.Text)+1;
iSize:= SizeOf(THotelClientDetails)
。pClientDetails: PHotelClientDetails
的唯一原因就是你打电话
SendClientsBuffer(pClientDetails,iSize);// to the Server for Check
SendClientsBuffer(ClientDetails,iSize);// to the Server for Check
StrCopy(pClientDetails.ClientName,PChar(ClientNameEd.Text));
ClientNameEd
执行两次复制操作?
StrCopy(pClientDetails.ClientName,PChar(ClientNameEd.Text));
//...
StrCopy(Pointer(Cardinal(pClientDetails)+SizeOf(THotelClientDetails)),
PChar(ClientNameEd.Text));
FreeMem
应位于finally
区块内。这样的事情更合适:
procedure TCForm.SendClientDetailsClick(Sender: TObject);
var
ClientDetails: PHotelClientDetails;
iSize: Integer;
begin
iSize := SizeOf(THotelClientDetails);
ZeroMemory(@ClientDetails, iSize);
ClientDetails.LSize := iSize;
StrLCopy(ClientDetails.ClientName, PAnsiChar(ClientNameEd.Text), SizeOf(ClientDetails.ClientName)-1);
pClientDetails.ClientRoomN := StrToInt(ClientNEd.text);
pClientDetails.RWithInternet := ClientWInternet.Checked;
pClientDetails.RoomStatus := ClientRoomStatus.ItemIndex;
SendClientsBuffer(@ClientDetails,iSize); // to the Server for Check
end;