I am developing Windows 10 Universal App using C#. My question is refers to a case when an user runs my application on PC/desktop.
I want my app to be full screen, this can by done by calling
Windows.UI.ViewManagement::TryEnterFullScreenMode()
Now we are in full screen. But when user swipes mouse pointer to lower edge of the screen Windows' Taskbar will appear and I don't want it to appear - what can I do?
I've tried setting FullScreenSystemOverlayMode property of corresponding Windows.UI.ViewManagement to FullScreenSystemOverlayMode.
Minimal alongside with setting SuppressSystemOverlays to true.
Neither has helped, what can I do?
When I do something like that I use:
ApplicationView.GetForCurrentView().SuppressSystemOverlays = true;
ApplicationView.GetForCurrentView().FullScreenSystemOverlayMode = FullScreenSystemOverlayMode.Minimal;
ApplicationView.GetForCurrentView().TryEnterFullScreenMode();
Maybe just semantics, but sometime those semantics matter.
Related
I have an app that displays video in a subview and where it would be nice to give the option to display that video on a second screen such as an Apple TV and be able to use that freed-up space to show additional controls.
I've found all sorts of help about how to do that, but I'm hitting a wall even before getting out of the starting gate.
In order to detect that the app has started up in a multiple display environment, all the sample code features a line like...
if (UIScreen.Screens.Length > 1) {
// ...
}
(I'm doing this in C#/Xamarin, though I doubt the problem is related to that; anyway, the snippets are in C#)
My problem is that the array of screens is always 1 no matter what I do. The iPad is running iOS 11.2.5, and if I turn on mirroring, the iPad is mirrored, but , again, the array of screens only has a single item.
There are also a couple of observers to detect screens being added/removed while the app is running. I haven't seen Xamarin specific code, but I presume it looks like:
NSNotificationCenter.DefaultCenter.AddObserver(this, UIScreen.DidConnectNotification, NSKeyValueObservingOptions.New, IntPtr.Zero);
NSNotificationCenter.DefaultCenter.AddObserver(this, UIScreen.DidDisconnectNotification, NSKeyValueObservingOptions.New, IntPtr.Zero);
Anyway, those never fire even if I add/remove the Apple TV or enter/exit Mirroring Mode on the iPad.
Oh; also if I do
avPlayer.AllowsExternalPlayback = true;
avPlayer.UsesExternalPlaybackWhileExternalScreenIsActive = true;
then that works as expected, too. The video now appears full-screen on the Apple TV and the UIView on the iPad containing the avPlayer greys out rather than showing the video.
However, that's not what I'm looking for. I would like to control the layout of both screens and that does neither. (While I do want the video to be full screen on the Apple TV, I don't want it to be an AVPlayerViewController and I do want to repurpose the screen real-estate taken up by the iPad video view)
At the end of the day, all I think I need is to manage to get
UIScreen.Screens.Length to be equal to 2 when I launch the app.
What's the secret of getting UIScreen to detect/report a second display?
When an app is launched with screen mirroring already enabled, the UIScreen.screens array initially only contains the device's screen. Shortly after launch, iOS posts a UIScreenDidConnect notification to advise your app that a second screen is connected.
What you will see at launch is that the captured property of your main screen is true if mirroring is enabled, however you can't actually access the second screen until after the notification is posted. Note that captured could also indicate that screen recording is in progress.
Although this seems slightly counter-intuitive it actually makes your coding a little simpler; you need to observe the UIScreenDidConnect and UIScreenDidDisconnect notifications anyway and now you don't need to write any special code to handle the case where the app is launched with a second screen already attached.
You can use something like this in your didFinishLaunching:
let nc = NotificationCenter.default
nc.addObserver(forName: NSNotification.Name.UIScreenDidConnect, object: nil, queue: nil) { (notification) in
print("Screen connected")
self.enableExternalDisplay()
}
nc.addObserver(forName: NSNotification.Name.UIScreenDidDisconnect, object: nil, queue: nil) { (notification) in
print("Screen disconnected")
self.disableExternalDisplay()
}
UPDATE
Actually, it looks like you have the key/value observing format of AddObserver in your code, when you actually want notification observing. Something like:
NSNotificationCenter.DefaultCenter.AddObserver(UIScreen.DidConnectNotification,OnScreenConnected)
And then you need to implement an OnScreenConnected method.
I have two UWP apps and after testing them out with Continuum I noticed the app bar of the OS (the bar with the Start button) at the bottom of the screen (it can be at each of the 4 edges of the screen, of course) was covering part of my app.
Now, I'm already using ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseVisible) before calling Window.Current.Activate(), but that doesn't seem to solve the issue.
1) Why is it that setting the DesiredBoundsMode property doesn't seem to work here? Shouldn't that automatically resize the window
content to the visible bounds (ie. excluding system overlays like the
navigation bar or the app bar)?
The workaround I'm using for now on Windows 10 Mobile devices is to subscribe to the VisibleBoundsChanged event and then manually adjust the margins of my Window.Current.Content item to make sure it doesn't show anything behind covered areas of the screen.
Basically, I use the Window.Current.Bounds property and the ApplicationView.VisibleBounds property to calculate the occluded areas on the different edges of the app window, and increase the margins from there.
2) Is there a proper/better way to do this?
I mean, I'm quite sure there's another method that should be used to avoid this issue (considering there are tons of different situations like Continuum, navigation bar etc... that I don't think are supposed to be manually handled one by one).
Thank you for your help!
Use the subscription to the event VisibleBoundsChanged. This is the best solution that I found.
var curr = ApplicationView.GetForCurrentView();
if (curr.IsFullScreenMode == true)
{
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.FullScreen;
curr.FullScreenSystemOverlayMode = FullScreenSystemOverlayMode.Minimal;
}
else
{
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.Auto;
curr.FullScreenSystemOverlayMode = FullScreenSystemOverlayMode.Standard;
}
I have written a WPF desktop app that I want to put in the Windows Store using the Desktop Bridge. The app is capable of presenting itself in light and dark modes, and using an accent color. But, to be a good citizen of Windows 10, I want to get that information from the OS, if possible.
It is my current understanding that I can get the accent color from here:
var accentBrush = SystemParameters.WindowGlassBrush;
How can I get whether Windows 10 is in its light or dark theme? Also, what method would you recommend to be notified of a change in the user's preference for either light/dark or the accent color?
There is a registry value that is updated whenever this light/dark mode setting in Windows 10 Anniversary Update or later changes. It's key is:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize
The name of the value is:
AppsUseLightTheme
If it is 1, then the theme is Light. If it is 0, then the theme is Dark. I'm going to assume Light if I can't find the key or the value (as would be the case in previous versions of Windows).
As far as I'm concerned, lindexi deserves credit for the answer. Without that comment, it didn't occur to me to investigate.
Some simple code to give you a bool for light mode in normal WPF apps, not UWP.
Never tested with high contrast modes.
If the value does not exist or something goes wrong, it assumes light mode.
bool is_light_mode = true;
try
{
var v = Microsoft.Win32.Registry.GetValue(#"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", "1");
if (v != null && v.ToString() == "0")
is_light_mode = false;
}
catch { }
Some users might have custom setting. Like Dark App mode and Light System mode. If user has Light System mode, it will make the Taskbar and Start menu in light color.
Like #Daniel Henry said above, AppsUseLightTheme value name tells Light/Dark App mode. Similarly SystemUsesLightTheme value name tells about Light/Dark System mode. This could be helpful for apps which have System tray icons and want to make their tray icon it clearly visible.
I am working on a Windows Store App using C#.
I am trying to change the cursor when the user hover over a rectangle but it is causing me problems.
Here is my code:
Rectangle item = sender as Rectangle;
item.Cursor = Cursors.AppStarting;
mouseVerticalPosition = e.GetCurrentPoint(null).Position.Y;
mouseHorizontalPosition = e.GetCurrentPoint(null).Position.X;
isMouseCaptured = true;
item.CapturePointer(e.Pointer);
It says 'Windows.UI.Xaml.Shapes.Rectangle' does not contain a definition for 'Cursor'.
You're confusing WPF with WinRT/XAML. These are both XAML-based UI technologies, but although superficially similar when looking at some basic controls and properties - these are completely separate implementations that have many differences once you start looking at the details. One of these is the Cursor property missing in the Windows Runtime.
You can use Window.Current.CoreWindow.PointerCursor property to get or set the cursor on the current window.
You can also use some attached behaviors I wrote in WinRT XAML Toolkit here to get an API similar to the WPF one where you set a cursor per element. There's a sample you can check here that shows how you can set a cursor on an element like this:
Extensions:FrameworkElementExtensions.SystemCursor="Arrow"
I have a C# Windows application that I want to ensure will show up on a second monitor if the user moves it to one. I need to save the main form's size, location and window state - which I've already handled - but I also need to know which screen it was on when the user closed the application.
I'm using the Screen class to determine the size of the current screen but I can't find anything on how to determine which screen the application was running on.
Edit: Thanks for the responses, everyone! I wanted to determine which monitor the window was on so I could do proper bounds checking in case the user accidentally put the window outside the viewing area or changed the screen size such that the form wouldn't be completely visible anymore.
You can get an array of Screens that you have using this code.
Screen[] screens = Screen.AllScreens;
You can also figure out which screen you are on, by running this code (this is the windows form you are on)
Screen screen = Screen.FromControl(this); //this is the Form class
in short check out the Screen class and static helper methods, they might help you.
MSDN Link, doesn't have much..I suggest messing around in the code by yourself.
If you remember the window's location and size, that will be enough. When you set the position to the previously used position, if it happened to be on the second monitor it will go back there.
For example, if you have 2 monitors, both sized 1280x1024 and you set your window's left position to be 2000px, it will appear on the second monitor (assuming the second monitor is to the right of the first.) :)
If you are worried about the second monitor not being there when the application is started the next time, you can use this method to determine if your window intersects any of the screens:
private bool isWindowVisible(Rectangle rect)
{
foreach (Screen screen in Screen.AllScreens)
{
if (screen.Bounds.IntersectsWith(rect))
return true;
}
return false;
}
Just pass in your window's desired location and it will tell you if it will be visible on one of the screens. Enjoy!
You can get the current Screen with
var s = Screen.FromControl(this);
where this is the Form (or any control on the Form). As about how to remember that is a little tricky, but I would go for the index in the Screen.AllScreens array, or maybe s.DeviceName. In either case, check before using the settings on startup, to prevent using a monitor that was disconnected.
The location of the form will tell you which screen the form is on. I don't really understand why you'd need to know what screen it is on, because if you restore it using the location you saved it should just restore to the same location (maybe you can expand as to why).
Otherwise you can do something like this:
Screen[] scr = Screen.AllScreens;
scr[i].Bounds.IntersectsWith(form.Bounds);
Each screen has a Bounds property which returns a Rectangle. You can use the IntersectsWith() function to determine if the form is within the screen.
Also, they basically provide a function that does this as well on the Screen class
Screen screen = Screen.FromControl(form);
You can use the 'Screen' object:
System.Windows.Forms.Screen
Start playing with something like this:
Screen[] screens = Screen.AllScreens;
for (int i = 0; i < screens.Length ; i++)
{
Debug.Print(screens[i].Bounds.ToString());
Debug.Print(screens[i].DeviceName);
Debug.Print(screens[i].WorkingArea.ToString());
}
It may get you what you need