-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathDirectoryPickerWindow.xaml.cs
More file actions
94 lines (80 loc) · 3.34 KB
/
Copy pathDirectoryPickerWindow.xaml.cs
File metadata and controls
94 lines (80 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
using System;
using System.Runtime.InteropServices;
using Windows.Graphics;
using Coder.Desktop.App.Utils;
using Coder.Desktop.App.ViewModels;
using Coder.Desktop.App.Views.Pages;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
using WinRT.Interop;
using WinUIEx;
namespace Coder.Desktop.App.Views;
public sealed partial class DirectoryPickerWindow : WindowEx
{
public DirectoryPickerWindow(DirectoryPickerViewModel viewModel)
{
InitializeComponent();
TitleBarIcon.SetTitlebarIcon(this);
viewModel.Initialize(this, DispatcherQueue);
RootFrame.Content = new DirectoryPickerMainPage(viewModel);
// This will be moved to the center of the parent window in SetParent.
this.CenterOnScreen();
}
public void SetParent(Window parentWindow)
{
// Move the window to the center of the parent window.
var scale = DisplayScale.WindowScale(parentWindow);
var windowPos = new PointInt32(
parentWindow.AppWindow.Position.X + parentWindow.AppWindow.Size.Width / 2 - AppWindow.Size.Width / 2,
parentWindow.AppWindow.Position.Y + parentWindow.AppWindow.Size.Height / 2 - AppWindow.Size.Height / 2
);
// Ensure we stay within the display.
var workArea = DisplayArea.GetFromPoint(parentWindow.AppWindow.Position, DisplayAreaFallback.Primary).WorkArea;
if (windowPos.X + AppWindow.Size.Width > workArea.X + workArea.Width) // right edge
windowPos.X = workArea.X + workArea.Width - AppWindow.Size.Width;
if (windowPos.Y + AppWindow.Size.Height > workArea.Y + workArea.Height) // bottom edge
windowPos.Y = workArea.Y + workArea.Height - AppWindow.Size.Height;
if (windowPos.X < workArea.X) // left edge
windowPos.X = workArea.X;
if (windowPos.Y < workArea.Y) // top edge
windowPos.Y = workArea.Y;
AppWindow.Move(windowPos);
var parentHandle = WindowNative.GetWindowHandle(parentWindow);
var thisHandle = WindowNative.GetWindowHandle(this);
// Set the parent window in win API.
NativeApi.SetWindowParent(thisHandle, parentHandle);
// Override the presenter, which allows us to enable modal-like
// behavior for this window:
// - Disables the parent window
// - Any activations of the parent window will play a bell sound and
// focus the modal window
//
// This behavior is very similar to the native file/directory picker on
// Windows.
var presenter = OverlappedPresenter.CreateForDialog();
presenter.IsModal = true;
AppWindow.SetPresenter(presenter);
AppWindow.Show();
// Cascade close events.
parentWindow.Closed += OnParentWindowClosed;
Closed += (_, _) =>
{
parentWindow.Closed -= OnParentWindowClosed;
parentWindow.Activate();
};
}
private void OnParentWindowClosed(object? sender, WindowEventArgs e)
{
Close();
}
private static class NativeApi
{
[DllImport("user32.dll")]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
public static void SetWindowParent(IntPtr window, IntPtr parent)
{
SetWindowLongPtr(window, -8, parent);
}
}
}