1

I'm trying to set the column width for printing with my Delphi application. Whatever I type for the string doesn't make the width fewer. Actually I don't understand why the property returns a string, it should return width in pixels.

My code is

Printer.Canvas.TextWidth('M');

Edit: i understood it doesn't return a string but what does 'M' mean? what i m trying to do is making a column narrower. my code is located at sudrap.org/paste/text/19688

Edit: i m afraid i couldn t explain the problem clearly, i m sorry. i want it to print like this:

enter image description here

not like this: enter image description here

nikel
  • 653
  • 4
  • 13
  • 24
  • But the [TextWidth](http://docwiki.embarcadero.com/VCL/en/Graphics.TCustomCanvas.TextWidth) should return integer. Are you using `Printers` unit in your uses clause ? –  Jul 29 '11 at 01:32
  • yes i m using it. 'M' returns 75, 'A' returns 61. i m confused. – nikel Jul 29 '11 at 01:37
  • @nikel: I don't get it either. Canvas.TextWidth() is not a property and it does not return a string. It returns the width of the string when displayed (printed) on the canvas, in pixels. It does not change the string parameter. Could you post a few more lines of your code? – Rudy Velthuis Jul 29 '11 at 01:38
  • i understand, it returns integer. i just want to make column smaller. my code: http://www.sudrap.org/paste/text/19688/ – nikel Jul 29 '11 at 01:42
  • 75 and 61 are the respective widths of the strings 'M' and 'A', when printed on the canvas. Try the strings 'AM' or 'MA', and you probably get something close to 136 in both cases. I have the impression you don't quite understand what TextWidth() is supposed to do. – Rudy Velthuis Jul 29 '11 at 01:42
  • thanks for the replies. no i totally couldn t understand what TextWidth() is supposed to, that s why i m asking here. i have searched through a search engine about how to make the column narrow. – nikel Jul 29 '11 at 01:51
  • The first parameter to `TextOut` is the x coordinate for the text. Pass whatever number to it where you want your second column to be when outputting the second column. – Sertac Akyuz Jul 29 '11 at 02:00
  • i thought second parameter is Y position. i ll try that. – nikel Jul 29 '11 at 02:03
  • no it didn't work, it just put text to top. – nikel Jul 29 '11 at 02:05
  • @nikel - `Printer.Canvas.TextOut(500, ...` will leave 500 pixels from the left, `Printer.Canvas.TextOut(400, ...` will leave 400 pixels from the left. With the latter you'll have a more narrow first column than the former. If you're reserving 15 'M's space for the first column, then make it 10 'M's... – Sertac Akyuz Jul 29 '11 at 02:11
  • Sounds to me like you are wanting to use Printer.Canvas.Font.Size to change the size of the characters. That will make it narrower. – mj2008 Jul 29 '11 at 08:22
  • @Nikel - What happens if you write `Col2:=10*Printer.Canvas.TextWidth('M');` instead of `Col2:=15*Printer.Canvas.TextWidth('M');`? – Sertac Akyuz Aug 01 '11 at 02:18
  • it brings column 2 on column 1 (it moves col2 to left) – nikel Aug 01 '11 at 02:35
  • i m not testing by printing because my printer is broken. instead i save as xps. – nikel Aug 01 '11 at 02:37
  • @nikel - But isn't it narrowing column 1, in other words isn't it what you're asking? If text in column 1 does not fit the width of the column then you have to use a smaller font, or to clip/wrap the text you have to work out daemon's answer.. – Sertac Akyuz Aug 01 '11 at 02:38
  • i ve edited the question, added screenshots please see them. – nikel Aug 01 '11 at 03:03
  • 2
    @nikel - That's 'word wrapping' as mentioned in daemon's answer. You should proceed in that direction. Thanks for making the question clear BTW. :) – Sertac Akyuz Aug 01 '11 at 03:13
  • when i try it, Delphi underlines TargetRect with red, and doesn't compile. the error is [DCC Error] Unit1.pas(461): E2250 There is no overloaded version of 'TextRect' that can be called with these arguments – nikel Aug 01 '11 at 03:18
  • i somehow fixed it but now either columns on the left and right side disappeared. – nikel Aug 01 '11 at 03:24

