I need to write some fixed-width font (i.e Courier New or Consolas) text to a .net Winforms window in the Paint event - not using a label or any other winforms control - rather using a graphics object method to render the text onto the form's client area.
I am having difficulty aligning text on different lines under headings even though it is fixed width font. How can I get a precise measurement of the width of a single character in the fixed-width font? How can I get 2 lines to print out aligned horizontally in successive text out calls?
For example:
Heading 1 Heading 2
Short Other text
A bit longer Still aligned?
I need a separate call to render each cell of text under Heading 2. For argument's sake - let's say column 1 items are printed in black and column 2 are printed in blue - we can't use the same text out call for the entire line.
Graphics.MeasureString may be what you are looking for.
Ok so here is the code that works the way I want using MeasureString. A string is printed twice. One time using a single call to DrawString. The second time, character by character in a loop. What I needed was that the 2 strings should appear identical but I was having trouble getting the correct horizontal position of each char when drawing the second string. You can put this code into the Paint event of a form to try it out (set the form font to Consolas or other fixed width font):
Dim i As Single
Dim sf As StringFormat
Dim String1 As String = "Here is out test string"
Dim CharSizeF As SizeF
sf = StringFormat.GenericTypographic
CharSizeF = e.Graphics.MeasureString(String1, Me.Font, 10000, sf)
CharSizeF.Width /= String1.Length
e.Graphics.DrawString(String1, Me.Font, Brushes.Black, 0, 0, sf)
For Each c As Char In String1
e.Graphics.DrawString(c.ToString, Me.Font, Brushes.Black, i * CharSizeF.Width, CharSizeF.Height, sf)
i += 1
Next
Microsoft also helped with:
http://msdn.microsoft.com/en-us/library/957webty.aspx
To obtain metrics suitable for adjacent strings in layout (for example, when implementing
formatted text), use the MeasureCharacterRanges method or one of the MeasureString methods that
takes a StringFormat and pass GenericTypographic. Also ensure the TextRenderingHint for the
Graphics is AntiAlias.
Related
I have a text box on an MS-Access 2007 Form (its old, but its what I have) called text_record. I want to display the characters in the text box with a positional line directly underneath the text. e.g.
ABCDEF
123456
I used the following code to set the field:
dim x as string
x = Forms![mapped field names].Form![text_record] & vbcrlf
For i = 1 To Len(x) - 1
x = x & CStr(i Mod 10)
Next
Forms![mapped field names].Form![text_record] = x
The code works and shows the integer positions underneath, but the characters are not aligned directly above the numbers. I need the characters directly above the positional number so a user can see what is in a particular column.
I tried several different font types, all said they were monospaced, and they all fail to align directly above the number. Depending on the text in the record, the position was off as much as 5 columns.
I must be missing something simple.
Thanks in advance for any and all responses
Use a fixed font. Courier New is a fixed size.
So, on the form, I drop in a text box, and right below another text box
(I set the border to transparent, and I set enabled = false (so user can't edit, or tab into).
so we have this:
And the font for both text boxes is this:
And my code (it puts numbers below as you type).
Private Sub Text0_Change()
Dim sResult As String
Dim i As Integer
For i = 1 To Len(Text0.Text)
sResult = sResult & i Mod 10
Next i
Me.Text2 = sResult
End Sub
So, we see this (and I typed in "i" and "l", since they are small compared to numbers, and we get this:
so, not sure what font you used, but Courier new is a fixed font, and should work as per above.
You might be better off splitting the text and putting it into a multi-column list box.
So basically I have a textbox with a specific width and I need to know if the string I will put into it will either fit nicely in one line or take a second line. For example: I have
string v = "WERTYUIOSDFGHJKWERTYUISDFGHJKXCVBNSDFGHJ"
and a textbox that's 3000 in width.
At first I tried: if v.length = x then... where x is the length of the string that can fit into the textbox. But I soon found out that strings with mostly 'I' can fit more inside compared to a string of mostly 'M'. And that is where the problem lies. Is there a function that detects if the string is going to take/need a second line?
Another option is to create or use a 3rd-party Crystal Reports UFL (User Function Library). A list of 3rd-party UFLs is maintained by Ken Hamady here.
At least one of these UFLs provides functions that allow Crystal formulas to either:
a. specify as input the text, font name, font size, bold and italics status and get the required width (in pixels or twips), or
b. specify the available width for the text and get the maximum font size to fit, or the number of lines required for a given font size.
The advantage of using a UFL approach is that Crystal supports dynamic property expressions. That means that the result of the function call can dynamically control a property such as font size, height, position, etc.
I'm working on a cut list generator but I'm having difficulty on the final report. I'd like to display a rectangle that represents the factory length piece with lines indicating cut points. In each segment I'd like to have the length of the piece shown. Using Report.line I've created the rectangles needed but I'm not sure how to get text in each box. Here is a sample output so far As an example I want the three rectangles for Piece #1 to have 48" in them, probably all the way to the left. Any suggestions? I thought createReportControl might work but I'm not sure that is the correct approach. I'm also thinking about one text box with a monospace font so I can scale the input across the entire width. Any suggestions are appreciated.
Thanks,
Dave
I played around with the monospace font idea. It isn't as pretty as I would like but I'm getting closer.
The issue is that I cannot keep the text in the same spot in each box. There is one line lower on the page that pushes the number almost out the right side of the box.
Sample Output
This code is functional but I'm looking at the cosmetics. I'm inserting spaces between my values using the following function:
Private Function InsertSpaces(CutLen, PieceLen) As String
MaxChar = 50 ' 6 inch 14pt Courier text box
cutchar = Int(CutLen / PieceLen * MaxChar)
Cutcharcount = Len(Str(CutLen))
cutchar = cutchar - Cutcharcount + 1
For i = 1 To cutchar
InsertSpaces = InsertSpaces + " "
Next
End Function
I'm just trying to clean it up. CreateReportControl was giving me a error because I wasn't in design mode. I'm guessing that is because it ran as part of OnFormat of the Detail section.
I would like to draw 2 texts onto my PDF.
The first text should be aligned to the top left corner.
This works fine.
I'm using:
canvas = stamper.GetOverContent(i)
watermarkFont = iTextSharp.text.pdf.BaseFont.CreateFont(iTextSharp.text.pdf.BaseFont.HELVETICA, iTextSharp.text.pdf.BaseFont.CP1252, iTextSharp.text.pdf.BaseFont.NOT_EMBEDDED)
watermarkFontColor = iTextSharp.text.BaseColor.RED
canvas.MoveTo(0, 0) 'I think the canvas is the space that we draw onto. My documents always start at position X=0 and Y=0, so move to 0,0 should be fine
canvas.BeginText()
canvas.SetFontAndSize(watermarkFont, 12)
canvas.SetColorFill(watermarkFontColor)
canvas.ShowTextAligned(Element.ALIGN_TOP, uText, 0, 830, 0) 'is 830 the width of the available space?
canvas.EndText()
Now I would like to draw another text approximately 100 pixels below the first text.
I'm using:
canvas.MoveTo(0, 100) 'let's draw the second text at X=100, Y=100
canvas.BeginText()
canvas.SetFontAndSize(watermarkFont, 12)
canvas.SetColorFill(watermarkFontColor)
canvas.ShowTextAligned(Element.ALIGN_CENTER, uBewirtung, 0, 830, 0)
canvas.EndText()
The second text however doesn't show up at all.
I suspect I'm drawing outside the document, but I don't see my mistake.
The MoveTo() method is meant for drawing paths (lines amd shapes in graphics state), not text (in text state). It adds an m operator to the content stream. If you are a PDF specialist, you should use the SetTextMatrix() method inside your BT/ET text block: What does setTextMatrix of contentByte class in iText do?
Note the if; it is important. If you are not a PDF specialist, you shouldn't be toying around with those methods. You should use ColumnText.ShowTextAligned() instead of BeginText(), EndText() and all of the lines you added in-between. Those methods are meant for people who speak PDF syntax.
One of the part of my project is RichTextBox with string length form 10 to 50 chars, and font's size 175-225 in single line. I use special printer: 100 mm height, and 3000 mm (3m) width ribbon. Very long width is a real problem.
I've got problem with Printing.PaperSize width element (I have to use it). It's (MSDN) "The width of the paper, in hundredths of an inch".
I tried to get this from:
RichTextBox1.PreferredSize.Width
g.MeasureString(RichTextBox1.Text, RichTextBox1.Font).Width
g.MeasureCharacterRanges(Text, Font, Rect, Format)
All of them gives me "pixels" but I have no idea how can I use it with Printing.PaperSize - all of them are too short, and dependent on used font family.
Tricky part of this is that I need very precise length of my PaperSize, because I have to print several items before and after the string.
Is any way to estimate printed width (in cm/inches) when I have only pixel size of element?
If anyone can give me any answer in C#, or C++ it doesn't matter - I will be grateful.
You can measure the width of the string in a given font:
Sub ShowWidthOfText(s As String)
Using img As New Bitmap(1, 1)
img.SetResolution(300, 300)
Using f As New Font("Times New Roman", 225, GraphicsUnit.Point)
Using g = Graphics.FromImage(img)
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
Dim w = g.MeasureString(s, f)
MessageBox.Show(String.Format("{0} pixels = {1:N2} cm at {2} ppi", w.Width, w.Width * 2.54 / g.DpiX, g.DpiX))
End Using
End Using
End Using
End Sub
which gives 90.75 cm (35.73 in) for "lorem ipsum dolor sit amet" in the font you suggest, which seems reasonable to me. If you are intending to set the the width of the paper size from that, you would of course need a minimum of 3573 hundredths of an inch.
If you want to fit the text to a particular width, it would probably be best to use a successive approximation method rather than a direct calculation because the kerning of the text may depend on the size of the font.
The .SetResolution is in there in case you use that code to construct your output, it makes no difference to the measurement.
(The resolution names in .NET are wrong: they should be, e.g. PpiX rather than DpiX etc.)
Ref: Measure a String without using a Graphics object?