Skip to content

Commit 02bca6b

Browse files
Working on app model
1 parent 8c7af27 commit 02bca6b

File tree

7 files changed

+101
-31
lines changed

7 files changed

+101
-31
lines changed

ShortDev.Uwp.FullTrust/Core/Xaml/XamlApplicationWrapper.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ public sealed class XamlApplicationWrapper : IDisposable
1212

1313
public XamlApplicationWrapper(Func<XamlApplication> callback)
1414
{
15-
if (Current != null)
16-
throw new InvalidOperationException($"Only one instance of \"{nameof(XamlApplicationWrapper)}\" is allowed!");
15+
ThrowOnAlreadyRunning();
1716

1817
Application = callback();
1918
Current = this;
@@ -24,6 +23,11 @@ public void Dispose()
2423
Application = null;
2524
}
2625

26+
internal static void ThrowOnAlreadyRunning()
27+
{
28+
if (Current != null)
29+
throw new InvalidOperationException($"Only one instance of \"{nameof(XamlApplicationWrapper)}\" is allowed!");
30+
}
2731

2832
public static XamlApplicationWrapper? Current { get; private set; }
2933

ShortDev.Uwp.FullTrust/Core/Xaml/XamlWindowActivator.cs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO;
55
using System.Runtime.InteropServices;
66
using System.Threading;
7+
using Windows.ApplicationModel.Core;
78
using Windows.UI.Core;
89
using Windows.UI.Xaml;
910
using Windows.UI.Xaml.Markup;
@@ -20,6 +21,9 @@ public sealed class XamlWindowActivator
2021
/// A <see cref="XamlWindowSubclass"/> will be attached automatically.
2122
/// </summary>
2223
public static XamlWindow CreateNewWindow(XamlWindowConfig config)
24+
=> CreateNewInternal(config).window;
25+
26+
internal static (CoreApplicationView coreAppView, XamlWindow window) CreateNewInternal(XamlWindowConfig config)
2327
{
2428
if (XamlApplicationWrapper.Current == null)
2529
throw new InvalidOperationException($"No instance of \"{nameof(XamlApplicationWrapper)}\" was found!");
@@ -57,22 +61,23 @@ public static XamlWindow CreateNewWindow(XamlWindowConfig config)
5761
subclass.IsTopMost = config.IsTopMost;
5862
subclass.HasWin32TitleBar = config.HasWin32TitleBar;
5963

60-
//coreWindow.Closed += (CoreWindow window, CoreWindowEventArgs args) =>
61-
//{
62-
// subclass.Dispose();
63-
//};
64+
coreWindow.Closed += (CoreWindow window, CoreWindowEventArgs args) =>
65+
{
66+
subclass.Dispose();
67+
};
6468

6569
// Show window
6670
if (config.IsVisible)
6771
window.Activate();
6872

69-
return window;
73+
return (coreView, window);
7074
}
7175

7276
/// <summary>
7377
/// Creates a new <see cref="XamlWindow"/>, loads xaml from a <see cref="Stream"/> and sets it as <see cref="XamlWindow.Content"/>. <br/>
7478
/// The <see cref="Stream"/> will be disposed automatically!
7579
/// </summary>
80+
[Obsolete]
7681
public static XamlWindow CreateNewFromXaml(XamlWindowConfig config, Stream xamlStream)
7782
{
7883
using (xamlStream)
@@ -83,20 +88,13 @@ public static XamlWindow CreateNewFromXaml(XamlWindowConfig config, Stream xamlS
8388
/// <summary>
8489
/// Creates a new <see cref="XamlWindow"/> and sets xaml as <see cref="XamlWindow.Content"/>. <br/>
8590
/// </summary>
91+
[Obsolete]
8692
public static XamlWindow CreateNewFromXaml(XamlWindowConfig config, string xaml)
8793
{
8894
var window = CreateNewWindow(config);
8995
UIElement content = (UIElement)XamlReader.Load(xaml);
9096
window.Content = content;
9197
return window;
9298
}
93-
94-
public static void CreateNewThread(Action callback)
95-
{
96-
Thread thread = new(() => callback());
97-
thread.SetApartmentState(ApartmentState.STA);
98-
thread.IsBackground = true;
99-
thread.Start();
100-
}
10199
}
102100
}

