I created a simple program that contains Labels and TextBoxes. I added a Button to export the entire interface with Labels and Textboxes to PDF but I get this error message:
Unable to cast object of type 'System.Windows.Forms.Panel' to type
'iTextSharp.text.IElement'.,
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim pdfDoc As New Document()
Dim pdfWrite As PdfWriter = PdfWriter.GetInstance(pdfDoc, New FileStream("C:\Users\Win 10\Desktop\simple.pdf", FileMode.Create))
pdfDoc.open()
pdfDoc.Add(Panel1)
pdfDoc.Add(Panel2)
pdfDoc.Add(TextBox1)
pdfDoc.Add(TextBox2)
pdfDoc.Close()
End Sub
You will need to convert the controls to Bitmap images, then drop them into the PDF.
I wrote this function that will take WinForms controls, convert them to Bitmap and then into iTextSharp.text.Image formats that can then be placed inside of a PDF.
Function ControlToPDFImage(ControlToConvert As Windows.Forms.Control)
Dim Bmp As Bitmap = New Bitmap(ControlToConvert.Width, ControlToConvert.Height)
ControlToConvert.DrawToBitmap(Bmp, New Drawing.Rectangle(0, 0, Panel1.Width, Panel1.Height))
Dim PDFImg As Image = iTextSharp.text.Image.GetInstance(Bmp, System.Drawing.Imaging.ImageFormat.Png)
Return PDFImg
End Function
So if you change your code to this, it should work:
pdfDoc.Add(ControlToPDFImage(Panel1))
pdfDoc.Add(ControlToPDFImage(Panel2))
pdfDoc.Add(ControlToPDFImage(TextBox1))
pdfDoc.Add(ControlToPDFImage(TextBox2))
Related
I am trying to take the contents of my project file and turning/export it as a PDF. For context, here is the layout of my project file:
Don't mind the numbers, I was just testing that part of the code, my only issue is finding a way in taking that project file and turning it into a PDF. I tried breaking down this task into two buttons, the 2) Save File and 3) Create PDF buttons, though now I'm just getting more confused the more I try to do this.
Here is my code for the "2) Save File" button:
Private Sub Screenshot_Click(sender As Object, e As EventArgs) Handles Screenshot.Click
Dim bmp As New Bitmap(Me.Width, Me.Height)
Me.DrawToBitmap(bmp, New Rectangle(0, 0, Me.Width, Me.Height))
PictureBox1.Image = bmp
bmp.Save(My.Computer.FileSystem.SpecialDirectories.Desktop & "\" & ".png", Imaging.ImageFormat.Png)
SaveFileDialog1.ShowDialog()
SaveFileDialog1.Title = "Save file"
SaveFileDialog1.InitialDirectory = "E:\French"
Dim location As String
location = SaveFileDialog1.FileName
bmp.Save(SaveFileDialog1.ShowDialog())
End Sub
The 3) Create PDF button doesn't currently have any special code, all I did was to try and create a bitmap and then taking that bitmap and turning it into a PDF:
Private Sub PDFbutton_Click(sender As Object, e As EventArgs) Handles PDFbutton.Click
Dim bmpScreenshot As Bitmap = New Bitmap(Width, Height, PixelFormat.Format32bppArgb)
' Create a graphics object from the bitmap
Dim gfxScreenshot As Graphics = Graphics.FromImage(bmpScreenshot)
' Take a screenshot of the entire Form1
gfxScreenshot.CopyFromScreen(Me.Location.X, Me.Location.Y, 0, 0, Me.Size, CopyPixelOperation.SourceCopy)
' Save the screenshot
bmpScreenshot.Save("D:\Form1.jpg", ImageFormat.Jpeg)
End Sub
Just started working on vb.net, so I'm still new at this. I'll gladly take any help and/or advice!
I have a PictureBox added to my Panel1 with Panel1.Controls.Add(pb), and I have tried to make my .png picture transparent.
I have tried with Color.Transparent and with System.Drawing.Color.Transparent, but when I add the PictureBox to my Panel, I can not make it transparent.
And also I'm not able to bring to the front of the others images.
This is my code.
Private Function molduraint()
Dim pb As New PictureBox
pb.BringToFront()
pb.ImageLocation = OpenFileDialog1.FileName
pb.SizeMode = PictureBoxSizeMode.StretchImage
Panel1.Controls.Add(pb)
pb.Location = New Point(txtValueX.Text, txtValueY.Text)
If txtValueX.Text = 0 Or txtValueY.Text = 0 Then
pb.Location = New Point(300, 172)
End If
pb.Visible = True
pb.Size = New Size(TrackBar1.Value, TrackBar2.Value)
pb.Image = PictureBox1.Image
End Function
As you probably know, WinForms controls are not exactly designed to support true transparency (except Forms, those can be actually transparent).
Bitmaps, on the other hand, support transparency.
If you create a Bitmap object using an image format that supports an Alpha Channel, like a .png bitmap, you can draw that image preserving its transparency.
The first thing to do is to create an object that can be used to reference each Bitmap we want to draw, so we can keep track of them.
Since you want to be able to specify position and size of these objects, those are two of the properties that the object must have. I'm adding some more that can be helpful here.
Public Class BitmapObject
Public Property Name As String
Public Property Image As Bitmap
Public Property Position As Point
Public Property Size As Size
Public Property Order As Integer
End Class
The property Name will be the name of source file and Order will reference the z-order position of the Bitmap in relation to the other Bitmaps drawn inside a container.
All the Bitmaps will be grouped using a List of Bitmap objects, so we can summon them using the List Index or one of the properties.
Public MyBitmaps As List(Of BitmapObject) = New List(Of BitmapObject)
As for the drawing surface (canvas), we can use the Form itself, a PictureBox or a Panel (because they're - more or less - just surfaces). I prefer a Panel, it's lightweight, it can host other controls and can be moved around if needed.
If you want to draw on a control, you just need to subscribe its Paint() event and raise it calling the control's Invalidate() method.
Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
If MyBitmaps.Count > 0 Then
MyBitmaps.OrderBy(Function(item) item.Order).
Select(Function(item)
e.Graphics.DrawImage(item.Image, New Rectangle(item.Position, item.Size))
Return item
End Function).ToList()
End If
End Sub
To add a Bitmap to the List(Of BitmapObject), since you want to use an OpenFileDialog to let the user select a Bitmap, we assign this functionality to a Button and when the Bitmap is selected, a new BitmapObject is created and appended to the List.
Private Sub btnOpenFile_Click(sender As Object, e As EventArgs) Handles btnOpenFile.Click
Dim fd As OpenFileDialog = New OpenFileDialog()
fd.InitialDirectory = "[Images Path]"
Dim dr As DialogResult = fd.ShowDialog()
If dr = Windows.Forms.DialogResult.OK Then
Dim BitmapName As String = New FileInfo(fd.FileName).Name
Using tmpBitmap As Bitmap = New Bitmap(fd.FileName)
MyBitmaps.Add(New BitmapObject With {
.Image = New Bitmap(tmpBitmap),
.Position = New Point(Integer.Parse(TextBox1.Text), Integer.Parse(TextBox2.Text)),
.Size = New Size(tmpBitmap.Height, tmpBitmap.Width),
.Order = MyBitmaps.Count,
.Name = BitmapName})
ComboBox1.Items.Add(BitmapName)
ComboBox1.SelectedIndex = MyBitmaps.Count - 1
TrackBar1.Value = tmpBitmap.Height
TrackBar2.Value = tmpBitmap.Width
Panel1.Invalidate()
End Using
End If
End Sub
This is the result: (Full source code in PasteBin)
I already manage to convert the image file to pdf file.. but i want to make it automatically save to specific location and without it asking me where to save it. Please help me, any help would be appreciated. Beginner here. Here is the code that im currently trying.
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Text
Imports System.Windows.Forms
Imports PdfSharp.Pdf
Imports PdfSharp.Drawing
Imports System.IO
Public Class Form1
Private Sub captureScreen()
'Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim graph As Graphics = Nothing
Try
' gets the upper left hand coordinate of the form
Dim frmleft As System.Drawing.Point = Me.Bounds.Location
'use the commented out version for the full screen
'Dim bmp As New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
'this version get the size of the form1 The + 8 adds a little to right and bottom of what is captured.
Dim bmp As New Bitmap(Me.Bounds.Width + 8, Me.Bounds.Height + 8)
'creates the grapgic
graph = Graphics.FromImage(bmp)
'Gets the x,y coordinates from the upper left start point
'used below
Dim screenx As Integer = frmleft.X
Dim screeny As Integer = frmleft.Y
' The - 5 here allows more of the form to be shown for the top and left sides.
graph.CopyFromScreen(screenx - 5, screeny - 5, 0, 0, bmp.Size)
' Save the Screenshot to a file
bmp.Save("I:\eQA\temp.png")
bmp.Dispose()
graph.Dispose()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
captureScreen()
' Create new pdf document and page
Dim doc As New PdfDocument()
Dim oPage As New PdfPage()
' Add the page to the pdf document and add the captured image to it
doc.Pages.Add(oPage)
'Dim xgr As XGraphics = XGraphics.FromPdfPage(oPage)
Dim img As XImage = XImage.FromFile("I:\eQA\temp.png")
'xgr.DrawImage(img, 0, 0)
'Create XImage object from file.
Using xImg = PdfSharp.Drawing.XImage.FromFile("I:\eQA\temp.png")
'Resize page Width and Height to fit image size.
oPage.Width = xImg.PixelWidth * 72 / xImg.HorizontalResolution
oPage.Height = xImg.PixelHeight * 72 / xImg.HorizontalResolution
'Draw current image file to page.
Dim xgr = PdfSharp.Drawing.XGraphics.FromPdfPage(oPage)
xgr.DrawImage(xImg, 0, 0, oPage.Width, oPage.Height)
End Using
' instantiate a Bitmap object
Dim filesaveas As New SaveFileDialog
filesaveas.Filter = ("PDF File|*.pdf")
Dim btnSave As DialogResult = filesaveas.ShowDialog()
If btnSave.Equals(DialogResult.OK) Then
doc.Save(filesaveas.FileName)
doc.Close()
End If
' I used the Dispose() function to be able to
' save the same form again, in case some values have changed.
' When I didn't use the function, an GDI+ error occurred.
img.Dispose()
End Sub
End Class
I'm trying to add a feature to my program to take a full screenshot of the users screen when they click a button. I got the program to take the screenshot and open a file dialog box to save it, the saving works. The issue is that no matter how I save the screenshot, the saved image has significant quality loss and pixelates around text and stuff. This is a massive issue because I need the image to save exactly as it is seen on the users screen, I cannot have ANY quality loss at all. I tried to save the image as a jpg and a png and both gave me quality loss. I was wondering if anyone could point me towards some code or a method that would allow me to save the screenshots at the same quality as the users screen. I would like to save the image as a JPG or a PNG if possible. Any help would greatly be appreciated!
Get the image in Bitmap format and save it as bmp.
Private Function TakeScreenShot() As Bitmap
Dim screenSize As Size = New Size(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
Dim screenGrab As New Bitmap(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
Dim g As Graphics = Graphics.FromImage(screenGrab)
g.CopyFromScreen(New Point(0, 0), New Point(0, 0), screenSize)
Return screenGrab
End Function
For starters, JPEG images use a lossy compression algorithm so you tend to lose quality when you save in that format. It is preferable to save as Bitmap (BMP), which is uncompressed, or PNG, which uses a lossless compression.
Here is code to copy the working area of the screen to a PNG Image.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'the working area excludes all docked toolbars like taskbar, etc.
Dim currentScreen = Screen.FromHandle(Me.Handle).WorkingArea
'create a bitmap of the working area
Using bmp As New Bitmap(currentScreen.Width, currentScreen.Height)
'copy the screen to the image
Using g = Graphics.FromImage(bmp)
g.CopyFromScreen(New Point(0, 0), New Point(0, 0), currentScreen.Size)
End Using
'save the image
Using sfd As New SaveFileDialog() With {.Filter = "PNG Image|*.png",
.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.Desktop}
If sfd.ShowDialog() = Windows.Forms.DialogResult.OK Then
bmp.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Png)
End If
End Using
End Using
End Sub
.Net usually saves the file in 96dpi, so using following code you can save the file in higher resolution with Jpeg or other format.
'Create a new bitmap
Using Bmp As New Bitmap(800, 1000, Imaging.PixelFormat.Format32bppPArgb)
'Set the resolution to 300 DPI
Bmp.SetResolution(300, 300)
'Create a graphics object from the bitmap
Using G = Graphics.FromImage(Bmp)
'Paint the canvas white
G.Clear(Color.White)
'Set various modes to higher quality
G.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
G.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
G.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
'Create a font
Using F As New Font("Arial", 12)
'Create a brush
Using B As New SolidBrush(Color.Black)
'Draw some text
G.DrawString("Hello world", F, B, 20, 20)
End Using
End Using
End Using
'Save the file as a TIFF
Bmp.Save("c:\\test.Jpeg", Imaging.ImageFormat.Jpeg)
End Using
I've found that adding 3 lines to the above code significantly improves the quality of the image
var graphics = Graphics.FromImage(theRequestedAllocatedImage);
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
// Then call
graphics.CopyFromScreen(..)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim screenSize As Size = New Size(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
Dim screenGrab As New Bitmap(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
Dim g As Graphics = Graphics.FromImage(screenGrab)
g.CopyFromScreen(New Point(0, 0), New Point(0, 0), screenSize)
PictureBox1.Image = screenGrab
PictureBox1.Image.Save("c:\picture.bmp")
End Sub
I'm having an issue with iTextSharp and a PDF form (form fields specifically) that I've spend nearly two days on that I am direly hoping someone has the answer to.
I have a PDF form that when I open it as a user I can enter ampersands, &, into form fields just fine. However, when I use iTextSharp to fill in a form field value using .SetField the ampersands disappear. I have tried using & (which actually causes all the text in the field to appear as blank), the unicode representation of &, not flattening the form, flattening the form, etc. all to no avail. I am not sure what the issue could be as I mentioned the form field can certainly accept commas and ampersands with it's default encoding.
Is there something i'm missing?
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Using iText 4.1.2.0
GeneratePDF2()
End Sub
Private Sub GeneratePDF2()
''//The directory to output files to
Dim WorkingFolder = My.Computer.FileSystem.SpecialDirectories.Desktop
Dim FormFileName = Path.Combine(WorkingFolder, "testfile.pdf")
Dim FinalFileName = Path.Combine(WorkingFolder, "Final.pdf")
''//The name of the form field that we are going to create
Dim TextFieldName = "form1[0].#subform[0].Table3[0].Row2[0].Line2_FullName_and_AddressofEmployer[0]"
Dim FieldValue As String = "Jonathan & Chris & Mark" ' Does Not Work
'Dim FieldValue As String = "Jonathan and Chris and Mark" ' Works
Dim Letter As RandomAccessFileOrArray
'Create a PDF reader object based on the PDF template
Dim PDFReader As PdfReader
'Dim BAOS1 As MemoryStream
Dim Stamper As PdfStamper
Dim BAOS As MemoryStream = New MemoryStream()
Dim Copy As PdfCopyFields = New PdfCopyFields(BAOS)
Dim FormFilePath As String = FormFileName
Letter = New RandomAccessFileOrArray(FormFilePath)
'Create a PDF reader object based on the PDF template
PDFReader = New PdfReader(Letter, Nothing)
Dim BAOS1 As MemoryStream = New MemoryStream()
Stamper = New PdfStamper(PDFReader, BAOS1)
Dim FormFields As AcroFields = Stamper.AcroFields
'Set field value
FormFields.SetField(TextFieldName, FieldValue)
'Rename field after setting value
Dim RenamedFormFieldName As String
RenamedFormFieldName = String.Concat(Guid.NewGuid().ToString, "_", Guid.NewGuid().ToString)
FormFields.RenameField(TextFieldName, RenamedFormFieldName)
' flatten the form to remove editting options, set it to false
' to leave the form open to subsequent manual edits
Stamper.FormFlattening = True
' close the pdf
Stamper.Close()
'This could be the correct location
Copy.AddDocument(New PdfReader(BAOS1.ToArray))
Copy.Writer.CloseStream = False
Copy.Close()
PDFReader = New PdfReader(BAOS.ToArray())
Stamper = New PdfStamper(PDFReader, New FileStream(FinalFileName, FileMode.Create))
Stamper.FormFlattening = True
Stamper.Close()
End Sub
I'm unable to reproduce your problem, I'm using version 5.1.1.0. Below is sample code that creates a PDF, adds a field to it and then sets the field's value to This & that. (Its in three steps because I don't know how to add a field during the initial PDF creation.) I also tried manually creating a PDF in Acrobat and I was able to set the field to an ampersand just fine, too. Are you creating the form field in iTextSharp or another program? Can you post that PDF somewhere so we can look at it?
Option Explicit On
Option Strict On
Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports System.IO
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
''//The directory to output files to
Dim WorkingFolder = My.Computer.FileSystem.SpecialDirectories.Desktop
''//This sample code creates a base PDF, then adds a text field to it and finally sets the field value.
''//These filenames represent those three actions
Dim BaseFileName = Path.Combine(WorkingFolder, "Base.pdf")
Dim FormFileName = Path.Combine(WorkingFolder, "Form.pdf")
Dim FinalFileName = Path.Combine(WorkingFolder, "Final.pdf")
''//The name of the form field that we are going to create
Dim TextFieldName = "Text1"
''//Create our base PDF
Using FS As New FileStream(BaseFileName, FileMode.Create, FileAccess.Write, FileShare.Read)
Using Doc As New Document(PageSize.LETTER)
Using W = PdfWriter.GetInstance(Doc, FS)
Doc.Open()
Doc.NewPage()
Doc.Add(New Paragraph("This is my form"))
Doc.Close()
End Using
End Using
End Using
''//Add our form field
Using FS As New FileStream(FormFileName, FileMode.Create, FileAccess.Write, FileShare.Read)
Dim R1 = New PdfReader(BaseFileName)
Using S As New PdfStamper(R1, FS)
Dim F As New TextField(S.Writer, New Rectangle(50, 50, 500, 100), TextFieldName)
S.AddAnnotation(F.GetTextField(), 1)
S.Close()
End Using
End Using
''//Set the field value to text with an ampersand
Using FS As New FileStream(FinalFileName, FileMode.Create, FileAccess.Write, FileShare.Read)
Dim R2 = New PdfReader(FormFileName)
Using S As New PdfStamper(R2, FS)
S.AcroFields.SetField(TextFieldName, "This & that")
S.Close()
End Using
End Using
Me.Close()
End Sub
End Class
EDIT
I just tried it with the PDF you sent and its working just fine for me. Below is the full code that I ran. Here's the PDF it made. Are you sure you're not doing something else to the PDF (I don't know what.) If you create a brand new Windows Applications and use the below code against 5.1.1.0 does it work for you?
Option Explicit On
Option Strict On
Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports System.IO
Imports System.Text
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
''//The directory to output files to
Dim WorkingFolder = My.Computer.FileSystem.SpecialDirectories.Desktop
Dim FormFileName = Path.Combine(WorkingFolder, "testfile.pdf")
Dim FinalFileName = Path.Combine(WorkingFolder, "Final.pdf")
''//The name of the form field that we are going to create
Dim TextFieldName = "form1[0].#subform[0].Table3[0].Row2[0].Line2_FullName_and_AddressofEmployer[0]"
''//Set the field value to text with an ampersand
Using FS As New FileStream(FinalFileName, FileMode.Create, FileAccess.Write, FileShare.Read)
Dim R2 = New PdfReader(FormFileName)
Using S As New PdfStamper(R2, FS)
S.AcroFields.SetField(TextFieldName, "Chris & Mark")
S.FormFlattening = True
S.Close()
End Using
End Using
Me.Close()
End Sub
End Class
Had a similar case where German umlauts entered by the user in the application were not showing in the PDF. Turned out to be a font issue.
Had to ship our own fonts with the application (Liberation package to get cross-platform Arial-style) and doing this (it's Java):
BaseFont baseFont = BaseFont.createFont(FONT_FILE, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
acroFields.setFieldProperty(fieldName, "textfont", baseFont, null);