Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - TObject übergeben


fuggaz - Di 17.03.09 20:24
Titel: TObject übergeben
Hi,

Ich möchte etwas wahlweise auf ein Stringgrid "drucken" oder ausdrucken.
Dafür dachte ich mir übergebe ich ein TObject. Entweder stringgridname oder printer.
Allerdings klappt das gar nicht:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.test(Sender:TObject);
begin
with sender do
  showmessage(inttostr(canvas.font.size));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
printer.Canvas.Font.Size:=20;
test(printer);
end;


Was mache ich falsch?

Anscheinend weiß Delphi nicht was für ein Object das ist.
Wie kann ich das Delphi mitteilen?

Moderiert von user profile iconGausi: Code- durch Delphi-Tags ersetzt


Kha - Di 17.03.09 20:33

Das wäre quasi Duck Typing, Delphi ist aber statisch typisiert. Aber würde es nicht reichen, von beiden Klassen jeweils nur die Canvas zu übergeben? Dann kannst du den Parameter wieder als TCanvas statisch typisieren.


Boldar - Di 17.03.09 20:33


Delphi-Quelltext
1:
2:
3:
4:
case (sender is Tstringgrid) of
true: (sender as Tstringgrid).Canvas.font.size;
false: (Sender as TPrinter).Canvas.font.size;
end;


oder vielleicht auch


Delphi-Quelltext
1:
2:
3:
4:
5:
type Tdummycontrol = Tcontrol;

...

sender as Tdummycontrol
??


Edith sagt: ups, zu spät...


fuggaz - Di 17.03.09 20:50

Hm ich verstehe im Moment nicht genau wie ihr das meint.

Hier mal der Quelltext, der für ein Stringgrid und den Drucker gelten soll:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
var
  i,j,irow,breite:integer;
  rrect:TRect;
  x,y:integer;
  textmitte,sglrand:single;
  drh,strw :integer;
    //drh:DefaultRowHeight
    //strw:STRinggridWidth
  drucken:boolean;
begin

druckAlleFuellen;
if drucken then
  if not (printdialog1.Execute) then exit;
drucken:=true;
drh:=18;
strw:=Stringgrid1.Width;
irow:=0;
if drucken then
  begin
  breite:=printer.pagewidth;
  if printer.Orientation=poLandscape then  //Querformat
    drh:=round(drh*printer.PageHeight/strw)
  else //if printer.Orientation=poPortrait then :Hochformat
    drh:=round(drh*printer.PageHeight/(strw*sqrt(2)));
  end
else breite:=strw;

with printer do
  begin
  sglrand:=25*breite/strw;
  textmitte:=(drh-canvas.TextHeight('A')) div 2;
  if drucken then printer.begindoc;
  canvas.Font.Color:=clblack;
  for i:=0 to 0//length(Lehrer)-1 do
    begin
      //Überschrift
      rrect.Left:=round(sglrand);
      rrect.Top:=round(sglrand);
      rrect.Right:=round(breite-sglrand);
      rrect.Bottom:=round(drh+sglrand);
      x:=round((breite-canvas.TextWidth(d.cells[0,irow]))/2);
      y:=round(textmitte+sglrand);
      canvas.TextRect(rrect,x,y,d.cells[0,irow]);
      inc(irow);
    end;
  if drucken then printer.enddoc;
 end;
end;


Moderiert von user profile iconGausi: Code- durch Delphi-Tags ersetzt


fuggaz - Mi 18.03.09 15:11


Delphi-Quelltext
1:
2:
3:
stringgrid2.canvas.font.size:=20;
showmessage(inttostr(tstringgrid(sender).Canvas.Font.size));
showmessage(inttostr(tstringgrid(sender).Canvas.Font.size));


Das Ergebnis ist unterschiedlich~~
Das erste ist richtig und das zweite zeigt was falsches an...


Kann man mein Problem vllt. mit Zeigern lösen?
Über google habe ich noch was über property gelesen. Habe das aber überhaupt nicht verstanden~~


Boldar - Mi 18.03.09 16:49

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
case (sender is Tstringgrid) of
true: (sender as Tstringgrid).Canvas.font.size;
false: (Sender as TPrinter).Canvas.font.size;
end;


oder vielleicht auch


Delphi-Quelltext
1:
2:
3:
4:
5:
type Tdummycontrol = Tcontrol;

...

sender as Tdummycontrol


fuggaz - Mi 18.03.09 21:31

Zitat:

Hm ich verstehe im Moment nicht genau wie ihr das meint.


Ich habe den zweiten Teil ausprobiert aber er klappt nicht:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var Sender1: Tdummycontrol;
begin
sender1:=TStringgrid(stringgrid1);
stringgrid1.Canvas.Font.Size:=20;
with sender1 do
  showmessage(inttostr(Canvas.Font.Size));


Boldar - Mi 18.03.09 23:47

Das Habe ich ja auch nicht geschrieben. Schreibe direkt hinter Implementation
die Typendeklaration

Delphi-Quelltext
1:
type Tdummycontrol = Tcontrol;                    


und dann immer, wenn du auf sender zugreifst,

Delphi-Quelltext
1:
(sender as Tdummycontrol).xxx                    


Ich bin allerdings nicht ganz sicher, ob TPrinter Tcontrol ist, ansonsten geht nur Möglichkeit 1.


Kha - Do 19.03.09 11:16

@Boldar: Kannst du mir mal erklären, was du mit dem as TDummyControl vorhast? Wären beide Klassen Nachfahren von TControl, würde ich auch einfach einen TControl-Parameter nehmen :nixweiss: . Sind sie aber nicht...

@fuggaz: Imho steht der Aufwand, beide Klassen in eine Methode zu zwängen, in keinem Verhältnis zum Nutzen und erst recht nicht der Lesbarkeit. Mit zwei getrennten Methoden machst du dir das Leben einfacher. Und den Teil, der lediglich eine TCanvas benötigt, nämlich die for-Schleife, kannst du immer noch in eine gemeinsame Prozedur extrahieren.


Boldar - Do 19.03.09 15:14

Wenn TPrinter nicht TControl ist, geht das natürlich nicht, gerade in der Hinsicht war ich mir nich sicher.
Tdummycontrol dient hier als Access-klasse, damit man auf das (eigentlich private?) Canvas zugreifen kann.
Aber, wie gesagt, das geht also nicht.
Also so z.B.


Delphi-Quelltext
1:
2:
3:
4:
case (sender is Tstringgrid) of
true: (sender as Tstringgrid).Canvas.font.size;
false: (Sender as TPrinter).Canvas.font.size;
end;


fuggaz - Do 19.03.09 20:53

Ok, Schade.

Ich hatte gehofft es gibt einen leichten Trick.
Aber es muss schließlich auch Nachteile geben nicht mit c++ oder so zu programmieren ;-)


Danke für eure Antworten :-)


Boldar - Do 19.03.09 21:29

TPrinter und TStringgrid haben halt Nichts zusammen.
Alternativ mach dir eine eigen TPrinter Klasse und leite von TControl ab.