Missing Property in Visual Studio 2017 Community RichTextBox - vb.net

Win 7, VS 2017 Community, Framework 4.6.1, RichTextBox Version 4.6.1.0
I am using a RichTextBox and am trying to center the RichTextBox, both Horizontally and Vertically, in a Panel. However, the RichTextBox control is missing the property ClientSize. MicroSoft documentation shows the property exists. I am totally lost and welcome help.
A single or Multiline TextBox.Text has been placed
in the RichTextBox prior to calling this routine
Private Sub CenterRtb()
Dim LineSize As SizeF
Dim RtbW As Single ' RichTextBox Width
Dim RtbH As Single ' RichTextBox Height
Dim LocX As Integer
Dim LocY As Integer
' Find Longest Line and Total Height Of Lines
RtbW = 0
RtbH = 0
For Each Line As String In rtbText.Lines
cMetrics is predefined class for measuring Text strings using g.MeasureText
LineSize = cMetrics.Metrics.GetTexTSize(Line, rtbText.Font)
If (LineSize.Width > RtbW) Then RtbW = LineSize.Width
RtbH = RtbH + LineSize.Height
Next
Note: Would Prefer ClientSize rather than RichTextBox physical size.
' Adjust For RichTextBox Actual Size
If (RtbW > rtbText.Width) Then RtbW = rtbText.Width
If (RtbH > rtbText.Height) Then RtbH = rtbText.Height - 10
rtbText.Width = CInt(RtbW)
rtbText.Height = CInt(RtbH + 20)
LocX = CInt((pnlRtb.Width - rtbText.Width) / 2)
LocY = CInt((pnlRtb.Height - rtbText.Height) / 2)
rtbText.Location = New Point(LocX, LocY)
End Sub

Related

Is there a way to use the graphics class methods (Graphics.DrawString or Graphics.DrawLine) for a PrintDocumet outside of the PrintPage event?

I'm rewriting a VB6 application in VB.net. Instead of using the VB6 printer namespace, I'm trying make the code natively VB.net compatible.
The VB6 application has a bunch of printer.print statements as well as a bunch of printer.line statements. (I believe the lines use TWIPs.) Here is an example of some of the lines.
Printer.DrawWidth = 1.5
Printer.Line (200, 12940)-(11275, 12940)
Printer.Line (200, 13680)-(6660, 13680)
Printer.Line (6712, 13680)-(11275, 13680)
Printer.FillStyle = vbFSTransparent
Printer.DrawWidth = 1
Printer.DrawStyle = vbDashDot
Printer.Circle (5700, 6000), draw_scale * BC_Diam / 2
media.FontItalic = True
Printer.Print "some text"
media.FontItalic = False
Printer.Print "additional, non italic text"
The only way I've been able to find how to do any of this in VB.net is by using the PrintDocument's PrintPage event. A problem with doing it this way is you have to pass all of the text to this subroutine all at once and deal with a "printArea" for word wrap. Another problem is it makes it very difficult to switch between italic and non italic text. In the same way for text, I think I would have to pass in all of the line/circle coordinates as well, then draw them from the event subroutine.
Private Sub document_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles document.PrintPage
Dim printFont As Font = New Font("Courier New", 8.5, FontStyle.Regular)
' Set print area size and margins
With document.DefaultPageSettings
Dim leftMargin As Integer = .Margins.Left 'X
Dim topMargin As Integer = .Margins.Top 'Y
Dim printHeight As Integer = .PaperSize.Height - topMargin * 2
Dim printWidth As Integer = .PaperSize.Width - leftMargin * 2
End With
' Check if the user selected to print in Landscape mode
' if they did then we need to swap height/width parameters
If document.DefaultPageSettings.Landscape Then
Dim tmp As Integer
tmp = printHeight
printHeight = printWidth
printWidth = tmp
End If
Dim lines As Int32
Dim chars As Int32
'Now we need to determine the total number of lines
'we're going to be printing
Dim numLines As Int32 = CInt(printHeight / printFont.Height)
' Create a rectangle printing are for our document
Dim printArea As New RectangleF(leftMargin, topMargin, printWidth, printHeight)
' Set format of string.
Dim format As New StringFormat(StringFormatFlags.LineLimit)
e.Graphics.MeasureString(txtText.Text.Substring(curChar), printFont, New SizeF(printWidth, printHeight), format, chars, lines)
e.Graphics.DrawString(txtText.Text.Substring(curChar), printFont, Brushes.Black, printArea, format)
'Increase current char count
curChar += chars
'Detemine if there is more text to print, if
'there is the tell the printer there is more coming
Debug.Print("curChar < txtText.Text.Length:" & (curChar < txtText.Text.Length))
If curChar < txtText.Text.Length Then
e.HasMorePages = True
Else
e.HasMorePages = False
curChar = 0
End If
End Sub
There has to be a better way to do this, right? How I can call Graphics.DrawLine, Graphics.DrawEllipse, Graphics.DrawString, etc. for the PrintDocument from outside of the PrintPage event in VB.net like you could in VB6?

