Why the following code does not throw an exception?
FontFamily font = new FontFamily("bla bla bla");
I need to know if a specific font (as combination of FontFamily, FontStyle, FontWeight, ...) exists in my current OS. How have I to do?
This is by design. Programs frequently ask for fonts that are not present on the machine, especially in a country far flung from the programmer's domicile. The font mapper produces an alternative. Font substitution is in general very common. You are looking at Arial right now if you are on a Windows machine. But I can paste 你好世界 into this post and you'll see it render accurately, even though Arial doesn't have glyphs for Chinese characters.
So hint number one is to not actually worry about what fonts are available. The Windows api has EnumFontFamiliesEx() to enumerate available font families. But that's not exposed in WPF, some friction with OpenType there, a font standard that's rather poorly integrated with Windows. Another shadow cast when Adobe gets involved with anything Microsoft does, it seems.
Some confusion in the comments about Winforms' FontFamily class. Which is actually usable in this case, its GetFamilies() method returns an array of available families. But only TrueType, not OpenType fonts.
You can use the class System.Drawing.Text.InstalledFontCollection
http://msdn.microsoft.com/en-us/library/system.drawing.text.installedfontcollection.aspx
WPF have a framework specific method Fonts.SystemFontFamilies
http://msdn.microsoft.com/en-us/library/system.windows.media.fonts.systemfontfamilies.aspx
To answer the question of why it isn't throwing an exception, according to FontFamily Constructor on MSDN the exception wasn't added until framework version 3.5.
I suspect that you are targeting version 3.0 or below.
Cheers!
You can browse the available fonts on the System using the Fonts.SystemFontFamilies collection - use some Linq to match on whatever conditions you need;
// true
bool exists = (from f in Fonts.SystemFontFamilies where f.Source.Equals("Arial") select f).Any();
// false
exists = (from f in Fonts.SystemFontFamilies where f.Source.Equals("blahblah") select f).Any();
Related
I am fairly new to programming and I just wrote a simple application in C# .NET to retrieve information about system drive space. The program functions fine but I'm struggling with formatting the output.
See output:
I'm trying to use padding to get the text to line up in sort of a column format within a rich text box but the output doesn't line up because if there are multiple drives, the drive names are different lengths which throws off the padding. Even if the drive letter comes back one as M: and the other as I: the difference in the size of the letter is enough to throw off the alignment while padding.
I am wondering if there is a way to force each string value to a specific length so the padding is applied evenly or if maybe there's an even better way to format my output. Thank you in advance for your time and let me know if any further information would be helpful!
Note: One of the comments asked an important question, regarding whether the question refers to the System.Windows.Forms.RichTextBox (WinForms) or the System.Windows.Controls.RichTextBox (WPF) control. This answer applies only to the WinForms version of RichTextBox, so if you're using WPF, this doesn't apply.
The most important thing, and this was mentioned in the comments, is that you'll need to use a Monospaced font.
Since you stated you're using a RichTextBox, you'll need to know how to set it to use whatever monospaced font you've chosen.
To do that, you can use the RichTextBox.SelectionFont property.
For more general instructions, refer to this MSDN article: Setting Font Attributes for the Windows Forms RichTextBox Control
Once you set the RichTextBox.SelectionFont property, only text added to the control afterwards will use the specified font. To apply the font to existing text (i.e. you populate the RichTextBox and then change the font to an appropriate monospaced font), take a look at this answer, which tells you precisely what to do.
Once that's done, there remains the simple matter of adding the appropriate amount of whitespace to the end of each string, such that the next piece of data appears at the appropriate position. You'll probably be using String.PadRight, but for more general information about padding strings, check out this MSDN article: Padding Strings in the .NET Framework
Here is string formatting example:
string varOne = "Line One";
double varTwo = 15/100;
string output= String.Format("{0,-10} {1,5:P1}", varOne, varTwo);
//expected output is
//Line One 15 %
where formatting properties in curly brackets are:
{index[,alignment][ :formatString] }
The Situation
We are selling a Windows Forms Application to customers all over the world.
We installed it in several countries in Europe and America. No problems.
Last week we installed our software in South-Korea and recognized a strange behaviour...
The problem occurs only on the customers office PCs, but on all of them.
Some have Windows 7 Professional K, some have Windows XP.
The customer bought a new PC with an installed Windows 7 Ultimate.
On this PC, there is no problem.
The Function
All elements in our application are derived from a "parent-user-control" that offers special functions.
One of these functions is "autosizing and positioning".
When the parent changes size, this function of all childs is called.
When our application starts, we store the "ClientSize":
InitializeComponent();
this.m_actSize = this.ClientSize;
Whenever the size of the application changes, we calculate the scaling factor and raise an event with it:
void myFormSizeChanged(object sender, EventArgs e)
{
this.m_xFactor = (float)this.ClientSize.Width / (float)this.m_actSize.Width;
this.m_yFactor = (float)this.ClientSize.Height / (float)this.m_actSize.Height;
if (this.m_MyOnResize != null)
this.m_MyOnResize(this.m_xFactor, this.m_yFactor);
}
Now, each child that subscribed, performs automatic resizing and positioning:
void MyParentUserControl_MyOnResize(float v_xFactor, float v_yFactor)
{
this.Location = new Point((int)(this.m_actLocation.X * v_xFactor), (int)(this.m_actLocation.Y * v_yFactor));
this.Size = new Size((int)(this.m_actSize.Width * v_xFactor), (int)(this.m_actSize.Height * v_yFactor));
}
The Problem
When our application starts on the customers PCs in South-Korea, the width is about 20% to small.
That means, on the right side is an area where is just a grey background.
The height is about 10% to high.
That means, the items located on the bottom of our application are outside the screen.
The Fix
First, we thought the problem comes from the Windows DPI setting.
When I set my Laptop to 125%, it looked similar.
But, the customers PCs are all set to 100%...
Then, we thought about the screen resolution.
All have different ones, some the same as my Laptop...
All have different grafic adapters...
All have .NET 4.5.1...
The only way, that solved the problem, was a strange one:
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ScrollBar;
this.ClientSize = new System.Drawing.Size(1016, 734);
In the "Designer" file, manually changing the ClientSize from (1016, 734) to about (900, 800).
This made it look good on most customer PCs. But not on all.
The Question
What can be the real solution for this problem?
Where can it come from?
Do you have the same issues on the same computers if you use AutoScaleMode.Dpi or AutoScaleMode.None instead of AutoScaleMode.Font on each containing control?
If that solves your problem, here is why I think your issue may be related to using AutoScaleMode.Font
At a high level, according to MSDN, the effect of AutoScaleMode.Font is that the control will "scale relative to the dimensions of the font the classes are using, which is typically the system font." (Emphasis mine.)
I dug into the System.Windows.Forms.ContainerControl source code a bit. The method PerformAutoScale is automatically called during a control's OnLayout event. If AutoScaleMode is set to Font, then GetFontAutoScaleDimensions is called indirectly by OnLayout. The comments in GetFontAutoScaleDimensions explain howAutoScaleMode.Font is implemented:
// We clone the Windows scaling function here as closely as
// possible. They use textmetric for height, and textmetric
// for width of fixed width fonts. For variable width fonts
// they use GetTextExtentPoint32 and pass in a long a-Z string.
// We must do the same here if our dialogs are to scale in a
// similar fashion.
So, the method takes a "long" string, sends it out to GDI and asks, "what are the dimensions of this string?" Notably, this method takes into consideration the control's font "which is typically the system font."
Did you know that the Korean alphabet (Hangul) is not represented in Arial? (I didn't until I researched this answer!) It makes perfect sense that your system font (something like Tahoe or Arial) is different than that of your clients in South Korea. It also makes sense that two different fonts will display the same string of characters with a different height and width. So, I bet the issues in question occur on workstations with a system font different than your system font.
So, if you do some testing and find that AutoScaleMode.Font really is the culprit, then you have a few options:
Don't use AutoScaleMode.Font.
Explicitly set the font of all containing controls
explicitly. This will ensure that the font of the ContainerControl
does not default to the computer's system font.
No matter what you do, ensure all of your containers use the same AutoScaleMode setting. Mixing and matching will lead to headaches.
Good Luck!
I am trying to fill drop down box with font family names and I have a lot of fonts almost 600 and I want to reduce this number based on the user interface for example when the interface is LTR (western) English or french for example I would need to load just the fonts that support those scripts nothing more
right now I am doing this:
InstalledFontCollection c = new InstalledFontCollection();
FontFamily[] fontF = c.Families;
return fontF.Select(i => i.GetName(0)).ToArray();
when trying to change the language identifier in GetName method with other value I end up with the same amount of result
I have the values from Winnt.h header file which can be found here
I am using asp.net C# 4.5
what I am looking for is native C# solution without using P/Invoke or at least that would be my last fallback solution
Is there the way to create iTextSharp font using additional info (such as gdiCharSet etc) from System.Drawing.Font object?
Short answer: Yes.
Long answer: Each attribute is a bit different, but all that information can be expressed within PDF in general, and iText[Sharp] in specific.
You can specify a font's encoding when you create it, but you must do so in a way iText understands. Specifically, encoding values are strings within iText[Sharp]. BaseFont has a number of public static string members that list many of the available encodings, including several code pages that will map nicely to some of the GdiCharSet values. Others, not so much.
I generally suggest using "Identity-H" and subsetting your fonts (which happens automagically with Identity-H, you can't avoid it, which is a Good Thing) unless you need to keep the file size to a bare minimum. There are several single-byte encodings, the most common of which is "WinAnsiEncoding", BaseFont.WINANSI (the default IIRC). The string can also be the name of a "CMap" (such as Identity-H).
CMaps are generally language specific, and encoding specific. UTF & Japanese, or Big5 (a Chinese encoding as I recall), or what have you. Identity-H (and Identity-V) are font specific instead. They simply map values in the content stream to glyph indexes in the font (which can vary wildly from one font to the next, or between versions of a given font: that's why you're required to embed subsets of Identity-* fonts).
In PDF (and therefore iText[Sharp]), "bold" and "italic" are part of the font's identity, not a property. "Arial-Bold", "Arial-Italic", etc.
Strikeout and underline are decorations added after the fact (though I believe iText will let you set a flag at the font level for such things in com.itextpdf.text.Font's constructor).
iText won't give you direct access to the height, though a font's "descriptor" will let you define it.
The point size isn't a property either, you set it and the font (and color, default black) before you draw some text.
I'm working with ITextSharp for a project and am looking for a reasonable way to get a string list of different fonts it has available for use.
I thought maybe I could just use reflection and loop over a class of available fonts, but there does not seem to be an easy way to do this. What I really want to do is provide a drop down of available/supported fonts for my users to select from Does anyone have any thoughts on how I might accomplish this?
This webpage has a great reference for how to work with the 14 embedded fonts in iTextSharp, as well as how to embed and use any fonts of your choosing.
To get the list of fonts included in iTextSharp:
Dim myCol As ICollection
//Returns the list of all font families included in iTextSharp.
myCol = iTextSharp.text.FontFactory.RegisteredFamilies
//Returns the list of all fonts included in iTextSharp.
myCol = iTextSharp.text.FontFactory.RegisteredFonts
An example of a font family is Helvetica. An example of a font is Helvetica-Bold or Helvetica-Italic.
First call FontFactory.RegisterDirectories(); to get all fonts on the system registered.
Then call FontFactory.RegisteredFonts; to get all the fonts.