Winforms maximized windowstate exceeds monitor size for 64bit application - winforms

I'm migrating a Windows Forms application from 32bit to 64bit. One issue noticed is that the Form in maximized state in x64 overflows the monitor.
Monitor resolution in both cases is 1920 x 1080
Size when setting Maximized state in both cases is 1936 x 1096
However in 32bit it fits the screen perfectly but in 64bit the outer edge exceeds the screen.
Setting the border style to none does fit it better, but it leaves out the border margin around the app and hides the task bar which i dont want:
WindowState = FormWindowState.Normal;
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
Can anyone suggest any pointers please?

Related

WPF Window Left Property with negative values after aligned to left screen border

When aligning a WPF window of my application to the left screen border, my code returns negative values for the Left property of the window (-7, not expected).
The same code returns zero on a peer's PC (as expected).
Display scaling is switched off. It is a plain 96 DPI 1920 x 1200 screen.
AFAIR it worked on my PC as expected some time ago and of course I did not change anything ;-)
So
why does WPF return this value and
why does it work differently on different systems and
how can the 'factory settings' be retrieved?
Background: The application supports saving the window positions to a 'workbench' file and loading it again on a different system. This is difficult to achive if (0,0) is not the same on different systems. (Of course the available screens need to be considered. But this is a different stor.y)
Some more wierd details
System.Windows.SystemParameters.WorkArea.TopLeft is (0,0) (as expected).
Other parameters of System.Windows.SystemParameters.WorkArea are also as expected (width and height).
Setting the position of the application window to (-7,0) moves the window to the top left corner of the screen.
After sizing the window to fill the screen (using the mouse) it's width is 1934 (1920 expected). Setting its width to this values resizes the window to fill the screen(width).
So there seems to be some application specific scaling and offset that is consistent in retrieving and setting window size and position but does not match System.Windows.SystemParameters.WorkArea.
As a workaround the following code can be used:
private double GetWindowLeft(Window window)
{
if (window.WindowState == WindowState.Maximized)
{
var leftField = typeof(Window).GetField("_actualLeft", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
return (double)leftField.GetValue(window);
}
else
return window.Left;
}

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 can I prevent my form from vertically stretching when "live"?

My form looks gorgeous (YMMV) at design-time:
...but gets "stretchy" vertically when running on the device and, in fact, is a little too tall for the screen:
Why would this happen, and how can I prevent it from happening?
Possibly noteworthy: Form's WindowState == Normal, FormBorderStyle = FixedDialog
please check your form settings: AutoScaleMode and Size settings.
Is this your first Windows CE application? You have to keep in mind that there are devices with different resolutions (ie QVGA, square like 320x320 pixels, etc), so you should adjust your layout to the screen size. Or make your form maximized and set AutoScroll to enbaled (if the content does not fit).
When you design your form, you are using pixel counts. These are transformed to twips (1/1440dpi) and again transformed (on the device) back to pixels (including a correction for the resolution, the dots-per-inch (dpi)). So a form with 240x240 pixels will have adifferent size on a 96dpi and a 102dpi display. This scaling is controlled by AutoScaleMode.

Retrieve WP system tray (notification area) height

For some control layout calculations, I need to know the height of the notification area. Sure, I know that it equals 32 pixels in portrait mode in WP 7/8/8.1, but it's not a good idea to hard code this value for the future releases of the OS. How can I retrieve this value on-the-fly in a Silverlight app?
You cant get Height of notification area by Code.
its Standards are Pre-Defined.
System Tray is the small tiny bar across the top of the Phone screen. It displays in Portrait mode. When your application is set in Portrait mode, the height of the System Tray becomes 32 pixel and when the application is set in Landscape mode, the width of the System Tray becomes 72 pixel. This is as per the UI Design Guidelines and Interaction Guideline of Windows Phone 7.
You can get more information here about what is accessible
double contentScaleFactor = (double)Application.Current.Host.Content.ScaleFactor / 100;
double systemTrayHeight = 32 / contentScaleFactor;
Or 72 for landscape orientation. Phones like the Lumia 1520 scale the app content up, so you have to adjust for it.
Found a workaround. We can determine the vertical offset for the main layout root control (generally a Grid), and it will be the height of the system tray:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
GeneralTransform gt = LayoutRoot.TransformToVisual(Application.Current.RootVisual as UIElement);
Point offset = gt.Transform(new Point(0, 0));
double systemTrayHeight = offset.Y;
}

WPF custom drawing and transparency - how to optimize?

I have a WPF application with a custom windows style (AllowsTransparency="True" WindowStyle="None"). This window has a custom Peak Meter control which uses WriteableBitmap to draw data from DirectSound audio input.
I am using a bitmap with all levels drawn as colored rectangles (red/yellow/green/red) and when the audio arrives I just draw a black rectangle over my level meter form the top. It works fine on my machine (Windows 7, Pentium 4 single core). But it works bad on a laptop with Windows XP SP3 and integrated video.
I know that transparency effects have some issues on DirectX 9, but I have read the problem should be fixed in SP3. Still the call to _writeableBitmap.AddDirtyRect takes 30-40% CPU on XP and sometimes it causes dropouts in audio (if USB audio is used, and those dropouts occur not in my application but somewhere in DirectSound<->drivers subsystem).
On Windows 7 the same app takes no more than 3% CPU and no audio dropouts noticed (but the CPU is actually weaker on the Win7 PC than on the laptop with XP).
I tried not to use AddDirtyRect but just draw a WPF Rectangle element over the Image with leds and set the height of the rectangle when new audio level arrives. What a surprise! Somehow changing the height of a Rectangle element takes noticeably less resources than calling _writeableBitmap.AddDirtyRect for 100x20 pixel rectangle! Now on XP it took just 10-20% instead of 30-40% with AddDirtyRect.
But when I removed transparency effect from the window, finally also XP (and even on VirtualBox) went down to 2-6% CPU. Obviously transparency makes it really hard to redraw 20x100 rectangle 10 times per second.
I could live with no transparency in my application, but the problem is - the design uses rounded corner windows and I need to cutoff the area around them. But as soon as I set AllowsTransparency="False", the window shows the background color behind.
So the main question is - how do I make the contents of the window to clip away the background of the window so the corners stay round without using XP-heavy transparency?
I remember that I could do than even on a C++ Windows application just by setting a custom window region and not using any transparency (that was on a Windows 98 machine). Can the same thing be done on WPF?
Or maybe there is some trick how to make WriteableBitmap to use less resources on XP?
As I did not find anything better, I used the old way: SetWindowRgn API.
It was a bit complicated because my application uses some animated slide-out parts which protrude out of the main window so I had to sync WPF animation with SetWindowRgn calls to make slide-out effect look as clean as possible. The result is not ideal but acceptable. And the main thing - no more high CPU and no audio dropouts.

Resources