Entwickler-Ecke

Multimedia / Grafik - Printer.Canvas - Drehen möglich?


jjturbo - Mi 22.09.10 11:37
Titel: Printer.Canvas - Drehen möglich?
Moin Forum,

ich habe ein Etikett direkt auf Printer.Canvas gezeichnet, läßt sich das jetzt gezeichnete auf einfache Weise drehen?
Oder muß man es zwangsweise erst in ein Bitmap zeichnen, und dann dieses drehen und anschließend auf dem Drucker ausgeben?


bummi - Mi 22.09.10 11:39

drehen, zoomen usw.

MfG
bummi


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:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
unit ExCanvasTools;
// 20100915 by Thomas Wassermann
interface
uses
  Windows, SysUtils,  Classes, Graphics;

  Function Grad2Rad(w:Double):Double;
  Procedure PaintGraphic(ACanvas:TCanvas;x,y:Integer;AGraphic:TGraphic;Faktor,Winkel:Double;PosIsCenter:Boolean=false);
  Procedure PaintText(ACanvas:TCanvas;Const s:String;x,y:Integer;Faktor,Winkel:Double;PosIsCenter:Boolean=false);
  Procedure ResetCanvas(ACanvas:TCanvas);
  procedure SetCanvasZoomAndRotation(ACanvas: TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double);

implementation

Function Grad2Rad(w:Double):Double;
  begin
     Result := w  / 360 * PI *2;
  end;

Procedure PaintText(ACanvas:TCanvas;Const s:String;x,y:Integer;Faktor,Winkel:Double;PosIsCenter:Boolean=false);
var
  px,py:Integer;
begin
     SetCanvasZoomAndRotation(ACanvas , Faktor, Winkel, x,y);
     if PosIsCenter then
        begin
          px := Round( ACanvas.TextWidth(s) / 2 );
          py := Round( ACanvas.TextHeight(s) / 2 );
        end
     else
        begin
          px := 0;
          py := 0;
        end;

     ACanvas.TextOut(-px ,-py ,s);
     ResetCanvas(ACanvas);
end;




Procedure PaintGraphic(ACanvas:TCanvas;x,y:Integer;AGraphic:TGraphic;Faktor,Winkel:Double;PosIsCenter:Boolean=false);
var
  px,py:Integer;
begin
     if PosIsCenter then
        begin
          px := Round( AGraphic.Width / 2 );
          py := Round( AGraphic.Height / 2 );
        end
     else
        begin
          px := 0;
          py := 0;
        end;
     SetCanvasZoomAndRotation(ACanvas , Faktor, Winkel, x , y  );
     ACanvas.Draw(-px ,-py ,AGraphic);
     ResetCanvas(ACanvas);
end;





Procedure ResetCanvas(ACanvas:TCanvas);
begin
   SetCanvasZoomAndRotation(ACanvas , 100,0);
end;

Procedure SetCanvasZoomAndRotation(ACanvas:TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double);
var
    form : tagXFORM;
    Winkel:Double;

begin
      Winkel := Grad2Rad(Angle);
      SetGraphicsMode(ACanvas.Handle, GM_ADVANCED);
      SetMapMode(ACanvas.Handle,MM_ANISOTROPIC);
      form.eM11 := Zoom * cos( Winkel);
      form.eM12 := Zoom *Sin( Winkel)  ;
      form.eM21 := Zoom * (-sin( Winkel));
      form.eM22 := Zoom * cos( Winkel) ;
      form.eDx := CenterpointX;
      form.eDy := CenterpointY;
      SetWorldTransform(ACanvas.Handle,form);
end;

end.


jjturbo - Mi 22.09.10 11:56

Das hört sich gut an.
Also um das auf die Canvas gezeichnete um 180° zu drehen:


Delphi-Quelltext
1:
SetCanvasZoomAndRotation(Printer.Canvas,1,180,0,0);                    


Ist das richtig so?


bummi - Mi 22.09.10 12:12

CenterpointX,CenterpointY
wirst Du rausrechnen müssen....


jjturbo - Mi 22.09.10 12:27

ok, das heißt:

Delphi-Quelltext
1:
SetCanvasZoomAndRotation(Printer.Canvas,1,180,Printer.PageWidth div 2, Printer.PageHeight div 2);                    


dreht mir die Canvas um 180°, Größe unverändert, um den Mittelpunkt, ja?


bummi - Mi 22.09.10 12:36

Mach Dir mal eine kleine Schleife die Dir auf dem Canvas eines Forms einen Text in 30 Grad-Schritten dreht, dann siehst Du wie es tickt....

Es wird immer um 0,0 gedreht, das heißt bei 180 Grad befindest Du Dich im Quadranten links oberhalb Deines Forms, dies kannst Du mit Centerpoint X,Y ausgleichen.

Also 180 Grad gedreht würde wenn es links oben dargestell werden soll für CenterpointX die Angabe der Breite Deiner Ausgabe und für CenterpointY die Angabe der Höhe ausgabe benötigen.

MfG
Thomas


jjturbo - Mi 22.09.10 12:47

Ok, Grundsätzlich funktioniert es schon mal sehr gut.

Ich habe eine Routine:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TFormDrucker.Zeichne(BreitePixel,HoehePixel:Integer;MyCanvas:TCanvas);
begin
.
.
.
  SetCanvasZoomAndRotation(MyCanvas,1,180,MyCanvas.ClipRect.Right,MyCanvas.ClipRect.Bottom);
  Mycanvas.Draw(irgendwas);
  Mycanvas.Pen.Color := BlaBla;
  Mycanvas.MoveTo(Irgendwo);
  Mycanvas.LineTo(WoandersHin);
.
.
.
end;


Wenn ich es aufrufe mit

Delphi-Quelltext
1:
2:
    //(MyImage1 ist ein TImage)
    Zeichne(MyImage1.Picture.Bitmap.Width,MyImage1.Picture.Bitmap.Height,MyImage1.Canvas);


dann wird es auf dem Bildschirm korrekt angezeigt.
Aber

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
  if PrintDialog1.Execute then begin
    with Printer do begin
      Title       := Application.Title + ' Etikett drucken ';
      BeginDoc;
      Zeichne(Printer.PageWidth,Printer.PageHeight,Printer.Canvas);
      EndDoc;
    end;//with Printer do begin
  end;//if PrintDialog1.Execute then begin


Gibt das Bild nicht gedreht aus. Was mache ich denn noch falsch?


bummi - Mi 22.09.10 13:57

Du machst ncht falsch, Dein Druckertreiber wird SetWorldTransform wohl leider nicht unterstützen, sorry, also doch erst mal in ein Bitmap malen und das dann an den Drucker schicken.


jjturbo - Mi 22.09.10 14:14

Oh mein Gott, ich muß sorry sagen... :oops:

Alles wurde ordnungsgemäß gedreht, ich habe nicht beachtet, daß das Blatt anders herum heraus kam.
Ich habe die Grafik am oberen Rand gedreht erwartet, da ich aber die Grafik auf das gesamte Blatt gezoomt hatte war es nicht auf den ersten Blick zu sehen.

Funktioniert super!!!

Danke!!!