Recent

Author Topic: [SOLVED] With Sender problem  (Read 1366 times)

Badger

  • Full Member
  • ***
  • Posts: 144
[SOLVED] With Sender problem
« on: September 06, 2019, 12:31:53 pm »
I am using a TImage canvas to display text and graphics  on the screen. (TextOUt, MoveTo, LineTo, etc). When a user hits the 'Print' button I want to repeat all the code but send it to the printer instead. I tried Copying the Image bitmap to the printer but the text was a bit fuzzy so I had to go back to my original idea and use code for the printer.

Rather than write the code twice I thought I could call a "PutOnPage(Sender:Object)  - either  calling image or printer routine - and just cover the ratio of image resolution to printer resolution with a ratio.

I know sender.canvas is the clue .However, as  I understand it, I have to use the term With Sender as .... or  with sender.canvas do (either printer or TImage.)  this means I would still have to duplicate the code.  Is there a way round this?
« Last Edit: September 07, 2019, 01:04:19 am by Badger »
Badger
(A bad tempered, grumpy animal that sleeps most of the winter!)

If at first you don't succeed - you're running about average!

I'm using Windows 10 Lazarus v2.4.4  FPC 3.2.2   Win 32/64

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: With Sender problem
« Reply #1 on: September 06, 2019, 01:06:08 pm »
Hi!

Put all your drawings to the canvas together in one main procedure:

Code: Pascal  [Select][+][-]
  1. Procedure TForm1.MainGraph (Can: TCanvas);
  2. begin
  3. Can.TextOut (x1,y1,'Toast Test Taste');
  4. ....
  5. ....
  6. end;
  7.  

After that you only have two different calls:

Code: Pascal  [Select][+][-]
  1. MainGraph (Image1.Canvas);
  2.  

or

Code: Pascal  [Select][+][-]
  1. MainGraph (Printer1.Canvas);
  2.  

Or draw it on any component that owns a canvas.

Winni

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: With Sender problem
« Reply #2 on: September 06, 2019, 02:45:23 pm »
Yes, you can draw on any canvas and subsequently assign that to any other canvas.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

jamie

  • Hero Member
  • *****
  • Posts: 6131
Re: With Sender problem
« Reply #3 on: September 06, 2019, 04:03:23 pm »
The printer's dots per inch is normally much higher than your screen so you'll end up with a small image on a sheet of paper and if you stretch draw it then the image will most likely look a little distorted.

  Depending on how the metrics is setup for the Stretch draw code depends on how the image looks afterwards.

 In windows you can set the stretching to smooth the image so that when you enlarge it you don't get blocking corners and when shrinking will smooth and blend pixels that would otherwise be missing in the image.

  What I would do is write the code block for drawing to the image via a canvas pass and also pass the Pixels Per Pinch value in the call, this way you can scale the size automatically to fix larger Dot per inch canvases.
 
  I do this in a vector drawing display and it works very nicely..

 Write a simple translating function that will return a pixel value from an inch or mm value.

 For example
   TextOut(S(X),S(Y),  your text);

 S(n) is the function that returns the Pixel value plot location using the current DPI settings of the canvas.
The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: With Sender problem
« Reply #4 on: September 06, 2019, 09:04:47 pm »
That technique is called oversampling: dwaing in higher precision, say 4 times and scale it to be smaller, not larger.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

jamie

  • Hero Member
  • *****
  • Posts: 6131
Re: With Sender problem
« Reply #5 on: September 06, 2019, 11:53:39 pm »
Here is a conceptional idea of helping the cause a bit.
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$ModeSwitch TypeHelpers}
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     procedure Button1Click(Sender: TObject);
  17.   private
  18.  
  19.   public
  20.  
  21.   end;
  22.  TMyCanvasHelper = Class Helper for TCanvas
  23.     Private
  24.     Function I(X:Single):Integer;
  25.     Public
  26.     Class Var DPI:Integer;
  27.     Procedure TextOutInch(X,Y:Single;S:String);
  28.    end;
  29. var
  30.   Form1: TForm1;
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36.  { TForm1 }
  37.  
  38.  procedure TForm1.Button1Click(Sender: TObject);
  39.  begin
  40.    canvas.DPI := Screen.PixelsPerInch; // Normally you would get this from a printer;
  41.    Canvas.TextOutInch(1.0, 1.0, 'Test');
  42.  end;
  43.  Function TMyCanvasHelper.I(X:Single):Integer; Inline;
  44.  Begin
  45.    Result := Round(X * DPI);
  46.  End;
  47.  
  48.  Procedure TMyCanvasHelper.TextOutInch(X,Y:single;S:String);
  49.   begin
  50.     Self.TextOut(I(X),I(Y),S);
  51.   end;
  52. end.
  53.  

Help out the TCanvas and give it some more functions that uses Inch scale instead!
 This idea will pave the way to add all the other functions needed so that one can print using inches if they wish, if they want to remain at pixels using the same math then set the DPI to 1 otherwise set it to the Printer canvas DPI or screen or what ever.
The only true wisdom is knowing you know nothing

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: With Sender problem
« Reply #6 on: September 07, 2019, 12:38:53 am »
The resolution is mostly not the problem. And if you rely on the information given by the printer drivers you often run in trouble.

Asking GetDeviceCaps will give you often nonsens.

And the relationship of height and width often differs between the (basic) image, a printer and a preview and an icon.

So what I do is to enhance my above example to

Code: Pascal  [Select][+][-]
  1. Procedure TForm1.MainGraph (Can: TCanvas; fx,fy : single);

where fx and fy are the factors for width and height.

I am assuming that the main image is always fx=1 and fy= 1

so fx and fy for a printer are
Code: Pascal  [Select][+][-]
  1. fx := Printer.PageWidth/Image1Width;
  2. fy := Printer.PageHeight/Image1.height;
  3.  

In reality you (most) have to swap PageWidth and PageHeight as an image on the screen is typically landscape and the printer not - but that is a second issue.

And then I only have to do

Code: Pascal  [Select][+][-]
  1. Can.TextOut (round (x1*fx), round(y1*fy),'A Text');


Winni


Badger

  • Full Member
  • ***
  • Posts: 144
Re: With Sender problem
« Reply #7 on: September 07, 2019, 01:03:28 am »
Thanks All
My problem was I was trying to pass the object as the parameter rather than its canvas.
Badger
(A bad tempered, grumpy animal that sleeps most of the winter!)

If at first you don't succeed - you're running about average!

I'm using Windows 10 Lazarus v2.4.4  FPC 3.2.2   Win 32/64

 

TinyPortal © 2005-2018