c# windows forms form is not scaling - winforms

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.

Related

wpf notifyicon context menu not centered on tray icon at 100% dpi

I'm using the wpf notifyicon (http://www.hardcodet.net/wpf-notifyicon)
When my laptop is at 100% dpi scaling, the left side of the context menu is centred on the tray icon, as expected.
When the laptop isn't at 100%, the context menu is pushed to the far right.
On high resolution laptop displays, 100% scaling is not the default.
Wherever my tray icon is positioned, that is, however far from the clock, the menu always pops up over the clock, as far to the bottom-right of the screen as is possible while remaining visible.
Note: I'm testing on a default installation of Windows 8.1. Also, the NotifyIcon that I'm using is the one that is generally recommended for anyone attempting tray functionality in WPF.
To reproduce: the problem exists in the windowless sample provided by hardcodet. I'm using wpf NotifyIcon without a window, and can reproduce easily in code or xaml. In fact, I cannot stop reproducing it. It occurs when dpi scaling is turned on, i.e. when a 1080p display is actually showing a lesser resolution, which is what windows does to stop applications having text too tiny to read.
Any ideas about how I can make the context menu appear in the expected place regardless of dpi?
Screen shots as suggested by kennyzx:
good behaviour. the m on red background (MEGAsync) has just been right-clicked
bad behaviour. the green tick, my notifyicon, has just been right-clicked and the menu appears over the clock
!good behaviour. the m on red background (MEGAsync) has just been right-clicked
!bad behaviour. the green tick, my notifyicon, has just been right-clicked and the menu appears over the clock
and some code:
var n = new TaskbarIcon();
n.Icon=new System.Drawing.Icon(#"C:\window - 64 - tick.ico");
n.ContextMenu = new System.Windows.Controls.ContextMenu();
n.ContextMenu.Items.Add(new System.Windows.Controls.MenuItem {Header="E_xit" });
Found the solution here: http://www.codeproject.com/Messages/4929452/Problem-with-context-menu-position.aspx
It is, with thanks to codeproject user Igorious:
Get the code for Wpf Notifyicon (http://www.hardcodet.net/wpf-notifyicon)).
In Hardcodet.Wpf.TaskbarNotification.TaskbarIcon.ShowContextMenu()
replace
ContextMenu.HorizontalOffset = cursorPosition.X;
ContextMenu.VerticalOffset = cursorPosition.Y;
with
var g = Graphics.FromHwnd(IntPtr.Zero);
var scaleX = g.DpiX / 96.0;
var scaleY = g.DpiY / 96.0;
ContextMenu.HorizontalOffset = cursorPosition.X / scaleX;
ContextMenu.VerticalOffset = cursorPosition.Y / scaleY;
Explanation (thanks to codeproject user yachting):
It's needed because WinApi.GetPhysicalCursorPos return the mouse position in pixel,
but WPF's measurement unit is device independent pixel (by definition, it's 1/96 inch)
You need to adjust the return value of GetPhysicalCursorPos by DPI (dots per inch) setting,
otherwise the position of the context menu will be incorrect if users set DPI other than the default 96.

How to accelerate WPF fade in/out animation

I implemented lightbox effect with window's opacity change whilst fading in/out. When I have my window maximized this effect has big delay or when I use duration property then opacity change is not smooth.
I manage this eg. with like here:
DoubleAnimation animate = new DoubleAnimation();
animate.From = 1.0;
animate.To = 0.5;
animate.Duration = new Duration(TimeSpan.FromSeconds(0));
this.BeginAnimation(Window.OpacityProperty, animate); // main window
Window1 win = new Window1(); // new window to get focus
win.ShowDialog();
Tell me please, if you know, does this effect works on GPU by default? If not, can I manage this somehow?
The maximization issue sounds like the computer might have performance issues, and the Duration issue exists because you set it to 0, a zero second animation is instant, of course it is not smooth.

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

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.

Can't consistently maximize WPF window

I have a minimized WPF window. I click the item in the taskbar to maximize. It makes a little audio ding, then I try again, and again. Usually about the third try it will maximize. What could cause it to refuse my initial maximize attempt?
One possibility is that you have some code that's changing the value of the ResizeMode property to NoResize.
See this page for more: http://msdn.microsoft.com/en-us/library/ms748948.aspx
Second, you might be overriding OnStateChanged and not calling base.OnStateChanged() consistently.
Third, you may have something hogging the UI's thread during your first attempts. Once that task--whatever it is--stops blocking then WPF can repaint the window in restored/maximized state.
I had a similar problem when trying to manually maximize a custom window.
The solution was to put the next code in my maximize button...
this.SizeToContent = System.Windows.SizeToContent.Manual;
this.MaxWidth = double.PositiveInfinity;
this.MaxHeight = double.PositiveInfinity;
this.Width = double.NaN;
this.Height = double.NaN;
this.WindowState = WindowState.Maximized;
Where 'this' referes to the Window.

WPF Window with Style=None cover taskbar when Maximised after app initialization

I want to achieve the same effect as Windows Media Player or Browser based Flash players which take up the ENTIRE (not even the taskbar is visible) real estate when maximized.
This works fine if the WindowState is set to Maximized and the WindowStyle is set to None in XAML so the app is started in that state. Problem is I want to start the app in a bordered window and when the user chooses, maximize as specified above. In the StateChanged handler I check for Maximized state and if this is the case I set the WindowStyle to None. This has the effect of maximizing the window but NOT covering the taskbar. The following code will make this work as I want but its a hack and I'd like to clean it up:
if (WindowState == WindowState.Maximized)
{
m_videoWindow.Maximize();
WindowStyle = WindowStyle.None;
//the following makes this work but I would like to clean it up
Hide();
Show();
}
EDIT This (from 2006 when still in CTP) mentions the problem and someone from MS states they hope to improve full screen support in the next version, have these improvements been made?
This article explains it all: Maximizing window (with WindowStyle=None) considering Taskbar.
Also worth checking out: Custom Window Chrome in WPF.
Edit: Now new, is the WPF Shell Integration Library that allows complete restyle of the window chrome without the headaches of reimplementing move, resizing, etc.
Edit 2015: Shell Integration Library is now integrated in WPF and MS retired the code
I found I could maximize to full screen (covering the taskbar) by setting the properties when creating the window (in xaml), but was not able to switch back and forth after creation. After some experimenting, I found the order the properties are set seems to matter:
public bool IsFullscreen
{
get
{
return WindowState == System.Windows.WindowState.Maximized
&& ResizeMode == System.Windows.ResizeMode.NoResize
&& WindowStyle== System.Windows.WindowStyle.None;
}
set
{
if ( value )
{
ResizeMode = System.Windows.ResizeMode.NoResize;
WindowStyle = System.Windows.WindowStyle.None;
WindowState = System.Windows.WindowState.Maximized;
}
else
{
ResizeMode = System.Windows.ResizeMode.CanResize;
WindowStyle = System.Windows.WindowStyle.SingleBorderWindow;
WindowState = System.Windows.WindowState.Normal;
}
}
}
Note that WindowState comes last in the setter.
To get this to properly work in my WPF/.NET 4.0 application I am calling this function whenever I enter or exit full screen mode:
private static void RefreshWindowVisibility(Window window)
{
if (window.OriginalWindowState == WindowState.Maximized)
{
window.Hide();
window.Show();
window.BringIntoView();
}
}
There is a flicker associated with this method, but it seems the same flicker exists when going to full screen mode on Chrome. Internet Explorer seems to take a different approach.
I don't know if this is ok for you, but you can resize the window to have the same size than the working area (that is, in most cases, all the screen except the taskbar) and locate it at 0,0 (top-left corner):
Width = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
Height = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
Left = 0;
Top = 0;
The exact definition for the WorkingArea property (from MSDN) is:
Gets the working area of the display. The working area is the desktop area of the display, excluding taskbars, docked windows, and docked tool bars.
Hope it helps

Resources