winforms app written in win7 looks different on win xp. why? - winforms

I have written a simple app in winforms (.net 4.0) on win 7. Application looks how I want but when I tried it on windows xp everything looks different.
I have created a sample example to show how it looks on win 7 and xp.
What can I do to have the same look on both systems?
The problem is not only with the background and font color but with the controls too. Here I show how the numericupdown looks but with table layout I have problem too.
private void InitializeComponent()
{
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.groupBox1 = new System.Windows.Forms.GroupBox();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
this.SuspendLayout();
//
// numericUpDown1
//
this.numericUpDown1.DecimalPlaces = 2;
this.numericUpDown1.Increment = new decimal(new int[] {
1,
0,
0,
131072});
this.numericUpDown1.Location = new System.Drawing.Point(21, 26);
this.numericUpDown1.Maximum = new decimal(new int[] {
1,
0,
0,
0});
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(54, 22);
this.numericUpDown1.TabIndex = 0;
//
// groupBox1
//
this.groupBox1.Location = new System.Drawing.Point(21, 82);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(226, 99);
this.groupBox1.TabIndex = 1;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "groupBox1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ActiveCaption;
this.ClientSize = new System.Drawing.Size(407, 331);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.numericUpDown1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
this.ResumeLayout(false);
}
I have no modified the xp color themes.
I have the same result on two diffrent computers with win xp.

this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ActiveCaption;
These are the statements that cause your trouble. I'll pick-off the easy one first, don't make the BackColor of the form the same as the caption color. If you want to pick a theme color then only choose the "Control" color. Albeit that you'll typically get the old battleship gray. Picking a neutral pastel color is your best bet but honoring the user's preference will never get you into trouble.
The AutoScaleDimensions property is auto-generated, based on the video adapter's DPI setting. Which is different the XP machine. You've got 120 dots-per-inch on your dev machine, 96 DPI (the default) on XP. On Win7, that's set by the widget that looks like a ruler, Control Panel + Display, "Set custom text size (DPI)".
The AutoScaleMode property is correctly set to Font. This ensures that all controls are automatically scaled to fit the font size. Which is larger on your Win7 machine because of the higher DPI setting. Accordingly, the form and its controls shrink on the XP machine. The problem with the NumericUpDown control is that its a bit buggy (in more than one way), it doesn't scale the up/down glyphs properly. They are proportionally too large, not leaving enough room for the text portion. Simply making it a bit wider solves the problem.
Auto-scaling is fairly ugly, it is rarely 100% perfect. The best thing to do is to switch your dev machine to 96 dpi. A very common setting, still today. Scaling up almost always works better than scaling down.

