左侧无法为记录类型分配值。

4

我正在尝试将我的应用程序从Delphi 2007升级到Delphi 10 Seattle。我知道在更改记录之前需要将其复制到本地变量中,然后再分配回去。我正在尝试同样的方法,但仍然出现错误,提示“无法向左边赋值”。请问有人能帮忙吗?

procedure TMydlg.WMGetMinMaxInfo(var Msg:TMessage);
var
     MinMaxInfo: TMinMaxInfo;
begin
   inherited;
   MinMaxInfo := (PMinMaxInfo(Msg.LParam)^);

   with MinMaxInfo do
   begin

      ptMinTrackSize.X := MinWidth;
      ptMinTrackSize.Y := MinHeight;
      ptMaxTrackSize.X := MinWidth;

   end;

   // Error here. Left side cannot be assigned to
   (PMinMaxInfo(Msg.LParam)^) := MinMaxInfo;

TMinMaxInfo是Winapi.windows中的一个类


2
删除 PMinMaxInfo(Msg.LParam)^ 周围的括号 '(' 和 ')'。 - kludg
2个回答

9
编译器错误是由于编译器拒绝在最终赋值的左侧括号外部。实际上,您的代码类似于以下内容:
type
  TMyRecord = record
  end;

procedure Foo;
var
  rec1, rec2: TMyRecord;
begin
  rec1 := rec2;   // compiles
  (rec1) := rec2; // E2064 Left side cannot be assigned to
end;

用这种简化的方式写出来,可以使问题更加突出。

我不确定编译器为什么会拒绝这些括号。我怀疑语言的正式语法使得你的左侧无效。Serg在评论中提供了一个合理的解释,即(...)是一个表达式,而表达式作为赋值语句的左侧是无效的。我倾向于相信这是准确的。

无论如何,修复你的代码很简单。而不是

(PMinMaxInfo(Msg.LParam)^) := MinMaxInfo;

PMinMaxInfo(Msg.LParam)^ := MinMaxInfo;

请注意,您不需要复制记录、修改它,然后再将其复制回来。一旦您将LParam转换为指向记录的指针,就可以直接修改该记录。

我会这样做:

procedure TMydlg.WMGetMinMaxInfo(var Msg:TMessage);
var
  pmmi: PMinMaxInfo;
begin
  inherited;
  pmmi := PMinMaxInfo(Msg.LParam);
  pmmi.ptMinTrackSize.X := MinWidth;
  pmmi.ptMinTrackSize.Y := MinHeight;
  pmmi.ptMaxTrackSize.X := MinWidth;
end;

在这种情况下,我省略了^指针解引用运算符,因为它是可选的。如果您愿意,您可以这样编写赋值语句:

pmmi^.ptMinTrackSize.X := MinWidth;
pmmi^.ptMinTrackSize.Y := MinHeight;
pmmi^.ptMaxTrackSize.X := MinWidth;

我认为这不是编译器的错误;括号中的变量是一个表达式,而表达式不能在赋值语句的左侧。这不是特定于记录类型的。 - kludg
@user246408:是的,我也是这么想的。如果我没记错的话,“Not an LVal”就是表达式。 - MartynA

-3

这是因为你没有使用记录类型而是使用了指针类型。

将你的代码改成这样:

procedure TMydlg.WMGetMinMaxInfo(var Msg: TMessage);
begin
  with pMinMaxInfo(Msg.LParam)^ do
  begin    
    ptMinTrackSize.X := MinWidth;
    ptMinTrackSize.Y := MinHeight;
    ptMaxTrackSize.X := MinWidth;      
  end;
end;

我创建了一个虚拟测试程序:

procedure TForm9.FormCreate(Sender: TObject);
var
  MinMaxInfo: pMinMaxInfo;
  Msg: TMessage;
begin
  MinMaxInfo := new(pMinMaxInfo);
  Msg.LParam := integer(MinMaxInfo);
  WMGetMinMaxInfo(Msg);
  Assert( pMinMaxInfo(Msg.LParam)^.ptMinTrackSize.X = 10);
end;

procedure TForm9.WMGetMinMaxInfo(var Msg: TMessage);
var
  MinMaxInfo: pMinMaxInfo;
begin
  MinMaxInfo := pMinMaxInfo(Msg.LParam);

  with MinMaxInfo^ do
  begin

    ptMinTrackSize.X := 10;
    ptMinTrackSize.Y := 10;
    ptMaxTrackSize.X := 10;
  end;    
end;

1
这是因为您没有使用记录类型而是指针类型。不,不是这样的。 - David Heffernan
1
也许你应该仔细阅读我的回答,看看我没有复制你写的内容。 - David Heffernan
2
编写代码的方法并不多。此外,在你编辑之前,我已经开始写我的答案了。当时你还有一个本质上是 ptr^ := ptr^ 的任务。有趣的是理解编译器错误,这是你忽略了的。所以,我认为我写我的答案是可以的。 - David Heffernan
2
@DavidHeffernan 我很喜欢阅读你的回答,因为你不仅回答了问题,还解释了各种情况下发生的事情。对我来说,像你这样的回答让我学到了很多,因为它有助于更好地理解实际问题以及可以采取哪些方法来解决它们。 - Craig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接