Results 1 to 14 of 14

Thread: Dynamische array kopieren in ander Form

  1. #1
    Senior Member Henk Schreij's Avatar
    Join Date
    Sep 2002
    Location
    Heino (Raalte)
    Posts
    1,465

    Dynamische array kopieren in ander Form

    Ik heb een dynamische array met strings waarin ik de invullingen op een Form bewaar. Dat werk prima binnen een Form (zo kan ik gegevens van broer/zus snel kopieren). Maar naar een ander Form kopieren wil niet.
    Wat code (ingedikt tot zijn essentie):

    Kopieren binnen een Form van array A naar array B:
    Code:
      public
        A, B: array of string;
      end;
    
    var
      Form2: TForm2;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm2.Button1Click(Sender: TObject); //vul A
      procedure Bij(sNw: string);{sub}
      begin
        SetLength(A, Length(A) +1);
        A[Length(A)-1]:= sNw;
      end;//sub
    begin
     Bij('een');
     Bij('twee');
    end;
    
    procedure TForm2.Button2Click(Sender: TObject);//kopieer en toon
    var i: Integer;
    begin
     B:= Copy(A);
     for i:= 0 to (Length(B)-1) do
      Memo1.Lines.Add(B[i]);
    end;
    Voorgaande werkt prima binnen (sub-)Form 2

    Maar als ik in (sub-)Form2 de array A vul en hem op dezelfde manier in (het aanroepende) Form1 probeer te kopieren krijg ik een lege string B.

    De gebruikte code in Form1:
    Code:
      public
        { Public declarations }
        B: array of string;
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    uses Unit2;
    
    {$R *.dfm}
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
     Form2:= TForm2.Create(Application);
     with Form2 do begin
      ShowModal;
      B:= Copy(A);
      Release;
     end;
    end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    var i: Integer;
    begin
     for i:= 0 to (Length(B)-1) do
      Memo1.Lines.Add(B[i]);
    end;
    Is het zo dat je dynamische arrays alleen binnen een Form kunt kopieren?
    En waarom niet van de ene naar het andere Form?
    Want als ik hetzelfde met een stringlist doe dan gaat het wel goed.

    Of is er iets wat ik over het hoofd zie, of fout doe.

  2. #2
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    De with-valkuil?
    Code:
     with Form2 do begin
      ShowModal;
      B:= Copy(A);
      Release;
     end;
    Deze B is de B van TForm2, niet die van TForm1.
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  3. #3
    Senior Member Henk Schreij's Avatar
    Join Date
    Sep 2002
    Location
    Heino (Raalte)
    Posts
    1,465
    Ja, in de with valkuil gestonken.

    Maar daarmee is het echte probleem pas naar voren gekomen:
    De code in Form1 wordt nu:
    Code:
      public
        { Public declarations }
        B: array of string;
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    uses Unit2;
    
    {$R *.dfm}
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
     Form2:= TForm2.Create(Application);
     with Form2 do begin
      ShowModal;
      Form1.B:= Copy(A);
      Release;
     end;
    end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    var i: Integer;
    begin
     for i:= 0 to (Length(B)-1) do
      Memo1.Lines.Add(B[i]);
    end;
    Nu krijg ik de foutmelding:
    incompatible types
    bij de regel:
    Form1.B:= Copy(A);
    Raar genoeg denkt die nu dat "array of string" in Form1 niet van hetzelfde type is als "array of string" in Form2.
    Terwijl dezelfde code binnen een Form wel werkt.

  4. #4
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    Dat klopt. "array of String" is een zogenaamd samengesteld type (niet standaard) en omdat deze op twee verschillende plaatsen staat gedeclareerd zijn deze niet aan elkaar compatible. Maak er een gezamenlijk type van:
    Code:
    type
      TStringArray = array of String;
    Opm: deze declaratie mag dus maar in één unit staan.
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  5. #5
    Senior Member Henk Schreij's Avatar
    Join Date
    Sep 2002
    Location
    Heino (Raalte)
    Posts
    1,465
    Quote Originally Posted by NGLN View Post
    Maak er een gezamenlijk type van: type TStringArray = array of String;
    Opm: deze declaratie mag dus maar in één unit staan.
    In welke unit moet ik hem zetten?
    Als ik in Form2 declareer kent hij hem niet in Form1. En andersom.
    Moet ik een datamodule gebruiken en die in beide aan de uses toevoegen?

  6. #6
    Een derde unit die beide units moeten usen
    DeX 3 Delphi := The ease of VB with the power of C; Zoekt en gij zult vinden

  7. #7
    Senior Member Henk Schreij's Avatar
    Join Date
    Sep 2002
    Location
    Heino (Raalte)
    Posts
    1,465
    OK.
    Ik heb een DataModule die door beide geused wordt.
    Daarin zet ik de type declaratie.
    Kijken of het werkt

  8. #8
    Senior Member Henk Schreij's Avatar
    Join Date
    Sep 2002
    Location
    Heino (Raalte)
    Posts
    1,465
    Het werkt, maar ..
    Ik moest in Unit1 en Unit2 de DataModule wel in de Interface uses bovenin zetten, ipv in het Implementation deel.

    Dat komt natuurlijk doordat ik de Type ook in de Interface gedeclareerd had:
    Code:
    unit Unit3;
    
    interface
    
    uses
      SysUtils, Classes;
    type
      TStringArray = array of string;
    type
      TDataModule3 = class(TDataModule)
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    Eens kijken of ik daar nog wat aan kan doen.

  9. #9
    Senior Member Henk Schreij's Avatar
    Join Date
    Sep 2002
    Location
    Heino (Raalte)
    Posts
    1,465
    Nou daar is niet zo wat aan te doen.
    Logisch ook wel dat de type declaratie in het interface deel moet staan.

    Of is er toch nog iets te verzinnen dat ik de uses van mijn Datamodule in het Implementation deel van Unit1 en Unit2 kan blijven houden?

  10. #10
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Daar hoef je niet per sé een TDataModule voor te gebruiken: een simpele unit is voldoende.
    Zelf gebruik ik vaak zo'n unit waar ook gewone procedures en functies in staan voor algemeen
    gebruik (dus geen class-functies en -procedures):
    Code:
    Unit MiscUnit;
    
    Interface
    
    Uses
      Windows, Messages, Classes, SysUtils;
    
    Type
      TStringArray = Array Of String;
      TMyType      = (mtOne, mtTwo, mtThree);
      TMyTypes     = Set Of TMyType;
      TProgressUpdateEvent = Procedure(Sender    : TObject;
                                       Progress  : Byte;
                                       Var Abort : Boolean) Of Object;
    
    Function GetTempName(Prefix : String) : String;
    ...
    
    Implementation
    
    ...
    
    End.
    Zolang je een bepaald type gebruikt in het interface-gedeelte kun je zo'n unit nooit onder
    de implentation zetten...

    [EDIT]
    Is zie eigenlijk het probleem niet... wat is er op tegen om zo'n unit in het interface gedeelte
    te zetten?
    TMemoryLeak.Create(Nil);

  11. #11
    Senior Member Henk Schreij's Avatar
    Join Date
    Sep 2002
    Location
    Heino (Raalte)
    Posts
    1,465
    Is zie eigenlijk het probleem niet... wat is er op tegen om zo'n unit in het interface gedeelte te zetten?
    Om eerlijk te zijn niets.
    Maar ik heb al mijn units geused (wat een lelijk woord) in het Implementation deel, dus ook de DataModule. Vandaar.
    Maar ik ga eens kijken, naar aanleiding van je opmerking, of ik de Type declaratie niet beter in mijn Bibliotheek unit kan zetten. Dat is logischer.
    Op een of andere manier vind ik het ook mooier om de Bib unit in mijn Interface Uses te zetten.

  12. #12
    Zo'n type declaratie is inderdaad typisch iets dat je wel in een aparte library unit kunt zetten.

    Overigens ben ik (na lang anders beweerd te hebben!) inmiddels overtuigd dat het beter is om alle units in het interface gedeelte te usen. (Ge??sed is vast met een umlaut )
    De reden hiervoor is dat het beter is om geen circulaire referentie tussen units te hebben. Als unit1 verwijst naar unit2 én andersom, dan is dat eigenlijk altijd het signaal dat je je programma niet in de juiste structuur hebt opgedeeld.
    Omdat Delphi wel toestaat dat je unit1 uset (d?át is pas lelijk) in de interface van unit2 en unit2 vervolgens in de implementation van unit1, kun je zo dus eigenlijk ongemerkt een circulaire referentie maken, waar je later nog wel eens flink last van kunt krijgen.

    Door alle units in het interface gedeelte te plaatsen, zal de compiler protesteren bij circulaire referenties. Zodoende kun je dus al in een vroeg stadium ontdekken dat er een fout in je ontwerp zit (of in de uitvoering daarvan).
    1+1=b

  13. #13
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Natuurlijk zit dit type al sinds D6 of zo in unit types als
    Code:
    Type
      TStringDynArray       = array of string;
    Net als alle andere dynamische arrays van basistypes.

    Goleztrol: Jouw verhaal wat circulaire referenties betreft snap ik niet. Je kan ook units circulair referencen in interface. (a used B en b used a in interface).

    Het verplaatsen van uses naar de implementatie is een heel belangrijke feature, met name in factory patterns:

    - hoofdunit abstract definitie basis type
    - andere units afgeleide type.
    - hoofdunit implementatie importeert de bekende units, en kan in er mee werken.

  14. #14
    Senior Member Henk Schreij's Avatar
    Join Date
    Sep 2002
    Location
    Heino (Raalte)
    Posts
    1,465
    Inderdaad.
    Aan de uses toegevoegd: Types
    En dan heb ik opeens beschikking over:
    Code:
    type
    TIntegerDynArray      = array of Integer; 
    TCardinalDynArray     = array of Cardinal;  
    TWordDynArray         = array of Word;  
    TSmallIntDynArray     = array of SmallInt;  
    TByteDynArray         = array of Byte;  
    TShortIntDynArray     = array of ShortInt;
    TInt64DynArray        = array of Int64;  
    TLongWordDynArray     = array of LongWord;  
    TSingleDynArray       = array of Single;  
    TDoubleDynArray       = array of Double;  
    TBooleanDynArray      = array of Boolean;  
    TStringDynArray       = array of string;  
    TWideStringDynArray   = array of WideString;
    Markov (en ook de anderen) bedankt

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •