Show secondary window center of main window in UWP - c#

I started using multiple windows in UWP and need to display secondary windows center of screen or at least center of parent window.
I found nothing relevant about how to specify where to show additional windows on the screen, other than Window.Current.Bounds property.
Here is the simplified version of the method that I am using to create additional windows. The method signature is: CreateFrameWindow(Size size, Type pageType, object parameter)
CoreApplicationView newWindow = CoreApplication.CreateNewView();
ApplicationView newView = null;
bool result = await newWindow.Dispatcher.TryRunAsync(CoreDispatcherPriority.Normal, () =>
{
Frame frame = new Frame();
frame.Navigate(pageType, parameter);
Window.Current.Content = frame;
Window.Current.Activate();
newView = ApplicationView.GetForCurrentView();
});
result = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newView.Id);
newView.TryResizeView(size);
The TryResizeView works fine as long as the secondary window has enough space to resize based on its current location on the screen. I want to enable resize up to the maximum available size (size of window when it is maximized) and place it to the center of the screen. If this is not possible, placing to the center of the parent or main window is acceptable.

Show secondary window center of main window in UWP
CoreApplicationView does not provide api to set the view position manually. For your requirement please try to use AppWindow to archive this feature. And AppWindow has RequestMoveRelativeToDisplayRegion method that position the window in the specified display region at the specified offset. For more please refer official code sample scenario 5
Update
If you want to make your new window display in the center, you need know your windows size before, and calculate X Y value for RequestMoveRelativeToDisplayRegion method.
X = (1920-W)/2 //1920 is Horizontal Resolution W is the new window's width
Y = (1080-H)/2 //1080 is Vertical Resolution H is the new window's height
For get current display resolution please refer this case link
var bounds = ApplicationView.GetForCurrentView().VisibleBounds;
var scaleFactor = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
var size = new Size(bounds.Width*scaleFactor, bounds.Height*scaleFactor);

For AppWindow I'm using...
//Set custom window size
Windows.UI.WindowManagement.Preview.WindowManagementPreview.SetPreferredMinSize(appWindow, new Size(500, 500));
appWindow.RequestSize(new Size(500, 500));
DisplayRegion displayRegion = ApplicationView.GetForCurrentView().GetDisplayRegions()[0];
double displayRegionWidth = displayRegion.WorkAreaSize.Width;
double displayRegionHeight = displayRegion.WorkAreaSize.Height;
int horizontalOffset = (int)(displayRegionWidth - 520); //New window is 500 width + 20 to accomodate for padding
int verticalOffset = (int)(displayRegionHeight - 500); //New window is 500 height
appWindow.RequestMoveRelativeToDisplayRegion(displayRegion, new Point(horizontalOffset / 2 , verticalOffset / 2));

Related

Maximize / Resize to Display Resolution a Windows-10 C# UWP App?

In the below version of App.xaml.cs, written using Visual Studio 2019, associated with my Windows C# UWP solution / project called Example_Application, class App's constructor successfully resizes the blue app window that appears when starting the app. My question: Assuming a resolution scale of 1, just to make things easier, how do I change 1920 and 1080 to the two numbers comprising my Windows-10 display resolution?
namespace Example_Application
{
sealed partial class App : Windows.UI.Xaml.Application
{
public App()
{
Windows.UI.ViewManagement.ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(1920, 1080);
Windows.UI.ViewManagement.ApplicationView.PreferredLaunchWindowingMode = Windows.UI.ViewManagement.ApplicationViewWindowingMode.PreferredLaunchViewSize;
}
protected override void OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs e)
{
Windows.UI.Xaml.Controls.Frame rootFrame = new Windows.UI.Xaml.Controls.Frame();
Windows.UI.Xaml.Window.Current.Content = rootFrame;
rootFrame.Navigate(typeof(MainPage), e.Arguments);
Windows.UI.Xaml.Window.Current.Activate();
}
}
}
Things I've tried:
Changing "PreferredLaunchViewSize" to "Maximized" does not maximize my blue window on my monitor. Changing "PreferredLaunchViewSize" to "FullScreen" does make my application take up the full screen, but this is not what I want because I want to be able to see my application title bar and my Windows-10 taskbar.
I can write Windows.Foundation.Rect visibleBounds = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds; only at the very end of OnLaunched, and bounds' Width and Height properties return present application width and height, not Windows-10 display resolution.
I can write uint screenWidthInRawPixels = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().ScreenWidthInRawPixels; only at the very end of OnLaunched, and screenWidthInRawPixels is the present application width, not Windows-10 display width.
To get the screen resolution in UWP apps, you could try to use DisplayInformation.ScreenHeightInRawPixels Property and DisplayInformation.ScreenWidthInRawPixels Property.
Like the following code:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
........
Window.Current.Activate();
}
//screen resolution
string heightsize = DisplayInformation.GetForCurrentView().ScreenHeightInRawPixels.ToString();
string widthsize = DisplayInformation.GetForCurrentView().ScreenWidthInRawPixels.ToString();
Size mysize = new Size(Convert.ToDouble(widthsize), Convert.ToDouble(heightsize));
ApplicationView.PreferredLaunchViewSize = mysize;
ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;
}
My resolution is 1920*1080. In my test, it could get my screen resolution correctly as 1920*1080.
Ultimately, I choose to maximize my UWP App (written in C#) in my workspace, that area of my screen above my Windows taskbar. I would like to provide minimal instructions for creating a maximized app that you know is working.
I created a new default Blank App (Universal Windows) using C# in Visual Studio Community 2019, called "Draw Bounding Boxes". I included spaces here so that I could access "Draw Bounding Boxes" with spaces from my Start Menu.
I replaced the contents of "App.xaml.cs" with the following code block.
namespace Draw_Bounding_Boxes
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Windows.UI.Xaml.Application
{
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(Windows.ApplicationModel.Activation.LaunchActivatedEventArgs e)
{
// Resize app.
uint screenWidthInRawPixels = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().ScreenWidthInRawPixels;
uint screenHeightInRawPixels = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().ScreenHeightInRawPixels;
double rawPixelsPerViewPixel = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
double screenWidthInViewPixels = System.Convert.ToDouble(screenWidthInRawPixels) / rawPixelsPerViewPixel;
double screenHeightInViewPixels = System.Convert.ToDouble(screenHeightInRawPixels) / rawPixelsPerViewPixel;
// If offsetToScreenWidthInViewPixels is less than 15,
// on first load app will be of default size, and on second load app will be full screen.
// A loaded image will have height equal to full screen height minus app title bar height minus app toolbar height minus 5 view pixels of padding.
// Part of a loaded image with aspect ratio less than one will be behind Windows taskbar.
// This is all very complicated and undesirable.
// If offsetToScreenHeightInViewPixels is less than 40,
// on first load app will be of default size, and on second load app will be full screen.
// A loaded image will have height equal to full screen height minus app title bar height minus app toolbar height minus 5 view pixels of padding.
// Part of a loaded image with aspect ratio less than one will be behind Windows taskbar.
// This is all very complicated and undesirable.
// If offsetToScreenWidthInViewPixels is greater than or equal to 15 and offsetToScreenHeightInViewPixels is greater than or equal to 40,
// on first load app will be of PreferredLaunchViewSize, and a loaded image with aspect ratio less than one will have height exactly equal to height of app minus app title bar height minus app toolbar height.
// If PreferredLaunchViewSize.Height is only screenHeightInViewPixels - offsetToScreenHeightInViewPixels,
// part of app and a loaded image with aspect ratio less than one will be behind taskbar.
// If taskbarHeight is taken off of screenHeightInViewPixels - offsetToScreenHeightInViewPixels,
// bottom of app and coincident bottom of loaded image will be slightly above taskbar.
// I consider this ideal.
double offsetToScreenWidthInViewPixels = 15;
double offsetToScreenHeightInViewPixels = 40;
double taskbarHeight = 40;
Windows.UI.ViewManagement.ApplicationView.PreferredLaunchViewSize = new Windows.Foundation.Size(screenWidthInViewPixels - offsetToScreenWidthInViewPixels, screenHeightInViewPixels - offsetToScreenHeightInViewPixels - taskbarHeight);
Windows.UI.ViewManagement.ApplicationView.PreferredLaunchWindowingMode = Windows.UI.ViewManagement.ApplicationViewWindowingMode.PreferredLaunchViewSize;
// Set the app window to a new Frame.
Windows.UI.Xaml.Controls.Frame rootFrame = new Windows.UI.Xaml.Controls.Frame();
Windows.UI.Xaml.Window.Current.Content = rootFrame;
// Navigate the frame to the initial default page.
rootFrame.Navigate(typeof(MainPage), e.Arguments);
// Attempts to activate the application window by bringing it to the foreground and setting the input focus to it.
Windows.UI.Xaml.Window.Current.Activate();
} // protected override void OnLaunched
} // sealed partial class App
} // namespace Draw_Bounding_Boxes
I added property x:Name="page" to the <Page> tag in "MainPage.xaml".
I removed the <Grid> </Grid> environment from MainPage.xaml.
I replaced the contents of "MainPage.xaml.cs" with the following code block.
// Create namespace Draw_Bounding_Boxes to contain all classes associated with our app.
namespace Draw_Bounding_Boxes
{
// Create class MainPage that inherits fields and methods from Windows.UI.Xaml.Controls.Page and
// is used to declare and define user-interface elements and functionality.
public sealed partial class MainPage : Windows.UI.Xaml.Controls.Page
{
// Create constructor public MainPage.
public MainPage()
{
// Necessary to instantiate this Page, add a stackPanel to this Page, et cetera.
this.InitializeComponent();
// Find width of app in view pixels and height between bottom of app and bottom of title bar in view pixels.
double widthOfAppInViewPixels = Windows.UI.ViewManagement.ApplicationView.PreferredLaunchViewSize.Width;
double heightBetweenBottomOfAppAndBottomOfTitleBarInViewPixels = Windows.UI.ViewManagement.ApplicationView.PreferredLaunchViewSize.Height;
// Create a stackPanel.
Windows.UI.Xaml.Controls.StackPanel stackPanel = new Windows.UI.Xaml.Controls.StackPanel();
// Create a toolbar with width equal to the width of the app, height equal to 50 view pixels, and background color of light blue that has one row and four columns.
Windows.UI.Xaml.Controls.Grid toolbar = new Windows.UI.Xaml.Controls.Grid();
toolbar.Width = widthOfAppInViewPixels;
toolbar.Height = 50;
toolbar.Background = new Windows.UI.Xaml.Media.SolidColorBrush(Windows.UI.Colors.AliceBlue);
Windows.UI.Xaml.Controls.RowDefinition row = new Windows.UI.Xaml.Controls.RowDefinition();
toolbar.RowDefinitions.Add(row);
Windows.UI.Xaml.Controls.ColumnDefinition column = new Windows.UI.Xaml.Controls.ColumnDefinition();
column.Width = new Windows.UI.Xaml.GridLength(widthOfAppInViewPixels);
toolbar.ColumnDefinitions.Add(column);
stackPanel.Children.Add(toolbar);
page.Content = stackPanel;
}
}
}

Xamarin Forms Drag Image between Views

I have an application in Xamarin Forms, and I need that the user can choose one image from below and drag anywhere he wants to in the top view, the idea is: The below view with the images are the home rooms, and the top view is the Houseplant, the user can create his houseplant by dragging and rotating the images, and then finally save the top view as a jpg or png image.
I've searched here and 2 3 pages of google about drag and etc, but I haven't found anything that could help me with that, I tried pan gesture, tap gesture, but no success =[
Sorry if it is duplicated or something, this is my first post, and I really couldn't find anything.
How can I get this working in Xamarin.Forms or at least with custom renderers and etc?
Thank you guys.
Sample image of what I need
For your image in XAML:
<Image Source="plant.png" x:Name="image"/>
You can actually use pan gesture recognizers to drag and drop images in C#:
Define variables:
double x; // totalX for the pan gesture
double y; // totalY for the pan gesture
Initialize pan gesture and add it to the image:
PanGestureRecognizer panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += PanUpdated;
image.GestureRecognizers.Add(panGesture);
The event handler for the gesture:
void PanUpdated(object sender, PanUpdatedEventArgs args)
{
if (args.StatusType.Equals(GestureStatus.Running)) {
x = args.TotalX;
y = args.TotalY;
image.TranslateTo(x, y, 1);
}
else if (args.StatusType.Equals(GestureStatus.Completed)) {
// set the layout bounds of the image to the new position
// method varies depending on what type of layout you are using for the image
// eg. assume the image is in an absolute layout
// where the layout height is the screen height
// and the layout width is the screen width
Task.Run(() => {
Device.BeginInvokeOnMainThread(async () => // run UI task on main thread
{
await Task.Delay(50); // avoid flickering
var screenWidth = Application.Current.MainPage.Width;
var screenHeight = Application.Current.MainPage.Height;
var b = image.Bounds;
var newBounds = new Rectangle(b.X + x, b.Y + y, b.Width, b.Height);
var newAbsoluteBound =
new Rectangle(newBounds.X / (screenWidth - newBounds.Width),
newBounds.Y / (screenHeight - newBounds.Height),
newBounds.Width / screenWidth,
newBounds.Height / screenHeight);
// set new absolute bounds so a new TranslateTo can be applied
AbsoluteLayout.SetLayoutBounds(image, newAbsoluteBound);
await image.TranslateTo(0, 0, 0);
});
});
}
}
Make sure your page or Image is not in a scrollView.
If ScrollView is enabled for both orientations, Pan-Gesture wont work.
.
.

How to compute maximum width/height of the element?

Let's say you have WPF window with one element that changes it size as the window resizes, say DockPanel with two elements. You maximize the window, and the second element gets maximized as well. So not I could read its height/width and those would be maximum values (this is good enough for my purpose, so I don't have to worry if the taskbar takes some space or similar issues).
OK, but let's get back to the freshly started window -- I would like to compute the max width/height of the given element without actually resizing the window, just pure computation. Is it doable? How?
If I understand you correctly you want to know the maximum size the window could be. That would be the size of the screen then. Screensize is an available value:
System.Windows.SystemParameters.PrimaryScreenWidth
System.Windows.SystemParameters.PrimaryScreenHeight
Perhaps you could do something like this:
Get size of window
Get size of element
calculate offset (windowSize - elementSize)
Get Screen size
calculate maximum size (screenSize - offset)
You can create a test window which will appear as maximised, get its width and height and then close it.
This can be done every time you need to calculate values or at the start of the application, assuming you will check whether screen resolution has not changed.
private void GetMaximumWidthAndHeight(FrameworkElement element)
{
var testWindow = new Window();
testWindow.Visibility = Visibility.Collapsed;
testWindow.ShowInTaskbar = false;
testWindow.WindowState = WindowState.Maximized;
testWindow.Show();
var maximizedWindowHeight = testWindow.ActualHeight;
var maximizedWindowWidth = testWindow.ActualWidth;
testWindow.Close();
var maxToCurrentHeightRatio = maximizedWindowHeight / this.ActualHeight;
var maxToCurrentWidthRatio = maximizedWindowWidth / this.ActualWidth;
var maximumElementHeight = element.ActualHeight * maxToCurrentHeightRatio;
var maximumElementWidth = element.ActualWidth * maxToCurrentWidthRatio;
// Do something with the values
}

How do I force my window to re-size?

I have an auto-sized application user control in WPF (Height="Auto" Width="Auto"). When a bunch of elements inside it are resized, the windows stays the same rendered size. How do I force it to resize? I have tried this line Application.Current.MainWindow.SizeToContent = SizeToContent.WidthAndHeight; in the function that resizes the components inside the window. The compiler gives me an error that there is no object associated with this call. I have tried this line MainWindowBorder.Height = Double.NaN; to trick it to resize. No luck either.
Use SizeToContent in XAML
SizeToContent="WidthAndHeight"
https://msdn.microsoft.com/en-us/library/system.windows.window.sizetocontent%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
If all the inside controls can be resized but the only one thing to resize is Window, How about this simple approach? Hope this helps..
int mycurrentscreenwidth = 1366;
int mycurrentwindowwidth = 1366;
var screen = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
var screenwidth = screen.Width;
if (Convert.ToInt32(screenwidth) < 1366)
{
double calculate_scalefactor= Convert.ToInt32(screenwidth) / (double)mycurrentscreenwidth;
double newwidth_tobescaled = mycurrentwindowwidth * calculate_scalefactor;
this.Width = newwidth_tobescaled;
}
To obtain the window of your current user control, see:
Access parent window from User Control
Then use:
Window yourParentWindow = Window.GetWindow(userControl);
yourParentWindow.SizeToContent = SizeToContent.WidthAndHeight;

