I was following this: http://zerosandtheone.com/blogs/vb/archive/2009/11/20/vb-net-include-a-font-as-an-embedded-resource-in-your-application.aspx to allow my application to use a custom fonts in a labels. The problem with that is I can run the application on my computer (probably because I have this font installed), the problem appears when any other person run the compiled application on his computer; the following error from the exception catch appears: 53 File doesn't exists.
Where does this exception is located at?
I'm talking about the module I linked above:
'MATTHEW KLEINWAKS
'ZerosAndTheOne.com
'2009
'CUSTOM FONT LOADED DYNAMICALLY FROM A RESOURCE
Imports System.Drawing.Text
Imports System.Runtime.InteropServices
Module CustomFont
'PRIVATE FONT COLLECTION TO HOLD THE DYNAMIC FONT
Private _pfc As PrivateFontCollection = Nothing
Public ReadOnly Property GetInstance(ByVal Size As Single, _
ByVal style As FontStyle) As Font
Get
'IF THIS IS THE FIRST TIME GETTING AN INSTANCE
'LOAD THE FONT FROM RESOURCES
If _pfc Is Nothing Then LoadFont()
'RETURN A NEW FONT OBJECT BASED ON THE SIZE AND STYLE PASSED IN
Return New Font(_pfc.Families(0), Size, style)
End Get
End Property
Private Sub LoadFont()
Try
'INIT THE FONT COLLECTION
_pfc = New PrivateFontCollection
'LOAD MEMORY POINTER FOR FONT RESOURCE
Dim fontMemPointer As IntPtr = _
Marshal.AllocCoTaskMem( _
My.Resources.DIGITALDREAMNARROW.Length)
'COPY THE DATA TO THE MEMORY LOCATION
Marshal.Copy(My.Resources.DIGITALDREAMNARROW, _
0, fontMemPointer, _
My.Resources.DIGITALDREAMNARROW.Length)
'LOAD THE MEMORY FONT INTO THE PRIVATE FONT COLLECTION
_pfc.AddMemoryFont(fontMemPointer, _
My.Resources.DIGITALDREAMNARROW.Length)
'FREE UNSAFE MEMORY
Marshal.FreeCoTaskMem(fontMemPointer)
Catch ex As Exception
MessageBox.Show(& Err.Number & " " & Err.Description)
End Try
End Sub
End Module
precisely this:
Catch ex As Exception
MessageBox.Show(& Err.Number & " " & Err.Description)
End Try
Is showing the message box, containing the 53 File doesn't exists message.
I don't really know why does it happends, because it works on my computer without any problems... I would appreciate any help attempt!
Try using this code
''' <summary>Adds the specified font to the private font collection.</summary>
''' <param name="font">The font to be added.</param>
Public Sub AddFont(ByVal font As Byte())
If font Is Nothing Then Throw New ArgumentNullException("The font cannot be null.", "font")
If font.Length = 0 Then Throw New ArgumentException("The length of the font array cannot be 0.", "font")
Try
privateFonts.AddMemoryFont(Marshal.UnsafeAddrOfPinnedArrayElement(font, 0), font.Length)
Catch ex As Exception
'handle you exceptions here
End Try
End Sub
And add fonts to the collection this way
Private Sub LoadFont()
Try
'INIT THE FONT COLLECTION
privateFonts = New PrivateFontCollection
AddFont(My.Resources.DIGITALDREAMNARROW)
Catch
'
' the rest of your code
'
End Sub
Assuming you added the font resource as a file, it is going to be passed to the AddFont method as a byte array.
Needless to say, the AddFont method assumes you have an initialized PrivateFontCollection object called privateFonts which is accessible within the scope of the method.
Update
Since you're saying that my solution is not working, I've uploaded a sample project here. Download and see how to load and use private fonts from resources.
Related
Im trying to get the privatefontcollection to work. But so far its not working, not in the sense of an error, just the font seen on screen is MS Sans Serif and not the Font im trying to load. so far i have tried two diffrent methods and neither seem to have worked for me.
First i tried:
Public Function GetFontInstance(ByVal data() As Byte, ByVal Size As Single, ByVal Style As FontStyle) As Font
Dim result As Font
Try
Dim pfc = New PrivateFontCollection
'LOAD MEMORY POINTER FOR FONT RESOURCE
Dim FontPtr As System.IntPtr = Marshal.AllocCoTaskMem(data.Length)
'COPY THE DATA TO THE MEMORY LOCATION
Marshal.Copy(data, 0, FontPtr, data.Length)
'LOAD THE MEMORY FONT INTO THE PRIVATE FONT COLLECTION
pfc.AddMemoryFont(FontPtr, data.Length)
'FREE UNSAFE MEMORY
'Marshal.FreeCoTaskMem(FontPtr)
result = New Font(pfc.Families(0), Size, Style)
pfc.Families(0).Dispose()
pfc.Dispose()
Catch ex As Exception
'ERROR LOADING FONT. HANDLE EXCEPTION HERE
MsgBox("Error in [GetFontInstance()]" & vbCrLf & ex.Message)
result = New Font(FontFamily.GenericMonospace, 8)
End Try
Return result
End Function
i called this function from the Print SubRoutine:
Dim newFont As Font = GetFontInstance(My.Resources.OpenSans_Bold, 22, FontStyle.Bold)
e.Graphics.DrawString("Hello World", newFont, Brushes.Black, 50, 2)
but what i see in the printdocument print preview, is just MS Sans Serif type font. not the font i have loaded into my Resources.
I then tried this method:
Dim sAppPath As String
sAppPath = System.Windows.Forms.Application.StartupPath
Dim fcollect As New PrivateFontCollection()
fcollect.AddFontFile(sAppPath & "\OpenSans-Bold.ttf")
Dim OpenSansFont As New Font(fcollect.Families(0), 50, FontStyle.Bold)
e.Graphics.DrawString("Hello World", OpenSansFont, Brushes.Black, 50, 2)
again i got the same result
is there something I'm missing to get this to work. other questions asked about this seem to indicate this should just work.
I should mention that the end user will run the Application on a system admin locked PC, so the option to "install" the font wont be possible. Id need to make use of the font only while the application is running / when the subroutine gets called.
I am allowing the use of themes in my application. So I create a font based on the user's choice of themes. However, I need to change the fontstyle from regular to bold, but I don't want to have to recreate the font.
I am doing it this way, because not all users will have the font installed on their machine. So I am embedding the font into the application.
For example: I may have a textbox assigned the font like this:
txtbox.font = theme_font
Is there a way to simply change the style to bold?
txtbox.font = theme_font.fontstyle.bold ' <-- this doesn't work
I call the font creation subroutine like this:
Public Shared theme_font = BerlinSans.GetInstance(theme_font_size, FontStyle.Regular)
And this is the subroutine being called:
Module BerlinSans
'PRIVATE FONT COLLECTION TO HOLD THE DYNAMIC FONT
Private _pfc As PrivateFontCollection = Nothing
Public ReadOnly Property GetInstance(ByVal Size As Single, ByVal style As FontStyle) As Font
Get
'IF THIS IS THE FIRST TIME GETTING AN INSTANCE
'LOAD THE FONT FROM RESOURCES
If _pfc Is Nothing Then LoadFont()
'RETURN A NEW FONT OBJECT BASED ON THE SIZE AND STYLE PASSED IN
Return New Font(_pfc.Families(0), Size, style)
End Get
End Property
Private Sub LoadFont()
Try
'INIT THE FONT COLLECTION
_pfc = New PrivateFontCollection
'LOAD MEMORY POINTER FOR FONT RESOURCE
Dim fontMemPointer As IntPtr = Marshal.AllocCoTaskMem(My.Resources.BRLNSR.Length)
'COPY THE DATA TO THE MEMORY LOCATION
Marshal.Copy(My.Resources.BRLNSR, 0, fontMemPointer, My.Resources.BRLNSR.Length)
'LOAD THE MEMORY FONT INTO THE PRIVATE FONT COLLECTION
_pfc.AddMemoryFont(fontMemPointer, My.Resources.BRLNSR.Length)
'FREE UNSAFE MEMORY
Marshal.FreeCoTaskMem(fontMemPointer)
Catch ex As Exception
'ERROR LOADING FONT. HANDLE EXCEPTION HERE
End Try
End Sub
End Module
You can use the Font(Font, FontStyle) constructor. Just pass it the old font and the new style you want to use and it'll copy the properties from the old font into the new one for you (apart from the style, of course).
txtbox.Font = New Font(theme_font, FontStyle.Bold)
My Visual Basic code works to write to the file, but not to read from it. Reading from the file needs to be part of the splash screen, so I can't move it to the main KMFile class. Can you help me figure out what's wrong with this code?
Imports System.IO
Public Class SplashScreen1
'TODO: This form can easily be set as the splash screen for the application by going to the "Application" tab
' of the Project Designer ("Properties" under the "Project" menu).
Private Sub SplashScreen1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Set up the dialog text at runtime according to the application's assembly information.
'Open the yacht type list to read from it.
'TODO: Customize the application's assembly information in the "Application" pane of the project
' properties dialog (under the "Project" menu).
'Application title
Dim YachtTypeString As String = "YachtTypes.txt"
Try
'Open the file.
Dim YachtsListStreamReader As StreamReader = New StreamReader("YachtTypes.txt")
' Read all elements into the list.
Do Until YachtsListStreamReader.Peek = -1
YachtTypeString = YachtsListStreamReader.ReadLine()
KMFile.YachtTypeComboBox.Items.Add(YachtTypeString)
Loop
'Close the file.
YachtsListStreamReader.Close()
Catch ex As Exception
'File missing.
MessageBox.Show("The yacht types file is not found.", "Enter yacht types manually to save", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Try
If My.Application.Info.Title <> "" Then
ApplicationTitle.Text = My.Application.Info.Title
Else
'If the application title is missing, use the application name, without the extension
ApplicationTitle.Text = System.IO.Path.GetFileNameWithoutExtension(My.Application.Info.AssemblyName)
End If
'Format the version information using the text set into the Version control at design time as the
' formatting string. This allows for effective localization if desired.
' Build and revision information could be included by using the following code and changing the
' Version control's designtime text to "Version {0}.{1:00}.{2}.{3}" or something similar. See
' String.Format() in Help for more information.
'
' Version.Text = System.String.Format(Version.Text, My.Application.Info.Version.Major, My.Application.Info.Version.Minor, My.Application.Info.Version.Build, My.Application.Info.Version.Revision)
Version.Text = System.String.Format(Version.Text, My.Application.Info.Version.Major, My.Application.Info.Version.Minor)
'Copyright info
Copyright.Text = My.Application.Info.Copyright
End Sub
End Class
Here:
Catch ex As Exception
'File missing.
MessageBox.Show("The yacht types file is not found.", "Enter yacht types manually to save", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Try
you swallow all exceptions and show a generic error message. Don't do that. Include ex.Message in your displayed message or only catch FileNotFoundExceptionss.
That way, you will see the real error message, leading you to the real cause of the problem you are experiencing.
I am using an ajaxfileupload control to upload a pdf file to the server. On the server side, I'd like to convert the pdf to jpg. Using the PDFsharp Sample: Export Images as a guide, I've got the following:
Imports System
Imports System.Drawing
Imports System.Drawing.Imaging
Imports PdfSharp.Pdf
Imports System.IO
Imports PdfSharp.Pdf.IO
Imports PdfSharp.Pdf.Advanced
Namespace Tools
Public Module ConvertImage
Public Sub pdf2JPG(pdfFile As String, jpgFile As String)
pdfFile = System.Web.HttpContext.Current.Request.PhysicalApplicationPath & "upload\" & pdfFile
Dim document As PdfSharp.Pdf.PdfDocument = PdfReader.Open(pdfFile)
Dim imageCount As Integer = 0
' Iterate pages
For Each page As PdfPage In document.Pages
' Get resources dictionary
Dim resources As PdfDictionary = page.Elements.GetDictionary("/Resources")
If resources IsNot Nothing Then
' Get external objects dictionary
Dim xObjects As PdfDictionary = resources.Elements.GetDictionary("/XObject")
If xObjects IsNot Nothing Then
Dim items As ICollection(Of PdfItem) = xObjects.Elements.Values
' Iterate references to external objects
For Each item As PdfItem In items
Dim reference As PdfReference = TryCast(item, PdfReference)
If reference IsNot Nothing Then
Dim xObject As PdfDictionary = TryCast(reference.Value, PdfDictionary)
' Is external object an image?
If xObject IsNot Nothing AndAlso xObject.Elements.GetString("/Subtype") = "/Image" Then
ExportImage(xObject, imageCount)
End If
End If
Next
End If
End If
Next
End Sub
Private Sub ExportImage(image As PdfDictionary, ByRef count As Integer)
Dim filter As String = image.Elements.GetName("/Filter")
Select Case filter
Case "/DCTDecode"
ExportJpegImage(image, count)
Exit Select
Case "/FlateDecode"
ExportAsPngImage(image, count)
Exit Select
End Select
End Sub
Private Sub ExportJpegImage(image As PdfDictionary, ByRef count As Integer)
' Fortunately JPEG has native support in PDF and exporting an image is just writing the stream to a file.
Dim stream As Byte() = image.Stream.Value
Dim fs As New FileStream([String].Format("Image{0}.jpeg", System.Math.Max(System.Threading.Interlocked.Increment(count), count - 1)), FileMode.Create, FileAccess.Write)
Dim bw As New BinaryWriter(fs)
bw.Write(stream)
bw.Close()
End Sub
Private Sub ExportAsPngImage(image As PdfDictionary, ByRef count As Integer)
Dim width As Integer = image.Elements.GetInteger(PdfImage.Keys.Width)
Dim height As Integer = image.Elements.GetInteger(PdfImage.Keys.Height)
Dim bitsPerComponent As Integer = image.Elements.GetInteger(PdfImage.Keys.BitsPerComponent)
' TODO: You can put the code here that converts vom PDF internal image format to a Windows bitmap
' and use GDI+ to save it in PNG format.
' It is the work of a day or two for the most important formats. Take a look at the file
' PdfSharp.Pdf.Advanced/PdfImage.cs to see how we create the PDF image formats.
' We don't need that feature at the moment and therefore will not implement it.
' If you write the code for exporting images I would be pleased to publish it in a future release
' of PDFsharp.
End Sub
End Module
End Namespace
As I debug, it blows up on Dim filter As String = image.Elements.GetName("/Filter") in ExportImage. The message is:
Unhandled exception at line 336, column 21 in ~:46138/ScriptResource.axd?d=LGq0ri4wlMGBKd-1vxLjtxNH_pd26HaruaEG_1eWx-epwPmhNKVpO8IpfHoIHzVj2Arxn5804quRprX3HtHb0OmkZFRocFIG-7a-SJYT_EwYUd--x9AHktpraSBgoZk4VJ1RMtFNwl1mULDLid5o5U9iBcuDi4EQpbpswgBn_oI1&t=ffffffffda74082d
0x800a139e - JavaScript runtime error: error raising upload complete event and start new upload
Any thoughts on what the issue might be? It seems an issue with the ajaxfileupload control, but I don't understand why it would be barking here. It's neither here nor there, but I know I'm not using jpgFile yet.
PDFsharp cannot create JPEG Images from PDF pages:
http://pdfsharp.net/wiki/PDFsharpFAQ.ashx#Can_PDFsharp_show_PDF_files_Print_PDF_files_Create_images_from_PDF_files_3
The sample you refer to can extract JPEG Images that are included in PDF files. That's all. The sample does not cover all possible cases.
Long story short: the code you are showing seems unrelated to the error message. And it seems unrelated to your intended goal.
I have written a program in VB.NET to monitor file changes to recent saved screenshots taken from the tool.
I have a custom FileSystemWatcher class written (shared by someone on the internet,just customized) and have an instance invoked in my program.
The basic issue or objective is that when i capture a screen area using my program, I want it to immediately copy it over to clipboard. There are times when I would want to edit the captured image, in which case any editing made and saved, after saving the edited image must automatically be copied over to clipboard.
I use the below code to copy the image over to clipboard
'Subroutine to Copy the captured screenshot
'Added 15/09/2014
Sub CopyImageCapture(ByVal ImgPath)
Dim ThreadA As Thread
ThreadA = New Thread(AddressOf Me.MyAsyncTask)
'Setting ApartmentState.STA as this is needed for Clipboard related functionalities
ThreadA.SetApartmentState(ApartmentState.STA)
ThreadA.Start(ImgPath)
End Sub
'Threading to handle the Clipboard copy function
'Copy the screenshot to Clipboard
'Added 15/09/2014
Private Sub MyAsyncTask(ByVal ImgPath)
Clipboard.Clear()
Clipboard.SetImage(ImgPath)
End Sub
And when i choose to edit the image, the below code takes care to monitor the file changes
Sub MonitorFileChange(ByVal FolderPath, ByVal ItemName)
Try
Dim sFolder As String
Dim sFile As String
sFolder = FolderPath
sFile = ItemName
If IO.Directory.Exists(sFolder) Then
objWatcher.FolderToMonitor = sFolder
objWatcher.FileToMonitor = sFile
'objWatcher.NotifyFilter = (NotifyFilters.FileName Or NotifyFilters.Size)
objWatcher.StartWatch()
Else
MessageBox.Show("Folder does not exist!")
End If
Catch ex As Exception
MsgBox("Encountered an exception in MonitorFileChange subroutine. Details - " + ex.Message)
End Try
End Sub
'Subrountine to capture FileChanged events (esp. when captured image is edited in Paint and Saved)
'Works in sync with custom class 'clsFSW' for this purpose.
'ADDED: 15/09/2014
Private Sub objWatcher_FileChanged(ByVal FullPath As String) Handles objWatcher.FileChanged
'Try
Dim lastWriteTime As DateTime
lastWriteTime = File.GetLastWriteTime(FullPath)
Debug.Print(lastWriteTime)
If (lastWriteTime <> lastRead) Then
objWatcher.EnableRaisingEvents = False
'QuickCopy for changes files. BUG FIX
If (QuickSaveToolStripMenuItem.Checked) Then
Debug.Print("File Changed: " & FullPath & vbCrLf)
Dim tempI As System.Drawing.Bitmap = New System.Drawing.Bitmap(FullPath)
Dim tempI2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(tempI, tempI.Width, tempI.Height)
CopyImageCapture(tempI2)
tempI.Dispose()
End If
lastRead = lastWriteTime
End If
'Catch ex As Exception
' MsgBox("Encountered an exception in objWatcher_FileChanged subrountine. Details - " + ex.Message)
' 'Finally
' 'objWatcher.EnableRaisingEvents = True
'End Try
End Sub
The problem is sometimes when I open the captured image and make quick saves or press save a couple of times real quick I get a "A Sharing violation occured" error
Can anyone help resolve the above issue? Which part of the code or logic is causing this to happen?
Also, if you check the above snippet, sometimes (havent seen any particular pattern) but the catch block in objWatcher_FileChanged is triggered and the error is "Parameter not found"
Can someone please help into this too?
Thanks in advance! Please let me know if any info more is required.
EDIT: Please note, the sharing violation error seems invoked from the Paint application itself and not my program, but why does it happen randomly, is a mystery to me. Is there nay loophole in the logic? Any alternative logic to what I want to achieve?
Try disposing tempI2. Windows may be locking the file used with tempI, and keeping it locked since it is assigned to tempI2. If so, it may remain locked until tempI2 is disposed.