ShortDev.Uwp.FullTrust/Core/Xaml/XamlWindowConfig.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
1-
namespace ShortDev.Uwp.FullTrust.Core.Xaml
1+
using System.Diagnostics;
2+
using Windows.ApplicationModel;
3+
4+
namespace ShortDev.Uwp.FullTrust.Core.Xaml
25
{
36
public sealed class XamlWindowConfig
47
{
8+
public static XamlWindowConfig Default
9+
{
10+
get
11+
{
12+
string windowTitle = Process.GetCurrentProcess().ProcessName;
13+
try
14+
{
15+
windowTitle = Package.Current?.DisplayName ?? windowTitle;
16+
}
17+
catch { }
18+
return new(windowTitle);
19+
}
20+
}
21+
522
public XamlWindowConfig(string title)
623
=> this.Title = title;
724

ShortDev.Uwp.FullTrust/ShortDev.Uwp.FullTrust.csproj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@
2626
<PackageReference Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.1">
2727
<PrivateAssets>all</PrivateAssets>
2828
</PackageReference>
29-
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
29+
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0">
30+
<PrivateAssets>all</PrivateAssets>
31+
</PackageReference>
32+
<PackageReference Include="System.Runtime.InteropServices.WindowsRuntime" Version="4.3.0">
33+
<PrivateAssets>all</PrivateAssets>
34+
</PackageReference>
3035
</ItemGroup>
3136

3237
<ItemGroup>

ShortDev.Uwp.FullTrust/Windows/UI/Xaml/FullTrustApplication.cs

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
using ShortDev.Uwp.FullTrust.Core.Xaml;
22
using System;
3-
using System.Diagnostics;
3+
using System.Reflection;
44
using System.Runtime.InteropServices;
55
using System.Threading;
6-
using Windows.ApplicationModel;
76
using Windows.ApplicationModel.Activation;
7+
using Windows.ApplicationModel.Core;
88
using Windows.System;
99
using Windows.UI.ViewManagement;
1010

@@ -26,28 +26,34 @@ public static Application Current
2626
[MTAThread]
2727
public static void Start([In] ApplicationInitializationCallback callback)
2828
{
29-
Thread thread = new(() =>
29+
XamlApplicationWrapper.ThrowOnAlreadyRunning();
30+
31+
Start(callback, XamlWindowConfig.Default);
32+
}
33+
34+
/// <inheritdoc cref="Start(ApplicationInitializationCallback)" />
35+
/// <param name="windowConfig">Custom <see cref="XamlWindowConfig"/>.</param>
36+
[MTAThread]
37+
public static void Start([In] ApplicationInitializationCallback callback, [In] XamlWindowConfig windowConfig)
38+
{
39+
XamlApplicationWrapper.ThrowOnAlreadyRunning();
40+
41+
Thread thread = CreateNewUIThread(() =>
3042
{
3143
// Application singleton is created here
3244
callback(null);
3345

34-
string windowTitle = Process.GetCurrentProcess().ProcessName;
35-
try
36-
{
37-
windowTitle = Package.Current?.DisplayName ?? windowTitle;
38-
}
39-
catch { }
46+
// Satisfy our api
47+
_ = new XamlApplicationWrapper(() => Application.Current);
4048

4149
// Create XamlWindow
42-
var window = XamlWindowActivator.CreateNewWindow(new(windowTitle));
50+
var window = XamlWindowActivator.CreateNewWindow(windowConfig);
4351

4452
InvokeOnLaunched();
4553

4654
// Run message loop
4755
XamlWindowSubclass.ForWindow(window).CurrentFrameworkView!.Run();
4856
});
49-
thread.SetApartmentState(ApartmentState.STA);
50-
thread.Start();
5157
thread.Join();
5258
}
5359

@@ -56,7 +62,11 @@ public static void Start([In] ApplicationInitializationCallback callback)
5662
/// </summary>
5763
static void InvokeOnLaunched()
5864
{
59-
IApplicationOverrides applicationOverrides = (IApplicationOverrides)Current;
65+
var app = Current;
66+
app.GetType().GetMethod("OnLaunched", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(app, new[] { new Win32LaunchActivatedEventArgs() as object as LaunchActivatedEventArgs });
67+
68+
return;
69+
IApplicationOverrides applicationOverrides = (IApplicationOverrides)app;
6070
applicationOverrides.OnLaunched(new Win32LaunchActivatedEventArgs());
6171
}
6272

@@ -101,5 +111,29 @@ public TileActivatedInfo TileActivatedInfo
101111
public User User
102112
=> _currentUser;
103113
}
114+
115+
public static Thread CreateNewUIThread(Action callback)
116+
{
117+
if (callback == null)
118+
throw new ArgumentNullException(nameof(callback));
119+
120+
Thread thread = new(() => callback());
121+
thread.SetApartmentState(ApartmentState.STA);
122+
thread.Start();
123+
return thread;
124+
}
125+
126+
/// <summary>
127+
/// Creates a new view for the app.
128+
/// </summary>
129+
public static CoreApplicationView CreateNewView()
130+
=> CreateNewView(XamlWindowConfig.Default);
131+
132+
/// ´<inheritdoc cref="CreateNewView" />
133+
public static CoreApplicationView CreateNewView(XamlWindowConfig windowConfig)
134+
{
135+
var result = XamlWindowActivator.CreateNewInternal(windowConfig);
136+
return result.coreAppView;
137+
}
104138
}
105139
}

Test/Host/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Windows.UI.Core;
1212
using Windows.UI.Core.Preview;
1313
using Windows.UI.Popups;
14+
using Windows.UI.Xaml;
1415

1516
namespace VBAudioRouter.Host
1617
{
@@ -24,6 +25,8 @@ static void Main()
2425
// https://raw.githubusercontent.com/fboldewin/COM-Code-Helper/master/code/interfaces.txt
2526
// GOOGLE: "IApplicationViewCollection" site:lise.pnfsoftware.com
2627

28+
FullTrustApplication.Start((param) => new App());
29+
2730
using (XamlApplicationWrapper appWrapper = new(() => new App()))
2831
{
2932
//XamlWindowActivator.CreateNewThread(() =>

Test/UwpUI/App.xaml.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Windows.UI.Xaml;
1+
using Windows.ApplicationModel.Activation;
2+
using Windows.UI.Xaml;
3+
using Windows.UI.Xaml.Controls;
24

35
namespace UwpUI
46
{
@@ -8,5 +10,12 @@ public App()
810
{
911
this.InitializeComponent();
1012
}
13+
14+
protected override void OnLaunched(LaunchActivatedEventArgs args)
15+
{
16+
Frame frame = new Frame();
17+
Window.Current.Content = frame;
18+
frame.Navigate(typeof(MainPage));
19+
}
1120
}
1221
}

0 commit comments

Comments
 (0)