Calculate width by code
Hello,
I have a code based report in which components (TPpLabel, TppDbText..)
are created by code.
Once created I tried to position them using your Tech Tip
"Calculating the widths of components at run-time"
I only sligthly modified it to read field size (I am printing data from
database tables) from the data dictionary, instead of relying on
lComponent.Caption as in the example.
The problem is that the calculated width is too large
For example a field is 80 character size and the function calculates,
say, 564 pixel that, once printed, are a quite too large.
Do I need to use a printer.canvas ?
But if so isn't the example a little flawed ?
I am using D7 and RB 9.02
Thanks!
Bye
Nicola
I have a code based report in which components (TPpLabel, TppDbText..)
are created by code.
Once created I tried to position them using your Tech Tip
"Calculating the widths of components at run-time"
I only sligthly modified it to read field size (I am printing data from
database tables) from the data dictionary, instead of relying on
lComponent.Caption as in the example.
The problem is that the calculated width is too large
For example a field is 80 character size and the function calculates,
say, 564 pixel that, once printed, are a quite too large.
Do I need to use a printer.canvas ?
But if so isn't the example a little flawed ?
I am using D7 and RB 9.02
Thanks!
Bye
Nicola
This discussion has been closed.
Comments
The example is correct however it calculates based on a screen pixel based
canvas. This measurement when translated to the printer canvas will loose
much of its accuracy. (printers usually print with 600 dots per inch and
most screens are set to 96 pixels per inch). Try using the printer canvas
and see if you get a more accurate result.
--
Regards,
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
I tried something like this:
uses
ppPrintr;
...
liTextWidth := ppPrinter.Canvas.TextWidth(MyString);
But the results are still larger than needed...
My code loads an external report as a template and then creates
components in the detail/header bands inside it.
I tried changing units (from screen pixels to printer pixels) of this
external template but I saw no changes in the output...
It seems that I need to scale down liTextWidth but I am uncertain which
parameter to use...
Nico Cizik (Digital Metaphors) ha scritto:
Be sure you are assigning the correct font to the canvas before making the
measurement. I believe this can have an effect on the size of the text
measured.
--
Regards,
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
This is the (pseudo)code I use
lCanvas := ppPrinter.Canvas;
lCanvas.Font := lCustomText.Font;
FieldSize := GetFieldSizeFromCatalog;
Campione := StringOfChar('A', FieldSize);
liTextWidth := lCanvas.TextWidth(Campione);
So I did this assignment
lCanvas.Font := lCustomText.Font;
Is this correct? (lCustomText is the TppDbText)
Thanks in advance
Bye
Nico Cizik (Digital Metaphors) ha scritto:
Yes, this looks correct. Are you getting better results. As a test I
created a simple app that measures the caption of a Label on a report.
Below was my code...
procedure TForm1.Button1Click(Sender: TObject);
var
liWidth: Integer;
begin
ppPrinter.Canvas.Font := ppLabel1.Font;
liWidth := ppPrinter.Canvas.TextWidth(ppLabel1.Caption);
ShowMessage(IntToStr(liWidth));
end;
The width of the label component (which is a little larger than the text
itself) on the report was 250 printer pixels. The return value for the text
width was 248. Pretty accurate.
--
Regards,
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik (Digital Metaphors) ha scritto:
No, using the printer canvas will always return printer pixels. You can use
the utility functions provided in ppUtils.pas to convert these values to
other units.
You will probably need to use a combination of ppToMMThousandths and
ppFromMMThousandths functions.
--
Regards,
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Total confusion here...
For test I tried to put manually with the report designer a TppDbText on
the same report in which I am creating components by code.
So I can compare the runtime generated TppDbText with the manual one (I
arranged my program in a way that it creates components after the
already present in the report)
In the manual created TppDbText I putted enough space for three
characters (Arial 8 font) so I can see his width in printer pixels that
is "reported" by the report designer: it is 106 pixels.
When my code runs it calculates for the same field (3 characters) a
little less, 90 pixel.
The very strange thing is the actual printed output!
My generated component holds 13 characters instead of the only 3 I expected.
in the runtime generated component I forced the same font (arial 8) and
autosize=false
Are there any other properties that may cause a "stretch" of the
TppDbText ??
I'm also a bit confused about what you are ultimately trying to do. Perhaps
a detailed description of what your report looks like and exactly what you
would like to see happen. During the report generation, the acutal text
component will not be re-sized based on the text being displayed. This is
going on in the drawcommand object. My suggestion is to manually retrieve
the text directly off the database and measure it to get an accurate result.
--
Regards,
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
What I need to do is quite simple:
1. load a report template.
This template has a title, a footer and a detail
The detail contains no components at all (in the final version)
2. at runtime the user can choose which fields she wants in the report
browsing a database catalog (e.g. the fields of a particular table)
3. the program creates the requested TppComponent in the detail band.
I am trying to size each component to fit the maximum length allowed for
each of them
For example
The user chooses the field "EMP"."SURNAME"
The program looks up in the database catalog and see that EMP.SURNAME
field is 40 character long, so it will create a TppDbText linked to the
EMP.SURNAME 40 character long.
This is what I need to accomplish
The SQL manipulation part works fine, even the TPpComponent creation
works, only the sizes are wrong....
Thanks for the explaination.
When creating the TppDBText components, have you tries simply setting the
AutoSize property to True? This should dynamically size the DBText width to
the size of the text being pulled from the database (I believe using the
same technique we've been trying).
--
Regards,
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Thanks for responding, I understand that is difficult for you help me
without seeing mu code..
Yes I alread tried autosize=true
But even so it doesn't work well.
The left position is too large
Remember the example?
The left position of each TppDbText in the list is setted using the
width as increment.
My components are too large spreaded, even when I don't set the width,
using only autosize=true
Nico Cizik (Digital Metaphors) ha scritto:
In your example "Calculating the widths of components at run-time"
the screen pixel property was used.
See:
..
{set components screen pixel left}
lCustomText.spLeft := liPosition;
..
There is also a comment but, you know, I missed to read it... -)
I changed spLeft into Left and now my results sound much better to me...
Thanks
Bye
Nicola
Fantastic! Glad you got it working.
--
Regards,
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com