Avatar billede hugopedersen Nybegynder
24. december 2008 - 14:52 Der er 16 kommentarer og
1 løsning

Ændre caption på form

Jeg sidder med en form i Delphi 2009 hvor jeg gerne vil ændre Caption i fobindelse med nogle valg der foretages.
Men af en eller anden grund vil den bare ikke ændre sig.
Jeg skriver  frmRemoteControl.Caption := 'Remotecontrol : ' + strCommand_String;

Er der nogle properties jeg kan have sat der forhindrer dette?
Avatar billede kroning Nybegynder
24. december 2008 - 14:59 #1
Nu har jeg ikke D2009 men det burde vel virke ligesom i D7.
Er du sikker på at koden bliver kaldt, prøv at indsætte et breakpoint og check værdien af strCommand_String ved break.
Avatar billede hugopedersen Nybegynder
24. december 2008 - 15:11 #2
Jeg har sat en ShowMessage ind efter følgende og den viser den rigtige tekst.
Avatar billede kroning Nybegynder
24. december 2008 - 15:57 #3
Det er jo mystisk så.
Avatar billede psycosoft-funware Nybegynder
24. december 2008 - 17:04 #4
det virker da meget underligt, den stump kode skulle virke...

ved godt det lyder dumt, men:
har du prøvet bare at skrive: frmRemoteControl.Caption := strCommand_String;
og se om det giver noget udslag?

og glædelig jul, her mellem julepakker, flæskesteg og and :)

./psycosoft-funware :)
Avatar billede mortvader Nybegynder
25. december 2008 - 11:31 #5
ER det den rigtige form du referer til? frmRemoteControl?
Avatar billede hugopedersen Nybegynder
25. december 2008 - 13:23 #6
Det er den rigtige form ja.

Jeg har nu ændret min kode til

Caption := 'Remotecontrol : ' + strCommand_String;

Og så virker det!!  Det synes jeg er meget underligt.
Avatar billede mortvader Nybegynder
25. december 2008 - 13:43 #7
ja det lyder da lidt crazy..
Avatar billede psycosoft-funware Nybegynder
25. december 2008 - 15:05 #8
ja det vil jeg også mene...

normalt skulle delphi være ligeglad med om man refere til caption endten via Form1.Caption eller Caption.
men jeg skal ikke kunne sige om de har ændret en del på delphi's core i den retning. jeg holder mig stadig til Delphi 7 og Lazarus

./psycosoft-funware :)
Avatar billede hugopedersen Nybegynder
26. december 2008 - 17:43 #9
Jeg skal ikke kunne sige det, men for at gøre forvirringen større så har jeg en anden form i min application hvor det virker som jeg først beskrev.

Kan det mon være noget med at formen først oprettes i det øjeblik jeg skal bruge den - altså ikke creates i dpr filen.

PS: Hvad er Lazarus for en størrelse?
Avatar billede psycosoft-funware Nybegynder
26. december 2008 - 19:19 #10
nu tror jeg der er en klokke der ringer.... prøver du at skrive til formens caption property før du har created den? i så fald så kan delphi godt drille hvad det angår.

Lazarus er et Open Source udviklingsmiljø der liger meget delphi men benytter Free Pascal Compileren som er en åben object pascal compiler. fordelen ved lazarus er at du kan lave et program som du kan kompliere til mange forskellige platforme fx Linux, Windows, Mac OS X, windows Mobile og forskellige processore 32 og 64 bit intel, 32 og 64 bit PowerPC eller ARM bare for at nævne et par stykker. den klart store fordel ved lazarus er at du kun behøves at skrive koden een gang og der efter vælge hvilke platforme dit program skal køre under og kompliere det. det giver langt større flexibillitet :)

www.lazarus.freepascal.org

./psycosoft-funware :)
Avatar billede a_nor Nybegynder
27. december 2008 - 11:21 #11
Hvis du (i D7) creater Form1 flere gange, har du kun adgang til den sidst oprettede
gennem objektangivelsen 'form1.xxx'. Hvis du istedet anvender 'self.xxx', kan du have flere instanser af den samme form. 

Det er også derfor din ændrede kode virker. Her er 'self' uderforstået foran Caption.

Du kan også prøve fra 'hovedprogrammet' - Der hvor du creater 'Form1' at udføre

Form1.visible := true; eller
Form1.show;

Du kan gennemgå alle dine "Forms" med kode som

i := 0 to  screen.formCount-1;
screen.Forms[i].Caption


mvh. Anders
Avatar billede hrc Mester
27. december 2008 - 18:22 #12
Du skal aldrig bruge den globale instansvariabel (her frmRemoteControl) inde i formen. Det er en kilde til meget ondt. Inde i klassen (TfrmRemoteContro) refererer man til instansen vha. self.