What is the best way to show a WPF window at the mouse location (to the top left of the mouse)?

I have found that this works PART of the time by inheriting the Windows Forms mouse point and subtracting out the height and width of my window to set the left and top (since my window's size is fixed):
MyWindowObjectThatInheritsWindow window = new MyWindowObjectThatInheritsWindow();
System.Windows.Point mouseLocation = GetMousePositionWindowsForms();
window.Left = mouseLocation.X - 300;
window.Top = mouseLocation.Y - 240;
window.Show();
Edit: Here is the code for getting the mouse position...
public System.Windows.Point GetMousePositionWindowsForms()
{
System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
return new System.Windows.Point(point.X, point.Y);
}
Note that this works by making the bottom right edge of the window touch the top left of your mouse cursor. But this breaks for different screen resolutions, or maybe multiple monitors with different resolutiosn? I haven't fully narrowed it down yet, but I just tried this same code on another PC, and it seems to spawn the window not to the top left of the mouse cursor, but to the bottom left of it, and a good distance past it...
I should probably add that my window sizes to content, width and height, so I can't just use the ActualWidth and ActualHeight properties since they're not available. Perhaps the issue is in getting that sizing right? Is there any way to do that? I know for sure the 300 and 240 is correct according to my main PC with two monitors running 1920x1080 resolutions, as I have calculated the widths and heights of all the objects in my window which I have explicitly sized. Edit: Just tried explicitly setting the height and width to 240/300, to ensure that the window is no longer sized to content, and I still have this issue when subtracting out the actual height and width!
Any ideas?
In the end, this did the trick:
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
MoveBottomRightEdgeOfWindowToMousePosition();
}
private void MoveBottomRightEdgeOfWindowToMousePosition()
{
var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
var mouse = transform.Transform(GetMousePosition());
Left = mouse.X - ActualWidth;
Top = mouse.Y - ActualHeight;
}
public System.Windows.Point GetMousePosition()
{
System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
return new System.Windows.Point(point.X, point.Y);
}
Can you not use something like this?:
Point mousePositionInApp = Mouse.GetPosition(Application.Current.MainWindow);
Point mousePositionInScreenCoordinates =
Application.Current.MainWindow.PointToScreen(mousePositionInApp);
I haven't been able to test it, but I think it should work.
UPDATE >>>
You don't have to use the Application.Current.MainWindow as the parameter in these methods... it should still work if you have access to a Button or another UIElement in a handler:
Point mousePositionInApp = Mouse.GetPosition(openButton);
Point mousePositionInScreenCoordinates = openButton.PointToScreen(mousePositionInApp);
Again, I haven't been able to test this, but if that fails as well, then you can find one more method in the How do I get the current mouse screen coordinates in WPF? post.
You can also do this by slightly modifying your initial example and positioning the window before showing it.
MyWindowObjectThatInheritsWindow window = new MyWindowObjectThatInheritsWindow();
var helper = new WindowInteropHelper(window);
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
var transformFromDevice = hwndSource.CompositionTarget.TransformFromDevice;
System.Windows.Point wpfMouseLocation = transformFromDevice.Transform(GetMousePositionWindowsForms());
window.Left = wpfMouseLocation.X - 300;
window.Top = wpfMouseLocation.Y - 240;
window.Show();

Categories

Resources