64 位标签属性被误用于存储对象引用

问题描述 投票:0回答:1

我正在将 32 位代码转换为 64 位代码,并且

.Tag
属性有很多用途。
其中许多仅用于存储整数值,然后像
MyInteger := Component.Tag
这样的赋值,虽然形式上是错误的(可能导致范围检查错误),但仍将继续工作。由于这些分配没有编译器提示/警告,我决定离开它们。是我们自己的代码首先将整数放入标签中......

但在其他地方,指向对象的指针被放置在

.Tag
属性中,例如像这样:

procedure IntervalWeergaveSubMenuToevoegen( AParentMenu : TMenuItem; ACaption : String; AInterval : TcxPivotGridGroupInterval; AField : TcxDBPivotGridField );
var lSubMenuItem : TMenuItem;
begin
  lSubMenuItem := TMenuItem.Create(Self);
  lSubMenuItem.Caption := ACaption;
  lSubMenuItem.ImageIndex := Integer(AInterval);  // (Mis-)use ImageIndex property to store interval
  lSubMenuItem.Tag := Integer(AField);            // (Mis-)use Tag property to store reference to field  THIS ONE!
  lSubMenuItem.GroupIndex := 99;               
  lSubMenuItem.RadioItem := True;
  lSubMenuItem.Checked := (AField.GroupInterval=AInterval);
  lSubMenuItem.OnClick := PopupSubMenuWeergaveClick;
  AParentMenu.Add(lSubMenuItem);
end;

然后

PopupSubMenuWeergaveClick
,接收一个
TMenuItem
作为它的
Sender
,将
.Tag
转换回
TcxDBPivotGridField

procedure TDialoogDynRapport.PopupSubMenuWeergaveClick(Sender: TObject);
begin
  inherited;
  ExcelPivotGrid.BeginUpdate;
  try                                  // TcxDBPivotGridField reference was put in MenuItem.Tag
    TcxDBPivotGridField(TMenuItem(Sender).Tag).GroupInterval := TcxPivotGridGroupInterval( TMenuItem(Sender).ImageIndex );
  finally
    ExcelPivotGrid.EndUpdate;
  end;
end;

不是很好,我知道。

我看到两条出路:

  • 例程
    IntervalWeergaveSubMenuToevoegen
    包含在
    TDialoogDynRapport
    方法中,所以我可以给
    TDialoogDynRapport
    一个额外的私有结构来存储
    TMenuItem
    TcxDBPivotGridField
    之间的关联。像这个
  • 只需将
    Integer(AField)
    分配给另一个演员。毕竟
    .Tag
    现在是8个字节,
    TcxDBPivotGridField
  • 的地址也是

推荐什么?
Delphi 11.3,没有多线程,也应该在 Win32 中继续工作。

delphi 64-bit delphi-11-alexandria
1个回答
0
投票

你真的根本不需要“标签”属性。

有一种更好的方法可以将 tMenuitem 映射到一个或多个对象。您可以简单地使用使用 tMenuitem 作为键的 tDictionary(= 快速查找引擎)。

这是一个快速而肮脏的例子:

Uses system.generics.collections, ..... ;

var fieldlookup: tDictionary <tMenuitem, TcxDBPivotGridField>;
    intervalLookup: tDictionary <tMenuitem, TcxPivotGridGroupInterval>;

Procedure initialization;
begin
 fieldlookup:=tDictionary <tMenuitem, TcxDBPivotGridField>.Create;
 intervallookup:=tDictionary <tMenuitem, TcxPivotGridGroupInterval>.Create;
end;

Procedure IntervalWeergaveSubMenuToevoegen( 
      AParentMenu : TMenuItem; 
      ACaption : String; 
      AInterval : TcxPivotGridGroupInterval; 
      AField : TcxDBPivotGridField);
var lSubMenuItem : TMenuItem;
begin
     lSubMenuItem := TMenuItem.Create(Self);
     fieldlookup.add(lSubMenuItem, AField);
     intervallookup.add(lSubMenuItem, AInterval);         
     lSubMenuItem.Caption := ACaption; 
     lSubMenuItem.GroupIndex := 99;               
     lSubMenuItem.RadioItem := True;
     lSubMenuItem.Checked := (AField.GroupInterval=AInterval);
     lSubMenuItem.OnClick := PopupSubMenuWeergaveClick;
     AParentMenu.Add(lSubMenuItem);              
end;




procedure TDialoogDynRapport.PopupSubMenuWeergaveClick(
          Sender: TObject);
Var Field:TcxDBPivotGridField; Interval:TcxPivotGridGroupInterval;
begin
  if (fieldlookup.TryGetValue(sender as tmenuitem, Field) and 
  intervallookup.Trygetvalue(sender as tmenuitem, Interval)) then
  begin
   {Field and interval are now known. Insert rest of event handler code here}
  end;
end;
© www.soinside.com 2019 - 2024. All rights reserved.