Location and Size of the controls on a Form change after the Form is maximized

I have a Form called formmain. When I open another Form, formmain is minimized.
My problem is that when I restore formmain, the Location and Size of the controls on it have changed completely.
I am using the following method when the Form is resized:
Public Sub ResizeForm(ObjForm As Form, DesignerHeight As Integer, DesignerWidth As Integer)
'#Region "Code for Resizing and Font Change According to Resolution"
'Specify Here the Resolution Y component in which this form is designed
'For Example if the Form is Designed at 800 * 600 Resolution then DesignerHeight=600
Dim i_StandardHeight As Integer = DesignerHeight
'Specify Here the Resolution X component in which this form is designed
'For Example if the Form is Designed at 800 * 600 Resolution then DesignerWidth=800
Dim i_StandardWidth As Integer = DesignerWidth
Dim i_PresentHeight As Integer = Screen.PrimaryScreen.Bounds.Height
'Present Resolution Height
Dim i_PresentWidth As Integer = Screen.PrimaryScreen.Bounds.Width
'Presnet Resolution Width
f_HeightRatio = CSng(CSng(i_PresentHeight) / CSng(i_StandardHeight))
f_WidthRatio = CSng(CSng(i_PresentWidth) / CSng(i_StandardWidth))
ObjForm.AutoScaleMode = AutoScaleMode.None
'Make the Autoscale Mode=None
ObjForm.Scale(New SizeF(f_WidthRatio, f_HeightRatio))
For Each c As Control In ObjForm.Controls
If c.HasChildren Then
ResizeControlStore(c)
Else
c.Font = New Font(c.Font.FontFamily, c.Font.Size * f_HeightRatio, c.Font.Style, c.Font.Unit, CByte(0))
End If
Next
ObjForm.Font = New Font(ObjForm.Font.FontFamily, ObjForm.Font.Size * f_HeightRatio, ObjForm.Font.Style, ObjForm.Font.Unit, CByte(0))
End Sub

iTextSharp Adding Background Color to Watermark Text

I am adding watermark text to PDFs in a class library I have created. The code I posted below works fine, however the watermark is sometimes difficult to read because it overlays with content on the PDF. How would I go about adding a white background color around the watermark text? I basically would like the watermark text to be surrounded inside a white rectangle the size of the text. Thanks
Public Function AddWatermarkText(ByVal tempDirectory As String) As String
' Just return the full path of the PDF if we don't need to add a watermark.
If Me.Document.RevRank <> 0 OrElse Me.Document.ReleaseDate Is Nothing Then Return Me.FullPath
Dim reader As iTextSharp.text.pdf.PdfReader = Nothing
Dim stamper As iTextSharp.text.pdf.PdfStamper = Nothing
Dim gstate As New iTextSharp.text.pdf.PdfGState()
Dim overContent As iTextSharp.text.pdf.PdfContentByte = Nothing
Dim rect As iTextSharp.text.Rectangle = Nothing
Dim watermarkFont As iTextSharp.text.pdf.BaseFont = Nothing
Dim folderGuid As Guid = Guid.NewGuid()
Dim outputFile As String = tempDirectory & System.IO.Path.DirectorySeparatorChar & folderGuid.ToString() & System.IO.Path.DirectorySeparatorChar _
& Me.Document.Prefix & Me.Document.BaseNumber & Me.Document.Revision & ".pdf"
' Create the temp directory to place the new PDF in.
If Not My.Computer.FileSystem.DirectoryExists(tempDirectory) Then My.Computer.FileSystem.CreateDirectory(tempDirectory)
My.Computer.FileSystem.CreateDirectory(tempDirectory & System.IO.Path.DirectorySeparatorChar & folderGuid.ToString())
reader = New iTextSharp.text.pdf.PdfReader(Me.FullPath)
rect = reader.GetPageSizeWithRotation(1)
stamper = New iTextSharp.text.pdf.PdfStamper(reader, New System.IO.FileStream(outputFile, IO.FileMode.Create))
watermarkFont = iTextSharp.text.pdf.BaseFont.CreateFont(iTextSharp.text.pdf.BaseFont.HELVETICA_BOLD, _
iTextSharp.text.pdf.BaseFont.CP1252, _
iTextSharp.text.pdf.BaseFont.NOT_EMBEDDED)
gstate.FillOpacity = 0.9F
gstate.StrokeOpacity = 1.0F
' Add the watermark to each page in the document.
For i As Integer = 1 To reader.NumberOfPages()
overContent = stamper.GetOverContent(i)
With overContent
.SaveState()
.SetGState(gstate)
.SetColorFill(iTextSharp.text.BaseColor.BLUE)
.Fill()
.BeginText()
.SetFontAndSize(watermarkFont, 8)
.SetTextMatrix(30, 30)
If Me.Document.RevRank = 0 AndAlso Me.Document.ReleaseDate IsNot Nothing Then
.ShowTextAligned(iTextSharp.text.Element.ALIGN_LEFT, UCase(String.Format("CONTROLLED DOCUMENT – THIS COPY IS THE LATEST REVISION AS OF {0}" _
, Date.Now.ToString("ddMMMyyyy"))), 10, rect.Height - 15, 0)
End If
.Fill()
.EndText()
.RestoreState()
End With
Next
stamper.Close()
reader.Close()
Return outputFile
End Function
I usually like to have code that you can just plop in but unfortunately you're code is a little too domain-specific to provide a direct answer (lots of Me.* that we have to guess at) but I can still get you there with a little code refactoring.
To do what you want to do you have to measure the string that you are drawing and then draw a rectangle to those dimensions. The PDF spec doesn't have a concept of "background color" for text and any implementation that makes it look like it does is really just drawing rectangles for you. (Yes, you can highlight text but that's an Annotation which is different.)
So first I'm going to pull things out into variables so that we can reuse and adjust them easier:
''//Text to measure and draw
Dim myText As String = UCase(String.Format("CONTROLLED DOCUMENT – THIS COPY IS THE LATEST REVISION AS OF {0}", Date.Now.ToString("ddMMMyyyy")))
''//Font size to measure and draw with
Dim TextFontSize As Integer = 8
''//Original X,Y positions that we were drawing the text at
Dim TextX As Single = 10
Dim TextY As Single = rect.Height - 15
Next we need to calculate the width and height. The former is easy but the latter requires us to first get the Ascent and Descent of the text and then calculate the difference.
''//Calculate the width
Dim TextWidth As Single = watermarkFont.GetWidthPoint(myText, TextFontSize)
''//Calculate the ascent and decent
Dim TextAscent As Single = watermarkFont.GetAscentPoint(myText, TextFontSize)
Dim TextDescent As Single = watermarkFont.GetDescentPoint(myText, TextFontSize)
''//The height is the difference between the two
Dim TextHeight As Single = TextAscent - TextDescent
(NOTE: I'm not sure if GetWidthPoint(), GetAscentPoint() and GetDescentPoint() work as desired with multi-line text.)
Then you probably want to have some padding between the box and text:
''//Amount of padding around the text when drawing the box
Dim TextPadding As Single = 2
Lastly, somewhere before you setup and draw the text you want to first draw the rectangle:
''//Set a background color
.SetColorFill(BaseColor.YELLOW)
''//Create a rectangle
.Rectangle(TextX - TextPadding, TextY - TextPadding, TextWidth + (TextPadding * 2), TextHeight + (TextPadding * 2))
''//Fill it
.Fill()

Detect width of text in vb.net

Is there a way to detect the actual width of text in a vb.net web app? It needs to be dependant upon its font-style and size.
In vb6 you could copy the text into a label and make it expand to fit then measure its width, but this won't work in vb.net.
Update: On further inspection, TextRenderer.MeasureText seems a better option:
Dim text1 As String = "Measure this text"
Dim arialBold As New Font("Arial", 12.0F)
Dim textSize As Size = TextRenderer.MeasureText(text1, arialBold)
See Graphics.MeasureString:
Measures the specified string when
drawn with the specified Font.
Dim myFontBold As New Font("Microsoft Sans Serif", 10, FontStyle.Bold)
Dim StringSize As New SizeF
StringSize = e.Graphics.MeasureString("How wide is this string?", myFontBold)
i have just recently done this in one of my projects here is how i did it
Dim textsize As Size = TextRenderer.MeasureText(cbx_Email.Text, cbx_Email.Font)
cbx_Email.Width = textsize.Width + 17
this is in a combobox.SelectedIndex changed sub.
The +17 is for the pixels that the dropdown arrow takes up in a combobox so it doesntcover text.
by using control.font it allows the code to dynamically change no matter what font is being used. Using Control.Text means you can use this on anything and wont have to change the code when changing the text of the control or page.
I wrote this low-end function to do just that without higher-level API's.
It creates a bitmap and graphics object, writes the string to the bitmap, scans backwards for the font edge and then returns the width in pixels
Private Function FontLengthInPixels(inputString As String, FontStyle As Font) As Integer
' Pick a large, arbitrary number for the width (500) in my case
Dim bmap As New Bitmap(500, 100)
Dim g As Graphics = Graphics.FromImage(bmap)
g.FillRectangle(Brushes.Black, bmap.GetBounds(GraphicsUnit.Pixel))
g.DrawString(inputString, FontStyle, Brushes.White, New Point(0, 0))
' Scan backwards to forwards, since we know the first pixel location is 0,0; we need to find the LAST and subtract
' the bitmap width from it to find the width.
For x = -(bmap.Width - 1) To -1
' Scan from the 5th pixel to the 10th, we'll find something within that range!
For y = 5 To 10
Dim col As Color = bmap.GetPixel(Math.Abs(x), y)
' Look for white (ignore alpha)
If col.R = 255 And col.G = 255 And col.B = 255 Then
Return Math.Abs(x) ' We got it!
End If
Next
Next
' Lets do this approx
Return 0
End Function

How can I calculate the number of lines in a text box?

I am hoping that someone can help me with a problem I've got at the moment using Compact Framework.Net 2 SP 2.
At the moment I have a UI with a series of text boxes and each textbox displays the contents of a database field. These are shown one beneath another with a scroll bar on the right hand side of the form. Each textbox has a set width which might
I would like to adjust the height each text box based on the number of lines it is holding, the font size and the font in order to avoid using scroll bars on each textbox.
At the moment I am been able to do this in a test application.
Screenshot:
see screenshot for output http://morrislgn.brinkster.net/SO/screenshot.jpg
My code:
'Text used in this example:
'TextBox1qwertyuiop lkjhgfdsazxcvbnm1234567890 TextBo
'x1qwer tyuioplkjhgfdsazxcvb nm1234567890
'qwe
'End of exmaple text.
Me.Textbox2.Text = Me.Textbox1.Text
Dim pobjGraphic As Graphics = Me.Textbox2.Parent.CreateGraphics()
Dim pobjSize As SizeF
'Padding values:
Dim piTop As Int32 = 4 'top of text and top of textbox
Dim piBottom As Int32 = 3 'bottom of text and top of textbox
Dim piLines As Int32 = 0
'Based on the font size chosen by the user, create a font to perform the calculation with.
Dim piFontSize As Single = 10
If Me.CheckBox1.Checked.Equals(True) Then
piFontSize = 6
ElseIf Me.CheckBox2.Checked.Equals(True) Then
piFontSize = 8
ElseIf Me.CheckBox3.Checked.Equals(True) Then
piFontSize = 12
Else
piFontSize = 10
End If
Dim pobjFont As New Font("Tahoma", piFontSize, FontStyle.Regular)
'Calculate the height of one line.
pobjSize = pobjGraphic.MeasureString("HELLO WORLD", pobjFont)
'Value of pobjSize returned: {Width = 71.0 Height = 13.0}
'Calculate the number of lines
Dim b As Bitmap
b = New Bitmap(1, 1, Imaging.PixelFormat.Format32bppRgb)
'Calculate the number of lines required to display the text properly based on the lenght of the text the width of the control.
'Length of text to show divide by the width of the textbox
piLines = Graphics.FromImage(b).MeasureString(Me.Textbox2.Text, pobjFont).Width / Me.Textbox2.Width
'Value of piLines returned: 2
If piLines = 0 Then
piLines = 1
End If
'Calculate the size of the text to be displayed using the margins, height of one line and number of lines.
Me.Textbox2.Height = (pobjSize.Height * piLines) + piTop + piBottom
' value produced: 33 = (13 * 2) + 4 + 3
'set font of text box
Me.Textbox2.Font = pobjFont
Finally, I know this can be achieved using a call to the COREDLL.dll using p/invoke but doing this makes the application crash.
Hi Folks,
Below is the pinvoke code as requested:
<Runtime.InteropServices.DllImport("coredll.dll")> _
Private Function SendMessage( _
ByVal hwnd As IntPtr, ByVal msg As Integer, _
ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
<Runtime.InteropServices.DllImport("coredll.dll")> _
Private Function GetCapture() As IntPtr
End Function
<Runtime.InteropServices.DllImport("coredll.dll")> _
Private Function ReleaseCapture() As Boolean
End Function
Public Function GetNumberOfLines(ByVal ptxtCountBox As TextBox) As Integer
Try
Dim hnd As IntPtr = New IntPtr
ptxtCountBox.Capture = True
' Capture the textbox handle.
hnd = GetCapture()
ptxtCountBox.Capture = False
' Get the count of the lines in the box.
Dim plCount As Integer = SendMessage(ptxtCountBox.Handle, EM_GETLINECOUNT, 0, 0)
' Count the number of return lines as we minus this from the total lines to take.
plCount = plCount - (CharCount(ptxtCountBox.Text, vbCrLf, False))
plCount += RemoveNonASCIIReturns(ptxtCountBox)
ReleaseCapture()
hnd = Nothing
' Return the line count.
Return plCount
Catch ex As Exception
GenerateError(msCLASS_NAME, "GetNumberOfLines", ex.Message.ToString)
End Try
End Function
Thanks,
Morris
I asked a similar question and got an answer that completely satisfied my needs on the subject! Please check out stevo3000's answer from my question:
AutoSize for Label / TextBox in .NET Compact Framework
He referred to these two blog posts that just completely fixed my problem with one swipe!
http://www.mobilepractices.com/2007/12/multi-line-graphicsmeasurestring.html
http://www.mobilepractices.com/2008/01/making-multiline-measurestring-work.html
Think I got to the bottom of this:
Public Function GetNumberOfLines(ByVal pstext As String, ByVal pobjfont As Font, ByVal pobjDimensions As Size) As Decimal
Dim pslines As String() = Nothing
'Used to measure the string to be placed into the textbox
Dim pobjBitMap As Bitmap = Nothing
Dim pobjSize As SizeF = Nothing
Try
Dim psline As String = String.Empty
Dim pilinecount As Decimal = 0.0
'Spilt the text based on the number of lines breaks.
pslines = pstext.Split(vbCrLf)
For Each psline In pslines
'Create a graphics image which is used to work out the width of the text.
pobjBitMap = New Bitmap(1, 1, Imaging.PixelFormat.Format32bppRgb)
pobjSize = Graphics.FromImage(pobjBitMap).MeasureString(psline, pobjfont)
'If the width of the text is less than 1.0 then add one to the count. This would incidcate a line break.
If pobjSize.Width < 1.0 Then
pilinecount = pilinecount + 1
Else
'Based on the dimensions of the text, work out the number of lines. 0.5 is added to round the value to next whole number.
pilinecount = pilinecount + (Round((pobjSize.Width / pobjDimensions.Width) + 0.5))
End If
Next
'If the line count it less than 1 return one line.
If pilinecount < 1.0 Then
Return 1.0
Else
Return pilinecount
End If
Catch ex As Exception
Return 1.0
Finally
If pslines IsNot Nothing Then
Array.Clear(pslines, 0, pslines.Length - 1)
pslines = Nothing
End If
If pobjBitMap IsNot Nothing Then
pobjBitMap.Dispose()
End If
End Try
End Function
Granted, its a bit of a hack but it appears to work ok at the moment! Any observations or comments on how to improve this are more than welcome.
Also, about the p/invoke stuff, discovered the root of the problem, or rather the solution. Upgraded the .Net fx on my device and that appears to have resolved the issue.
Thanks
Morris
Well, I would suggest a sound and smart solution to you.
Here's is the Algorithm:
Use a Label control for reference.
Assign:
• The size of Textbox to the Label.
• The font of Textbox to the Label.
• Autosize-property of Label to be True.
• BorderStyle Property of the Label as of Textbox'.
• MinimumSize Property of Label as original size of the Textbox.
• MaximumSize Property of Label as Width-same as original and Height to be a large multiple the original height.
Assign the Textbox' Text to Label's text.
Now: if the PrefferdHeight-property of Label > Height of the Textbox == True
It's time to increase the height of the Textbox and check the above condition until it’s False.
The Label can be disposed off now.
I have also posted a similar solution in MSDN Forum which can also be checked out:
[http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/03fc8e75-fc13-417a-ad8c-d2b26a3a4dda][1]
Regards.
:)