I dette tilfælde er den ikke initialiseret og så prøver du at finde caption i en form-instans der ikke er oprettet (og så derfor sikkert er nil, hvorved den fejler.

Det første man egentlig bør gøre når man opretter en ny form er, at slette ovennævnte globale variabel. Det hører ind under ordentlige programmeringsrutiner.
Avatar billede hugopedersen Nybegynder
27. december 2008 - 18:56 #13
Hvis jeg forstår dig ret så skal jeg slette
Var
  frmRemoteControl : TfrmRemoteControl;

Og så skal jeg skrive Self.Caption := 'Remotecontrol : ' + strCommand_String;
(det er som i VBA hvor det bare hedder Me)
Avatar billede a_nor Nybegynder
27. december 2008 - 19:58 #14
Prøv at køre følgende

Din variabelinstans skal eksistere inden du creater:

var frmRemoteControl = TfrmRemoteControl;

begin
frmRemoteControl := TfrmRemoteControl.create(application);
frmRemotecontrol.show;
frmRemotecontrol.caption := 'Create1';

frmRemoteControl := TfrmRemoteControl.create(application);
// du taber her adgangen det første objekt gennem instansvariablen frmRemoteControl
// men du kan stadig gå til det via 'screen'.... som eksemplificeret ovenfor.
frmRemotecontrol.caption := 'Create2';
// vil ikke blive vist da den nye form stadig ikke er vist (show ikke udført)
end;
Avatar billede hrc Mester
27. december 2008 - 21:40 #15
hugo: det er ret forstået. Den globale variabel er en plage, især fordi mange gør som du, bruger den inde i klassen da de ikke kender eksistensen af "self" (a.k.a. "this" for C++ et al).
Jeg gør meget ud af at undgå variablen. Hvis jeg f.eks. har en dialog hvor parametre til en QuickReport sættes, så lader jeg ikke QReport-formen snage i formen, men sender en (hjemmelavet) TParamData - klasse over. Den indeholder alle parametre som rapporten skal bruge. På den måde opnår jeg, at begge de to forme behøver kende hinanden. Parameterformen kender rapporten, men rapporten kender ikke formen der kalder den.

Endelig benytter jeg meget at modificere constructoren (her, i quickreport formen):

Laver en parameterunit som begge forme linker til (parameterformen linker i implementation-delen, mens rapportformen gør det under interface)

unit UParamData;

type
  TParamData = class
  private
    fFraDato: TDateTime;
    fTilDato: TDateTime;
    procedure SetDateTime(const Index: integer; const aValue: TDateTime);
  public
    constructor Create; // Initialisér attributter
    property FraDato: TDateTime index 0 read fFraDato write SetDateTime;
    property TilDato: TDateTime index 1 read fTilDato write SetDateTime;
    function IsValid: boolean;
  end;

implementation

constructor TParamData.Create;
begin
  inherited Create;
  fFraDato := 0.0;
  fTilDato := 0.0;
end;

// Demonstrerer brugen af Index'et i property-listen. Det smarteste er at bruge
// konstanter til indekserne
procedure TParamData.SetDateTime(const Index: integer; const aValue: TDateTime);
begin
  case Index of
    0: fFraDato := DateOf(aValue);
    1: fTilDato := DateOf(aValue);
  end;
end;

function TParamdata.IsValid: boolean;
begin
  result := (fFraDato <> 0) and (fTilDato <> 0) and (fFraDato <= fTilDato);
end;

// Lidt af parameterformen har vi her

implementation

uses
  UParamData;

procedure TfrmRapportParams.DoReport(Sender: TObject);
var
  ParamData: TParamData;
  frmQRapportForm: TfrmQRapportForm; // Kun lokale variable!!
begin
  ParamData := TParamData.Create;
  ParamData.FraDato := dtpFraDato.Date;
  ParamData.TilDato := dtpTilDato.Date;

  // .. osv

  frmQRapportForm := TfrmQRapportForm.Create(self,ParamData);
  try
    if Sender = btnPrint then
      frmQRapportForm.QuickRep.Print
    else
      frmQRapportForm.QuickRep.Prewiev;
  finally
    frmQRapportForm.Release; // eller free. Er i tvivl når det gælder QReport
    ParamData.Free;
  end;
end;

// I Rapport-formen har jeg modificeret constructoren (lad være med at bruge OnCreate
// sammen med sådan en konstruktion, for det virker ikke):

interface

uses SysUtils, Classes, UParamData ...;

type
  TQuickreportForm = class(TForm)
  private
    fParamData: TParamData;
  public
    constructor Create(aOwner: TComponent; aParamData: TParamData); reintroduce;
  end;

implementation

procedure TQuickRepForm.Create(aOwner: TComponent; aParamData: TParamData);
begin
  inherited Create(aOwner);
  fParamData := aParamData; // Gem "pointeren" til parameterklassen
end;

---------- EOE (End of Example) ----------

Det ser måske lidt omstændigt ud, men koden er sikker og stringent. Jeg har ikke fundet pænere løsning og bruger den på rygradden. Det er meget let at tilføje nye parametre. Desuden kan man validere og smukkesere data (her laver jeg f.eks. en TDateTime om til en TDate).
Avatar billede hugopedersen Nybegynder
20. januar 2009 - 14:57 #16
Måske nogle svar så jeg kan lukke.
Avatar billede a_nor Nybegynder
20. januar 2009 - 17:01 #17
Tak,  Giv point efter hvor nyttigt det var  :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester