Jedna procedura do różnych rekordów

0

Witam

Poniższy obraz ułatwi wyjaśnienie.
user image

Mam główną formę "FormA", która zawiera procedurę przeszukującą węzły (wpisy) w VirtualListView.

//FormA
public
  procedure Szukaj(const VST: TVirtualStringTree; const Edit: TEdit; Data: TTreeData);

Mam też formy podrzędne, Form1...Form4, z których to wywołuję przeszukiwanie, np.: w Form1 (każda forma podrzędna ma swój rekord odnoszący się do VirtualStringTree) odwołuję się do procedury z FormA, która to po parametrach ma szukać w VST_1 (VirtualStringTree) z rekordem z formy Form1.

PTreeData1 = ^TTreeData1;
  TTreeData1 = record
   //...
  end;

//wywołanie szukania
var
 Data: TTreeData1;
begin
 FormA.Szukaj(VST_1, Edit_1, Data);
end;

Problem w tym, że nie mogę odwołać się do TTreeData, skoro każda forma (unit) ma swój rekord, a nie chce ustalać procedury szukającej dla każdej formy z osobna.

Jak to rozwiązać ?

1

jeśli masz wspólną procedurę to przynajmniej część danych w TTreDatax musi być wspólna. We wszystkich tych rekordach wyodrębnij tą część wspólną na początku i poukładaj je wszędzie w dokładnie takiej samej kolejności. Następnie stwórz typ rekordowy z tylko tą wspólną częścią.

type
  TTreeData_form1 = record
    //wspólne
    aa: Taa;
    bb: Tbb;
    cc: Tcc;
    //pozostałe
    xy: TXyz
  end;

  TTreeData_form2 = record
    //wspólne
    aa: Taa;
    bb: Tbb;
    cc: Tcc;
    //pozostałe
    qwe: TQWE
    jh: TAas;
  end;

  TTreeData_form3 = record
    //wspólne
    aa: Taa;
    bb: Tbb;
    cc: Tcc;
    //pozostałe
    dupa; TDupa;
  end;

  TTreeData_wspolny = record
    //wspólne
    aa: Taa;
    bb: Tbb;
    cc: Tcc;
  end;

zmień procedurę Szukaj na

procedure Szukaj(const VST: TVirtualStringTree; const Edit: TEdit; Data: TTreeData_wspolny);

i jak będziesz chciał wyszukać to

var
 Data: TTreeData1;
begin
 FormA.Szukaj(VST_1, Edit_1, TTreeData_wspolny(Data));
end;

to coś na wzór dziedziczenia tylko, że tutaj kompilator nie pilnuje czy Data to na pewno TTreDatax, czy odpowiednie dane są w odpowiednim miejscu pamięci, czy typy się zgadzają, itp.

0

Dzięki Misiekd za kolejną pomoc :)

Nie wiem czy to dobre rozwiązanie, ale pomyślałem też o czymś takim: W procedurze szukającej posiadam odwołania do wszystkich rekordów i odnoszę się do nich na podstawie IdxRekord.

Chyba tak też można ? :)

//Form1
PTreeData1 = ^TTreeData1;
  TTreeData1 = record
    FCaption: string;
    FSubItem: string;
  end;

//Form2
PTreeData2 = ^TTreeData2;
  TTreeData2 = record
   FCaption: string;
  end;

//Procedura szukająca - schemat
procedure TFormA.Szukaj(const VST: TVirtualStringTree; Edit: TEdit; const IdxRekord: Byte); 
var
  Data1: PTreeData1;
  Data2: PTreeData1;
  //...
begin
 //...
 
 //gdzieś poniżej odwołanie do rekordu
 case IdxRekord of
    1: begin
         Data1 := VST.GetNodeData(Node);
         //ShowMessage(Data1.FCaption +#10+ Data1.FSubItem);
        end;
    2: begin
         Data2 := VST.GetNodeData(Node);
         //ShowMessage(Data2.FCaption);
        end;
 end;
end;

//Wywołanie Form1
begin
 FormA.Szukaj(VST_1, Edit_Tresc, 1);
end;

//Wywołanie Form2
begin
 FormA.Szukaj(VST_2, Edit_Tresc, 2);
end;
0

no ale jeśli w tej procedurze i tak masz case to nie widzę sensu robienia takich myków - napisz sobie trzy procedury, nazwij je tak samo tylko daj im różne typy dla TreeData i owerload na końcu i będzie to samo tylko ładniej :p

0

Czy nie prościej do procedury przekazać oprócz rekordu jeszcze adres funkcji porównującej?

0

Przecież o to chodzi, że każdy rekord jest inny, więc przekazanie rekordu jest kłopotliwe, mimo zastosowania wspólnych cech w rekordzie zbiorczym (nie zawsze tak można)... a jakiś przykład z "funkcją porównującą", bo pierwsze słyszę ?

0

Coś w tym guście:

  TItemDataKind=(idkA,idkB,idkC);
  PItemData=^TItemData;
  TItemData=record
    Kind:TItemDataKind;
    case TItemDataKind of
      idkA: ( Ai:Integer; Aj:Integer; );
      idkB: ( Bd:Double; );
      idkC: ( Cc:array[0..6]of Char; );
  end;
  TCmpFunc=function(VST:TVirtualStringTree;Node:PVirtualNode;const Rec:TItemData):Boolean;

function CpmA(VST:TVirtualStringTree;Node:PVirtualNode;const Rec:TItemData):Boolean;
var tmp:PItemData;
begin
  tmp:=VST.GetNodeData(Node);
  if tmp^.Kind=idkA then
  begin
    Result:=(tmp^.Ai=Rec.Ai)and(tmp^.Aj=Rec.Aj);
  end
  else Result:=false;
end;

function CpmB(VST:TVirtualStringTree;Node:PVirtualNode;const Rec:TItemData):Boolean;
var tmp:PItemData;
begin
  tmp:=VST.GetNodeData(Node);
  if tmp^.Kind=idkB then
  begin
    Result:=(tmp^.Bd=Rec.Bd);
  end
  else Result:=false;
end;

function TForm1.Szukaj(VST:TVirtualStringTree;Cmp:TCmpFunc;const Rec:TItemData):PVirtualNode;
var Node:PVirtualNode;
begin
  Node:=VST.GetFirst();
  while Node<>nil do
  begin
    if Cmp(VST,Node,Rec) then
    begin
      Result:=Node;
      Exit;
    end;
    Node:=VST.GetNext(Node);
  end;
  Result:=nil;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Rec:TItemData;
var Node:PVirtualNode;
begin
  Rec.Kind:=idkA;
  Rec.Ai:=1;
  Rec.Aj:=2;
  Node:=Szukaj(VirtualStringTree1,CpmA,Rec);
  if Node<>nil then
  begin

  end;
end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1