I want to add a new FreeText comment to a PDF file with vba.
Public Sub AddAnnot(Page As Object, Text As String)
Dim Rect As Object, Annot As Object
Set Rect = CreateObject("AcroExch.Rect")
Dim Space As Integer, Height As Integer
Space = 0
Height = 15
With Rect
.bottom = Space
.Left = Space
.Right = Page.GetSize.x - Space
.Top = Space + Height
End With
Set Annot = Page.AddNewAnnot(0, "FreeText", Rect)
With Annot
.SetTitle Text
.SetContents (Text)
.SetColor RGB(255, 255, 0)
.SetRect Rect
End With
End Sub
So this code worked with older versions of Acrobat, but now in Acrobat DC, it always fails at the line .SetContents (Text) with the simple error, that the method has failed. It doesnt matter, which pdf-file it is, it always fails.
What am i doing wrong?
Thanks in advance
For everyone who was desperately searching for a solution to this, but didn't find one: Before the whole procedure of adding Annots, open the document as an AVDoc, too. You don't have to use it, just opened and it works, even when you instantly hide it.
Related
it's been a while since I posted. Haven't had much time for programming for a while. Just got back into it a couple of days ago. I'm working on a personal project which is a kind of Project Manager with a fairly complete text editor. I am working with VB.NET in the Visual Studio IDE. I have been trying to mimic the behaviour of Word and other editors as follows:
FONT FAMILY: This code actually works to change the Font Family in the Font Picker Combo Box in real time according to text formatting at cursor position. i.e. click on different text formats in the Rich Text Box and the Font Family is displayed in the Combo Box! I am using a Tool Strip Combo Box!
BUG: The Font Family code (i.e. penultimate snippet) removes the formatting from text when it is reselected after formatting?
FONT SIZE: This code changes the Font Size in the Font Size Combo Box when Ctrl+Shift+< OR Ctrl+Shift+> keyboard shortcuts are used.
BUG: The Font Size code (i.e. Last snippet) affects Font Size when using the ,.<> keys because these keys are configured in the code to alter the value of the Font size in the Font Size ComboBox. So, pressing the keys causes the Font Size in the Combo Box to increase or decrease which also means the font in the RTB increases or decreases?!
WHAT I NEED: 1. Selecting formatted text should not remove formatting, but Font Family should be displayed in Combo Box according to formatting in the RTB. 2. The Font Size Combo Box value should only be altered when I use the keyboard shortcuts, Ctrl+Shift+< OR Ctrl+Shift+> to display the true Font Size in real time. Using the current code increments/reduces in steps of 2 rather than one Font Size at a time??? I realize this code is fairly simple and understand roughly why it's not working, but I can't seem to find a way to fix the issue? Any help would be greatly appreciated!
WHAT I HAVE TRIED
Rich Text Box (i.e. RTB = Description):
FONT FAMILY COMBO BOX CODE: (uses a timer)
Private Sub tbSelectFont_SelectedIndexChanged(sender As Object, e As EventArgs) Handles tbSelectFont.SelectedIndexChanged
Dim NewFont As New Font(tbSelectFont.SelectedItem.ToString(),
Description.SelectionFont.Size,
Description.SelectionFont.Style)
Description.SelectionFont = NewFont
End Sub
FONT SIZE COMBO BOX CODE:
Private Sub tbSelectSize_SelectedIndexChanged(sender As Object, e As EventArgs) Handles tbSelectSize.SelectedIndexChanged
Dim NewSize As Single = tbSelectSize.SelectedItem
Dim NewFont As New Font(Description.SelectionFont.Name, NewSize, Description.SelectionFont.Style)
Description.SelectionFont = NewFont
End Sub
RELATED FORM LOAD EVENTS:
'Display Installed Fonts In Font Picker (tbSelectFont):
Dim fonts As New InstalledFontCollection()
For fntFamily As Integer = 0 To fonts.Families.Length - 1
tbSelectFont.Items.Add(fonts.Families(fntFamily).Name)
Next
'Display Font Size in Font Size Picker:
For fntSize = 10 To 75
tbSelectSize.Items.Add(fntSize)
Next
FONT FAMILY:
Private Sub Description_SelectionChanged(sender As Object, e As EventArgs) Handles Description.SelectionChanged
If Description.SelectionFont IsNot Nothing Then
Dim fontSize As Single = Description.SelectionFont.Size
tbSelectSize.Text = fontSize
tbSelectFont.Text = Description.SelectionFont.Name
End If
End Sub
FONT SIZE:
If (Keys.Control AndAlso Keys.Shift AndAlso e.KeyCode = Keys.Oemcomma) Then
tbSelectSize.Text -= 1
ElseIf (Keys.Control AndAlso Keys.Shift AndAlso e.KeyCode = Keys.OemPeriod) Then
tbSelectSize.Text += 1
End If
OTHER CODE I TRIED:
THIS CODE WORKS, BUT WHEN YOU SELECT FORMATTED TEXT IT THROWS AN EXCEPTION OR REMOVES FORMATTING: System.NullReferenceException: 'Object reference not set to an instance of an object.'
SOURCE: MY OWN COMMENT FROM:
how to get the fontsize of a certain line in a richtextbox in c# using winforms
Dim fontName As String = Description.SelectionFont.Name
Dim fontSize As Single = Description.SelectionFont.Size
tbSelectFont.Text = fontName
tbSelectSize.Text = fontSize
tbSelectFont.SelectedIndex = tbSelectFont.FindStringExact(Description.SelectionFont.Name)
tbSelectSize.SelectedIndex = tbSelectSize.FindStringExact(Description.SelectionFont.Size)
THIS CODE WORKS, BUT WHEN YOU SELECT FORMATTED TEXT IT THROWS AN EXCEPTION: System.NullReferenceException: 'Object reference not set to an instance of an object.'
SOURCE: how to get the fontsize of a certain line in a richtextbox in c# using winforms - MarkusEgle's solution.
Dim comboBox1Index As Integer = tbSelectFont.FindStringExact(Description.SelectionFont.Name)
Dim comboBox2Index As Integer = tbSelectSize.FindStringExact(Description.SelectionFont.Size.ToString())
tbSelectFont.SelectedIndex = comboBox1Index
tbSelectSize.SelectedIndex = comboBox2Index
I have added an image to my iTextSharp PDF document like this:
Public Sub CreatePDFFromBitmap(ByVal uPath As String, ByVal uBitmap As Bitmap)
Dim nFs As System.IO.FileStream = New FileStream(uPath, FileMode.Create)
Dim nDocument As iTextSharp.text.Document
Dim nWriter As iTextSharp.text.pdf.PdfWriter
Dim nCb As iTextSharp.text.pdf.PdfContentByte
Dim nImgFromBitmap As System.Drawing.Image = DirectCast(uBitmap, System.Drawing.Image)
Dim nImg As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(nImgFromBitmap, Imaging.ImageFormat.Png)
Dim bLandscape As Boolean = (nImg.Width > nImg.Height)
'rotation needs to be set before document is being opened
If bLandscape Then
nDocument = New iTextSharp.text.Document(PageSize.A4.Rotate, 0, 0, 0, 0)
Else
nDocument = New iTextSharp.text.Document(PageSize.A4, 0, 0, 0, 0)
End If
'if an exception is raised here, the following will help: https://stackoverflow.com/questions/15833285/pdfwriter-getinstance-throws-system-nullreferenceexception
nWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(nDocument, nFs)
nDocument.Open()
nCb = nWriter.DirectContent
nImg.ScaleToFit(nDocument.PageSize.Width, nDocument.PageSize.Height) 'raises dpi size :-)))
'X-Y-Koordinatensystem 0,0 startet also unten links, nicht oben-links
nImg.SetAbsolutePosition(0, nDocument.PageSize.Height - nImg.ScaledHeight)
nCb.AddImage(nImg)
nDocument.Close()
nWriter.Close()
nFs.Close()
End Sub
It works fine.
However, when I click the image in the PDF, it gets selected.
This is not what I want.
If I click the image in the PDF, it should not be selected.
This is what it looks like: The image becomes blue:
I want to add editable fields to the PDF, so I need to make the image not selectable, else it would confuse the user.
As Abdel-Rahman Al-Qawasmi mentions in his answer, it is completely up to the PDF viewer which entities it makes selectable and which not. Thus, there is no guaranteed way to get what you want.
Nonetheless, there are ways to put an image into a PDF which dissuade current versions of most PDF viewers from making it selectable. These ways either transform the bitmap image into a non-bitmap entity (e.g. by iterating over the pixels of the bitmap and drawing a little rectangle per pixel using vector graphics) or wrap the bitmap image into something that usually is not selectable.
Let's take the latter approach and wrap the image into a page-size PDF pattern with which we then fill the actual page. You can do that by replacing your
nCb.AddImage(nImg)
by
Dim painter As iTextSharp.text.pdf.PdfPatternPainter = nCb.CreatePattern(nDocument.PageSize.Width, nDocument.PageSize.Height)
painter.AddImage(nImg)
nCb.SetColorFill(New iTextSharp.text.pdf.PatternColor(painter))
nCb.Rectangle(0, 0, nDocument.PageSize.Width, nDocument.PageSize.Height)
nCb.Fill()
(This essentially is the VB/iTextSharp pendant of the Java/iText code from this answer.)
This is a pdf program specifications and not related to asp.net or vb.net programming. you need to have control of the pdf reader settings. Or try to use another format.
I'm working on a VB.NET 4.5 project in VS2013.
I have a richtextbox on a form and when a button is clicked I need to toggle the BOLD setting on all instances of a specific string found in the richtextbox.
I put together some code based on this question.
Private Sub ToggleBold()
rtxtOutputText.SelectionStart = rtxtOutputText.Find("##$%", RichTextBoxFinds.None)
rtxtOutputText.SelectionFont = New Font(rtxtOutputText.Font, FontStyle.Bold)
End Sub
However when the toggle bold button is clicked it only bolds the first instance of the string "##$%".
How can I set all instances of the string to bold? There can also be several of them strung together ("##$%##$%##$%"), so each of those would need to be bolded too.
(I know I mentioned toggling bold, but I'll set up the toggle portion later, right now I'm just trying to get the bold on all instances working right...)
Just add a loop to it and use the RichTextBox.Find(String, Int32, RichTextBoxFinds) overload to specify from where to start looking. Look from the current index + 1 so that it doesn't return the same again.
You also ought to actually select the word as well, so that you're sure the bold applies to the current instance only and not the text around it.
Private Sub ToggleBold()
'Stop the control from redrawing itself while we process it.
rtxtOutputText.SuspendLayout()
Dim LookFor As String = "##$%"
Dim PreviousPosition As Integer = rtxtOutputText.SelectionStart
Dim PreviousSelection As Integer = rtxtOutputText.SelectionLength
Dim SelectionIndex As Integer = -1
Using BoldFont As New Font(rtxtOutputText.Font, FontStyle.Bold)
While True
SelectionIndex = rtxtOutputText.Find(LookFor, SelectionIndex + 1, RichTextBoxFinds.None)
If SelectionIndex < 0 Then Exit While 'No more matches found.
rtxtOutputText.SelectionStart = SelectionIndex
rtxtOutputText.SelectionLength = LookFor.Length
rtxtOutputText.SelectionFont = BoldFont
End While
End Using
'Allow the control to redraw itself again.
rtxtOutputText.ResumeLayout()
'Restore the previous selection.
rtxtOutputText.SelectionStart = PreviousPosition
rtxtOutputText.SelectionLength = PreviousSelection
End Sub
Credit to Plutonix for telling me to dispose the font.
I've edited a code I found to gets all the outline data of a text so I can manually draw it as lines in some other program.
My code works great in English, but when I try to send Hebrew text the outlines turn to be in gibberish font.
The main steps of the code are:
Typeface -> GlyphTypeface -> GlyphRun
And the main code is
Private m_gtf As System.Windows.Media.GlyphTypeface
Private m_glypText As GlyphRun
Private m_textFont As System.Drawing.Font
textFont = New Font("Aharoni", 12, FontStyle.Regular, GraphicsUnit.World, 177, False)
m_typeface = New Typeface(New System.Windows.Media.FontFamily(m_textFont.Name), m_fontStyle, _
m_fontWeight, New System.Windows.FontStretch())
m_typeface.TryGetGlyphTypeface(m_gtf)
'then use m_gtf to crate the m_glyphIndices and advanceWidths vectors
m_glypText = New GlyphRun(m_gtf, bidiLevel, False, m_height, m_glyphIndices, origin, advanceWidths, _
Nothing, Nothing, Nothing, Nothing, Nothing, Nothing)
I think that my problem is with the "m_typeface = New Typeface(…"
In this command there is no way to send the font gdiCharSet value.
Is there a way to get the typeface straight from the m_textFont?
Or is there another way to do this?
Zohar
Found the problem.
I was using:
Dim glyphIndex As UShort = m_gtf.CharacterToGlyphMap(Asc(m_textString(n)))
but I had to use AscW to get the correct ascii code:
Dim glyphIndex As UShort = m_gtf.CharacterToGlyphMap(AscW(m_textString(n)))
now it works!
Zohar
I have to create dynamic table layout panel with some controls with auto sized rows and and fixed columns size.
My problem is that i want to show whole checkbox text .
Any help
My code is
Dim textBox2 As New CheckBox()
textBox2.Text = "You forgot to add the ColumnStyles. Do this on a sample form first with the designer. Click the Show All Files icon in the Solution Explorer window. Open the node next to the form and double-click the Designer.vb file. "
textBox2.AutoSize = True
textBox2.Dock = DockStyle.Top
'' textBox2.Size = New Point(200, 90)
Dim lbl1 As New Label()
lbl1.Location = New Point(10, 10)
lbl1.Text = "Yoer.vb"
lbl1.AutoSize = True
lbl1.Location = New Point(120, 50)
lbl1.Dock = DockStyle.Top
'' dynamicTableLayoutPanel.Padding = New Padding(2, 17, 4, 5)
dynamicTableLayoutPanel.Controls.Add(lbl1, 0, 0)
dynamicTableLayoutPanel.Controls.Add(textBox2, 1, 0)
Me.dynamicTableLayoutPanel.SetColumnSpan(textBox2, 5)
If you mean you want the table to size to the controls within it, then:
dynamicTableLayoutPanel.AutoSize = True
I know this is old, but I stumbled across it and figured I'd throw my 2 cents in in case someone else comes along.
Note: I'm using Visual Studio 2015 with .NET 4.6. Functionality may differ between versions.
The problem is that the really long text is not word-wrapping to fit within the table or form. Instead, it is set to Dock = DockStyle.Top. This will cause it to make a single line that continues on and gets clipped, similar to a single-line textbox.
If you want it to automatically word wrap, you'll need to use Dock = DockStyle.Fill. Now, this doesn't completely resolve the problem if your row or table isn't large enough to display the text. Since all of the rows are set to AutoSize, it will only do the bare minimum to fit the control vertically. It doesn't care if text gets clipped off. The end result, using your example code against a 6-column, 10-row table, is this:
Since there isn't a word wrap property, you'll need to manually fit it. Now, to do this, you'll need to change the row to be Absolute instead of AutoSize. To figure out how big to make it, you can pretty much rely on PreferredSize. This reveals a much wider Width than the existing regular Width. From that, we can determine how many lines it would take if we wrap it.
This is what my code ended up looking like:
Dim h As Single = 0
Dim chk As New CheckBox()
chk.Text = "You forgot to add the ColumnStyles. Do this on a sample form first with the designer. Click the Show All Files icon in the Solution Explorer window. Open the node next to the form and double-click the Designer.vb file. "
chk.AutoSize = True
chk.Dock = DockStyle.Fill
Dim lbl1 As New Label()
lbl1.Text = "Yoer.vb"
lbl1.AutoSize = True
lbl1.Dock = DockStyle.Top
dynamicTableLayoutPanel.Controls.Add(lbl1, 0, 0)
dynamicTableLayoutPanel.Controls.Add(chk, 1, 0)
dynamicTableLayoutPanel.SetColumnSpan(chk, 5)
' Find the preferred width, divide by actual, and round up.
' This will be how many lines it should take.
h = Math.Ceiling(chk.PreferredSize.Width / chk.Width)
' Multiply the number of lines by the current height.
h = (h * chk.PreferredSize.Height)
' Absolute size the parent row to match this new height.
dynamicTableLayoutPanel.RowStyles.Item(0) = New RowStyle(SizeType.Absolute, h)
The changes included delaring a height variable, renaming the CheckBox variable, setting its Dock to Fill, removing the Location from lbl1, and adding in size calculation. The output:
This isn't perfect since the height includes the checkbox itself, and the checkbox takes up padding, so there can be too much or too little height calculated. There are other calculations that may need to be considered. But, this is a starting point.