this.BackColor = System.Drawing.SystemColors.ActiveCaption;
There's your problem. The color is going to be dependent on the operating system. http://msdn.microsoft.com/en-us/library/system.drawing.systemcolors.activecaption.aspx
Consider setting an explicit color value (e.g. one of the System.Drawing.Color http://msdn.microsoft.com/en-us/library/system.drawing.color.aspx enumerations) instead. Won't look exactly the same, but it will be closer.

Related

WinForms: Disable text anti-aliasing of RichTextBox

I use RichTextBox to display small texts which is much sharper without anti-aliasing. Texts in TextBox is not anti-aliased which gives a sharp outline. But texts in RichTextBox is anti-aliased which is blured. So I want to prevent RichTextBox from anti-aliasing the texts.
I think this is only possible if RichTextBox can also render bitmap-text since for small text, if it is rendered without anti-aliasing, the result won't be readable. So the question is indeed can RichTextBox render text in bitmap mode instead of vector mode?
Environment: Windows 10 x64, VS2017
This question's Disable Anti-aliasing on WinForms text rendering answer doesn't affect RichTextBox.
It turns out that RichTextBox can render bitmap font, it depends on the font that you use, if you use a bitmap font, then RitchTextBox will just render bitmap font...
I use NetRtfWriter https://sourceforge.net/projects/netrtfwriter/ to generate RTF text then put it in RichTextBox's Rtf property.
Win forms test code (txtMain is a RichTextBox)
public Form1()
{
InitializeComponent();
var doc = new RtfDocument(PaperSize.A4, PaperOrientation.Portrait, Lcid.English);
string rtf;
for (int i = 1; i < 20; i++)
{
RtfCharFormat fmt;
//basic text use bitmap font "roman"
RtfParagraph par = doc.addParagraph();
par.setText("("+i+") This is paragraph");
par.DefaultCharFormat.FontSize = i;
//search in Windows, there is a "roman.fon" in the system
//which is a bitmap font
par.DefaultCharFormat.Font = doc.createFont("roman");
//this section use vector font
fmt = par.addCharFormat(14, 17);
fmt.FgColor = doc.createColor(new DW.RtfWriter.Color(0, 0, 255)); ;
fmt.FontSize = i+10;
fmt.Font = doc.createFont("Times New Roman");
}
rtf = doc.render();
txtMain.Rtf=rtf;
}
If you don't set font for a Rtf section, then RichEditBox will use sort of default font (perhaps the same as Windows common controls), for this defaulft font, it will render with bitmap for some range of font sizes, and render vector font for other sizes that is too small or too big to get a good result from bitmap font.
NetRtfWriter has a default built'in font setting which prevent the above to happen so first modify the source code of NetRtfWriter:
In RtfBasics.cs:
//delete public static string Font = "Times New Roman";
public static string Font = null;//add
In RtfDocument.cs:
//delete rtf.AppendLine(#"{\f" + i + " " + RtfUtility.unicodeEncode(_fontTable[i].ToString()) + ";}");
if (_fontTable[i]!=null) rtf.AppendLine(#"{\f" + i + " " + RtfUtility.unicodeEncode(_fontTable[i].ToString()) + ";}");//add
In the above Winforms test code, remove the font setting to use the "default font":
//delete par.DefaultCharFormat.Font = doc.createFont("roman");
Windows/.NET will decide which size will be rendered with bitmap text, so the final result may depends on system configuration. But whatever the configuration is, you can find (with your face very near the screen and use native resolution of the monitor...) some lines of the result rendered with bitmap (if not, expand the range of i).
For my system which is 4K resolution, 300% system enlarge setting, the default Winforms exe will render 9-13 with bitmap. But when enable "High DPI scaling behavior" and set it to "application" for the executable in Explorer, it will only render 3 and 4 with bitmap.

c# windows forms form is not scaling

I have a window that is not scaling.
I have applied the PerMonitorV2 flag, and also I have in the class
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
When I try to see the window in DPI 100%, everything is fine
When I try to see the window in DPI 150%, I see the overall window size is bigger, but the size of user control didn't enlarge according to the window.
If I delete AutoScaleDimenstion and AutoScaleMode everything works fine in both cases which is so much weird.
Please assist, thanks.

WinForm Simple Raw Bitmap Font Writing?

I need to write in a form using a bitmap font at a specific point size, without having Windows do any antialiasing or otherwise "helping" the display of the text. The reason is that the text will be saved out as a bitmap for display on a low-resolution display (eg a Netduino-driven bitmap with space for 120 pixels wide and 40 pixels high) , so if I want a black "A" on the screen I can't have grey pixels added in and arund the letters.
I need to use a font like this
http://robey.lag.net/2010/01/23/tiny-monospace-font.html
Although I know Windows doesn't do BDF I included that as a reference to the kind of no-nonsense super small typeface that I need to use in Windows.
Using C#, Franework 4.5.2, what can I do to make .NET emit a typeface as a pure unscaled bitmap?
I built a bitmap using the "Tiny" TrueType font at 6 point. Notice in the generated bitmap image that the text is all not pure white, although I specified it that way.
using (var gb = Graphics.FromImage(mybitmap))
{
gb.PixelOffsetMode = PixelOffsetMode.Half;
gb.SmoothingMode = SmoothingMode.None;
gb.InterpolationMode = InterpolationMode.NearestNeighbor;
gb.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
gb.TextContrast = 0;
gb.Clear(colorbg);
var fontSize = Convert.ToSingle(6);
var nowFont = new Font( myfont , fontSize, GraphicsUnit.Pixel );
TextRenderer.DrawText(gb, "pack my box..." , nowFont , new Point(0, 0), colorforeground);
}
Thanks.
Set the Graphics.TextRenderingHint property to TextRenderingHint.SingleBitPerPixelGridFit. If the font has no TrueType hinting at all then SingleBitPerPixel is probably your preferred choice. Either renders text without any anti-aliasing.

WPF FormattedText randomly disappears in high resolution images

I have the requirement to create 600 DPI "trifold" images, which have the dimensions of 25.5"x11" (three times the size of a Letter page). To do so, I’m using WPF Imaging through the DrawingVisual, DrawingContext, and RenderTargetBitmap classes.
When I generate the image in lower resolutions, 400 DPI or less for example, all of the text displays in the correct positions as expected. However, once I increase my image resolution to the 500 DPI level and beyond, certain text positioned in the far right of the image will simply disappear, while other relatively positioned text/shapes print perfectly. The craziest part about it is that as I try varying DPIs, different text will appear/disappear. In one test case, 600 DPI is missing one set of drawn FormattedTexts, 650 DPI is missing a different set of drawn FormattedTexts, and 700 DPI prints everything fine!
I’ve recreated the issue with the snippet of code below. Run as-is (600 DPI) and all you get is a very large white image. Change the Dpi constant to 400 or lower, and it prints the text just fine.
Note that I’ve tried turning many of the knobs within the DrawingVisual class (e.g. VisualBitmapScalingMode, VisualTextRenderingMode, VisualEdgeMode, etc.) to no avail. Most of my research on those settings found them as useful settings to correct “fuzzy” text, not disappearing text. I’ve also had no luck with any of the guideline/snap settings of the DrawingVisual or DrawingContext.
Note that I’ve recreated this issue on both Win7 and Win2008R2, and my application is running .NET 4.5.
Any ideas?
const double ImageWidthInches = 25.5;
const double ImageHeightInches = 11.0;
const double Dpi = 600.0;
const double DeviceIndependentUnits = 96.0;
const double TypographicUnits = 72.0;
var visual = new DrawingVisual();
var drawing = visual.RenderOpen();
drawing.DrawRectangle(
Brushes.White,
null,
new Rect(0,
0,
ImageWidthInches*DeviceIndependentUnits,
ImageHeightInches*DeviceIndependentUnits));
var formattedText = new FormattedText(
"Why doesn't this display?",
CultureInfo.CurrentUICulture,
FlowDirection.LeftToRight,
new Typeface(new FontFamily("Arial Narrow"),
FontStyles.Normal,
FontWeights.Normal,
FontStretches.Normal),
8.0*DeviceIndependentUnits/TypographicUnits,
Brushes.Black);
drawing.DrawText(formattedText,
new Point(23.39*DeviceIndependentUnits,
2.6635416666666671*DeviceIndependentUnits));
drawing.Close();
var renderTarget = new RenderTargetBitmap(
(int) (ImageWidthInches*Dpi),
(int) (ImageHeightInches*Dpi),
Dpi,
Dpi,
PixelFormats.Default);
renderTarget.Render(visual);
var tiffEncoder = new TiffBitmapEncoder {Compression = TiffCompressOption.Ccitt4};
tiffEncoder.Frames.Add(BitmapFrame.Create(renderTarget));
using (var fileStream = new FileStream(#"c:\recreateWpfTextIssue.tif", FileMode.Create, FileAccess.Write))
tiffEncoder.Save(fileStream);
The workaround to this bug is to round the font size to 2 decimal positions:
Math.Round(8.0*DeviceIndependentUnits/TypographicUnits, 2),
This and some extra information can be found in the matching MSDN post: http://social.msdn.microsoft.com/Forums/en-US/98717e53-89f7-4d5f-823b-7184781a7b85/wpf-formattedtext-randomly-disappears-in-high-resolution-images

WPF Background setting failed

Here is a code.
var image = new BitmapImage(new Uri(#"pack://application:,,,/Images/background.png",
UriKind.RelativeOrAbsolute));
var backgroundBrush = new ImageBrush()
{
ImageSource = image,
Viewport = new Rect(0, 0, image.PixelWidth / ActualWidth,
image.PixelHeight / ActualHeight),
TileMode = TileMode.Tile,
Stretch = Stretch.None,
};
// Set it for the main window.
Background = backgroundBrush;
It works just fine on my PC with XPSP3 and .Net 4.0. But when I run the same sample on Eee PC T91MT with Windows 7 Home Premium it fails. No exceptions, but nothing is drawn (solid color brushes ARE drawn if used instead, though). I thought it could be the result of limited resources, but on Viliv S5, that has about the same specs it works fine too.
Any ideas?
Thanks!
UPDATE
The root of the problem is Viewport's rect. Since the bitmap has twice window's size by X, the rect is (0, 0, 2, 1). So, on power computer with XPSP3, the left half of the image is drawn. But on Eee PC it causes a problem with visualization.
The answer is just normalizing Viewport rectangle. E.g. instead of (0,0,2,1) I had to set it as (0,0,1,0.5).
I'm not sure, but it looks like WPF just transmit rect values (after some transformation) into a D3D driver, which is (or is not) able to handle it the right way. So, non-normalized rect Viewport works on GeForce-based machine but does not on Eee PC with it's integrated video's driver.

Resources