Why use TppDrawCommand?
HI,
Since I'm not familar with the print engine, so Can anybody explain to me,
Why we need the TppDrawCommand class to print on the preview device, printer
device or other device, since these device have Canvas, why we don't just
call the method PaintDesignControl of TppCustomCompnent class to paint on
these device, rather than use PaintDesignControl for design purpose and
using DrawCommand class for print, preview purpose. e.g. I'm trying to
design a checkbox with a description beside it. after I do the research, I
finally give up, since by using RB componet structure, I can't just simple
draw a rectangle and a caption because there is no corresponding draw
command class for it. I have to create a rectangle shape component + a
label component, which I think wasting resources and could make the report
more big.
Best Regards,
William
Since I'm not familar with the print engine, so Can anybody explain to me,
Why we need the TppDrawCommand class to print on the preview device, printer
device or other device, since these device have Canvas, why we don't just
call the method PaintDesignControl of TppCustomCompnent class to paint on
these device, rather than use PaintDesignControl for design purpose and
using DrawCommand class for print, preview purpose. e.g. I'm trying to
design a checkbox with a description beside it. after I do the research, I
finally give up, since by using RB componet structure, I can't just simple
draw a rectangle and a caption because there is no corresponding draw
command class for it. I have to create a rectangle shape component + a
label component, which I think wasting resources and could make the report
more big.
Best Regards,
William
This discussion has been closed.
Comments
metafile uses instructions to draw. The draw commands are instructions on
what to draw, not how to draw it. This allows for an open device
architecture, where each device takes the same draw command and renders it
on any device context (printer, text file, image or other format, such as
XHTML, PDF or XLS). This doesn't tie you down to having only TCanvas support
on a device class. If you wanted to, you could create an output device that
sent each page of the report as a separate email, because you aren't tied to
a canvas for drawing. The devices which have canvas' are implmented by
drawing on the canvas such as the screen device.
You'll need to create two draw commands. One for the shape and one for the
label.
Cheers,
Jim Bennett
Digital Metaphors
http://www.digital-metaphors.com
info@digital-metaphors.com
in the overridden PropertiesToCommand mthod:
inherited PropertiesToDrawCommand(aDrawCommand);
{make sure the drawcommand is of the appropriate class}
if not(aDrawCommand is TppDrawText) and not (aDrawCommand is TppDrawShape)
then Exit;
begin
CalcDimensions(llLeft, llTop, llRight, llBottom, llXCornerRound,
llYCornerRound);
llLeft := PrintPosRect.Left + ppToMMThousandths(llLeft, utScreenPixels,
pprtVertical, nil);
llTop := PrintPosRect.Top + ppToMMThousandths(llTop, utScreenPixels,
pprtVertical, nil);
llRight := PrintPosRect.Left + ppToMMThousandths(llRight,
utScreenPixels, pprtVertical, nil);
llBottom := PrintPosRect.Top + ppToMMThousandths(llBottom,
utScreenPixels, pprtVertical, nil);
llXCornerRound := ppToMMThousandths(llXCornerRound, utScreenPixels,
pprtVertical, nil);
llYCornerRound := ppToMMThousandths(llYCornerRound, utScreenPixels,
pprtVertical, nil);
lDrawShape := TppDrawShape(aDrawCommand);
lDrawShape.Pen.Color := clBlack;
lDrawShape.ShapeType := stRectangle;
lDrawShape.Left := llLeft;
lDrawShape.Top := llTop;
lDrawShape.Height := CheckBoxSize;
lDrawShape.Width := CheckBoxSize;
lDrawShape.XCornerRound := 0;
lDrawShape.YCornerRound := 0;
if FChecked then
lDrawShape.Brush.Color := clBlack
else
lDrawShape.Brush.Color := clBtnShadow;
end;
if aDrawCommand is TppDrawText then
begin
lDrawText := TppDrawText(aDrawCommand);
{set the position of the text on the page}
lDrawText.Left := PrintPosRect.Left + CheckBoxSize;
lDrawText.Top := PrintPosRect.Top;
lDrawText.Height := PrintPosRect.Bottom - PrintPosRect.Top;
lDrawText.Width := PrintPosRect.Right - PrintPosRect.Left;
{set the drawtext properties so the visual represention of the check box
will
be correct when the command is rendered by the receiving Device
(ScreenDevice
for Print Preview form, PrinterDevice when printing to printer, etc.)}
lDrawText.Alignment := taLeftJustify;
lDrawText.AutoSize := True;
lDrawText.Color := Color;
lDrawText.Font.Height := spHeight;
lDrawText.Text := Caption;
lDrawText.Transparent := Transparent;
lDrawText.WordWrap := False;
end;
But result on the preview form, it only prints the caption, no check box, so
what am I missing?, Could you please correct me? the check box component
is inherited from TppCustomComponent.
William
create which isn't passed in the parameter of this routine. For example, in
our source the page object is assigned after this routine is called in the
ancestor. Here is the code, perhaps this will give you abetter
understanding of what is happening when this routine is overridden by you
and it is called:
{---------------------------------------------------------------------------
---}
{ TppPrintable.CreateDrawCommand }
procedure TppPrintable.CreateDrawCommand(aPage: TppPage);
var
lDrawCommand: TppDrawCommand;
lParams: TraParamList;
begin
if (FDrawCommandClass = nil) then Exit;
{create the draw command}
lDrawCommand := FDrawCommandClass.Create(nil);
{transfer properties to draw command}
PropertiesToDrawCommand(lDrawCommand); <-- Here is the call, so most
likely your draw command class is always TppDrawText
{assign click event handler, do this after create}
lDrawCommand.Clickable := Assigned(FOnDrawCommandClick) or
IsActiveNotify(ciPrintableDrawCommandClick);
lDrawCommand.OnClick := DrawCommandClickEvent;
{assign the page rect - used for clipping}
lDrawCommand.ClipRect := aPage.PageDef.PageRect;
{trigger event}
if Assigned(FOnDrawCommandCreate) then FOnDrawCommandCreate(Self,
lDrawCommand);
{assign draw command to page, do this last, so drawcommand is properly
classified}
lDrawCommand.Page := aPage;
lParams := TraTppPrintableRTTI.GetParams('OnDrawCommandCreate');
lParams.CreateValuePointer(0, lDrawCommand);
SendEventNotify(Self, ciPrintableDrawCommandCreate, lParams);
lParams.Free;
end; {procedure, CreateDrawCommand}
So if you want to add a draw command, you'll have to create a TppDrawShape,
then reference Report.Engine.Page as the report is generating in order to
add a draw command to the page. lDrawShape.Page := Report.Engine.Page. This
call can't be made from inside PropertiesToDrawCommand, unless you create a
global function to let you get at the current TppReport object, but this
isn't exactly OO. After thinking about this more, the other (probably
better) alternative is to create a new draw command class that can draw a
shape and text all in one. This way you can create one object and it can
draw a shape and some text. Override the Draw routine of the draw command
descendent in order to let the draw command class draw itself rather than
let the device determine how to draw the draw command. See ppDevice.pas for
the TppDrawCommand ancestor interface section or check out our help file on
the draw command classes and members.
Cheers,
Jim Bennett
Digital Metaphors
http://www.digital-metaphors.com
info@digital-metaphors.com