3 Answers3

3

Try to check TextRect function. Using this function you can specify the target rectangle where the text should be printed, so you can narrow your column.

uses Graphics;

var
  Text: string;
  TargetRect: TRect;
begin
  Printer.BeginDoc;

  Text := 'This is a very long text';

  // now I'll specify the rectangle where the text will be printed
  // it respects the rectangle, so the text cannot exceed these coordinates
  // with the following values you will get the column width set to 50 px

  TargetRect := Rect(Margin, Y, Margin + 50, Y + LineHeight);

  Printer.Canvas.Font.Size := 11;
  Printer.Canvas.Font.Name := 'Arial';
  Printer.Canvas.Font.Style := [fsBold];
  Printer.Canvas.TextRect(TargetRect, Text);

  Printer.EndDoc;
end;

Except this you can get with the TextRect function set of the formatting flags which can help you to specify e.g. text alignment, word wrap etc. For instance if you would like to center the text horizontally in the specified rectangle [100;100], [250;117] you can use the following.

Text := 'Centered text';
TargetRect := Rect(100, 100, 250, 117);
Printer.Canvas.TextRect(TargetRect, Text, [tfCenter]);

Or in your case might be more useful word wrap. Here's an example with rectangle [100;100], [200;134] where the text is automatically wrapped by the TextRect function.

Text := 'This is a very long text';
TargetRect := Rect(100, 100, 200, 134);
Printer.Canvas.TextRect(TargetRect, Text, [tfWordBreak]);
  • i tried this a few days ago but it didn t work. i remember that it gave error. – nikel Aug 01 '11 at 00:57
  • One thing is that you need to add `Graphics` to your uses list as I updated in my post. That's what you probably have at this time. And the second thing is, I presume, that you're trying to pass something like `Memo1.Text` directly to the [TextRect](http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Graphics_TCanvas_TextRect@TRect@Integer@Integer@string.html) method. Although this method has two versions, the one I've used in my example needs to have the Text parameter declared, what is the `var` keyword in its definition `var Text: string;` –  Aug 01 '11 at 07:57
0

If you use a fixed width font on the canvas, you should get the same result for all single-character strings. If you use a variable width font, each character will return a different width.

Printer.Canvas.Font.Name = 'Courier New';
Printer.Canvas.Font.Size = 13;
ColumnWidth := Printer.Canvas.TextWidth('M');

For different fonts or different font sizes, you will get different results.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
0

I don't see how you're saying it returns text. If it were returning text your code wouldn't even compile, you would be getting errors when you tried to multiply a number by text. You even convert it to a string for display purposes.

Are you being mislead by the fact that with a variable-width font that you'll get different answers for different strings? You can even get different answers for the same letters in a different order. For some fonts "WAM" will produce a different answer than "WMA" because of how the W and A fit together.

Also, you're simply assuming that your labels are narrower than 15 M's. While this is generally the case it's not good programming practice. Instead, you should be asking for the width of each label and using something a bit above the biggest answer.

Finally, your handling of LineHeight is atrocious. Simply add 300 to y if that's what you really want although it should be some multiple of your line height, not a fixed value. You'll get VERY different results from your code off printers with different DPI settings.

Have you even tried stepping through this code with the debugger to see what's going on internally? Your output of the position to the printout suggests you aren't using the debugger.

Loren Pechtel
  • 8,945
  • 3
  • 33
  • 45
  • +1; also about getting margin there is e.g. [this post](http://www.swissdelphicenter.ch/torry/showcode.php?id=1039) which, even though there is an obsolete usage of [Escape](http://msdn.microsoft.com/en-us/library/dd162701%28VS.85%29.aspx) function, will be much more precise than `5 * width of upper cased M`, but it would totally exceed this question ;) –  Jul 29 '11 at 07:29
  • thanks for the detailed answer. i tried adding 300 to y in the previous days but it didn't work. and i couldn t understand what this has to do with labels. and how do i enable debugging? – nikel Aug 01 '11 at 00:51
  • @nikel: There's no need to enable debugging. You simply set a breakpoint where you want it and it will stop when it gets there. – Loren Pechtel Aug 01 '11 at 03:09