Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ git clone https://github.com/microsoft/WinUI-Gallery.git

Ensure that the `WinUIGallery` project is set as the startup project in Visual Studio.

Gallery uses an experimental Windows App SDK to demonstrate upcoming features.
Use the normal `Debug` or `Release` configuration; the SDK version is pinned in
`standalone.props`. The runtime is bundled with the app (self-contained deployment)
instead of referencing a shared Windows App SDK framework package. Experimental
APIs can change or be removed before a stable release.

The **Windowing APIs** page combines stable window creation with experimental
window sizing examples. Each experimental example has its own label and warning;
the stable example retains its original APIs.

> [!WARNING]
> Try deleting [`nuget.config`](nuget.config) and building again if you get the following build error:
> > Assets file 'C:\Users\\...\source\repos\WinUI-Gallery\WinUIGallery\obj\WinUIGallery\project.assets.json' not found. Run a NuGet package restore to generate this file.
Expand Down
64 changes: 56 additions & 8 deletions WinUIGallery/Controls/ControlExample.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,19 @@
Duration="0:0:0.1" />
</animations:ImplicitAnimationSet>
</UserControl.Resources>
<Grid x:Name="rootGrid" IsTabStop="False">
<Grid IsTabStop="False">
<Border
Background="{ThemeResource SystemFillColorCautionBackgroundBrush}"
BorderBrush="{ThemeResource SystemFillColorCautionBrush}"
BorderThickness="1"
CornerRadius="8"
IsHitTestVisible="False"
Visibility="{x:Bind IsExperimental}" />

<Grid
x:Name="rootGrid"
Margin="{x:Bind local:ControlExample.BoolToExperimentalMargin(IsExperimental), Mode=OneWay}"
IsTabStop="False">
<Grid.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
Expand All @@ -61,17 +73,40 @@
</Grid.Resources>

<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>

<TextBlock
x:Name="HeaderTextPresenter"
Margin="0,12"
AutomationProperties.HeadingLevel="Level3"
Style="{ThemeResource BodyStrongTextBlockStyle}"
Text="{x:Bind HeaderText, Mode=OneWay}" />
<Grid Margin="0,12" ColumnDefinitions="Auto,*">
<StackPanel
HorizontalAlignment="Left"
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="8"
Visibility="{x:Bind IsExperimental}">
<FontIcon
AutomationProperties.AccessibilityView="Raw"
FontSize="14"
Foreground="{ThemeResource SystemFillColorCautionBrush}"
Glyph="&#xE946;" />
<TextBlock
VerticalAlignment="Center"
Foreground="{ThemeResource SystemFillColorCautionBrush}"
Style="{ThemeResource BodyStrongTextBlockStyle}"
Text="Experimental" />
</StackPanel>

<TextBlock
x:Name="HeaderTextPresenter"
Grid.Column="1"
Margin="{x:Bind local:ControlExample.BoolToHeaderMargin(IsExperimental), Mode=OneWay}"
VerticalAlignment="Center"
AutomationProperties.HeadingLevel="Level3"
Style="{ThemeResource BodyStrongTextBlockStyle}"
Text="{x:Bind HeaderText, Mode=OneWay}" />
</Grid>

<RichTextBlock
x:Name="ErrorTextBlock"
Expand All @@ -85,7 +120,19 @@
</Paragraph>
</RichTextBlock>

<Grid Grid.Row="2" CornerRadius="8" IsTabStop="False">
<Border
Grid.Row="2"
Margin="0,0,0,12"
Padding="12"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
CornerRadius="4"
Visibility="{x:Bind IsExperimental}">
<TextBlock
Text="This example uses an experimental Windows App SDK API that may change before release."
TextWrapping="Wrap" />
</Border>

<Grid Grid.Row="3" CornerRadius="8" IsTabStop="False">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
Expand Down Expand Up @@ -240,5 +287,6 @@
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Grid>
</UserControl>
17 changes: 17 additions & 0 deletions WinUIGallery/Controls/ControlExample.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,23 @@ public Visibility SourceCodeVisibility
set { SetValue(SourceCodeVisibilityProperty, value); }
}

public static readonly DependencyProperty IsExperimentalProperty = DependencyProperty.Register(nameof(IsExperimental), typeof(bool), typeof(ControlExample), new PropertyMetadata(false));
public bool IsExperimental
{
get { return (bool)GetValue(IsExperimentalProperty); }
set { SetValue(IsExperimentalProperty, value); }
}

public static Thickness BoolToExperimentalMargin(bool value)
{
return value ? new Thickness(8) : new Thickness(0);
}

public static Thickness BoolToHeaderMargin(bool value)
{
return value ? new Thickness(12, 0, 0, 0) : new Thickness(0);
}

public ControlExample()
{
this.InitializeComponent();
Expand Down
1 change: 1 addition & 0 deletions WinUIGallery/Helpers/ControlInfoDataSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ private async Task GetControlInfoDataAsync()
{
string badgeString = item switch
{
{ IsExperimental: true } => "Experimental",
{ IsNew: true } => "New",
{ IsUpdated: true } => "Updated",
{ IsPreview: true } => "Preview",
Expand Down
23 changes: 0 additions & 23 deletions WinUIGallery/Helpers/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,12 @@
namespace WinUIGallery.Helpers;
internal partial class NativeMethods
{
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
internal static extern int SetWindowLong32(IntPtr hWnd, WindowLongIndexFlags nIndex, IntPtr newProc);

[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
internal static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, WindowLongIndexFlags nIndex, IntPtr newProc);

[DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLongPtr")]
internal static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

[DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SetWindowLong")]
internal static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);


[DllImport("user32.dll")]
internal static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, WindowMessage Msg, IntPtr wParam, IntPtr lParam);

internal unsafe static void SetWindowKeyHook()
{
delegate* unmanaged[Stdcall]<int, WPARAM, LPARAM, LRESULT> callback = &HookCallback;
Expand Down Expand Up @@ -56,19 +46,6 @@ internal static bool IsKeyDownHook(IntPtr lWord)
return (lWord >> 30 & 1) == 0;
}

internal delegate IntPtr WinProc(IntPtr hWnd, WindowMessage Msg, IntPtr wParam, IntPtr lParam);

[Flags]
internal enum WindowLongIndexFlags : int
{
GWL_WNDPROC = -4,
}

internal enum WindowMessage : int
{
WM_GETMINMAXINFO = 0x0024,
}

internal static bool IsAppPackaged { get; } = GetCurrentPackageName() != null;
internal static string? GetCurrentPackageName()
{
Expand Down
9 changes: 6 additions & 3 deletions WinUIGallery/Helpers/VersionHelper.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.Windows.ApplicationModel.WindowsAppRuntime;
using Microsoft.WindowsAppSDK;

namespace WinUIGallery.Helpers;

internal static partial class VersionHelper
{
// Use SDK-generated version info; self-contained apps don't deploy the framework's Insights resource DLL.
public static string WinAppSdkDetails =>
$"Windows App SDK {ReleaseInfo.Major}.{ReleaseInfo.Minor}";
$"Windows App SDK {Release.Major}.{Release.Minor}" +
(string.IsNullOrEmpty(Release.Channel) ? string.Empty : $" ({Release.Channel})");

public static string WinAppSdkRuntimeDetails =>
WinAppSdkDetails + $", Windows App Runtime {RuntimeInfo.AsString}";
WinAppSdkDetails + $", Windows App Runtime {Microsoft.WindowsAppSDK.Runtime.Version.DotQuadString}";
}
90 changes: 0 additions & 90 deletions WinUIGallery/Helpers/Win32WindowHelper.cs

This file was deleted.

52 changes: 39 additions & 13 deletions WinUIGallery/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media.Animation;
using Microsoft.UI.Xaml.Navigation;
using Microsoft.Windows.Storage;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -54,6 +55,41 @@ public MainWindow()
AdjustNavigationViewMargin(force: true);
AppWindow.Changed += (_, _) => AdjustNavigationViewMargin();
}

InitializeSizePersistence();
}

// Use a rudimenentary persistence mechanism to save the window size between app launches.
// In the future we hope to have persistence APIs directly in WinUI/WinAppSDK.
private void InitializeSizePersistence()
{
ApplicationData appData = NativeMethods.IsAppPackaged
? ApplicationData.GetDefault()
: ApplicationData.GetForUnpackaged(ProcessInfoHelper.Publisher, ProcessInfoHelper.ProductName);

const string containerName = "MainWindow_Settings";
const string valueName = "SavedSize";

if (appData.LocalSettings.Containers.TryGetValue(containerName, out var settingsContainer) &&
settingsContainer.Values.TryGetValue(valueName, out object? value) &&
value is Size savedSize)
{
Width = savedSize.Width;
Height = savedSize.Height;
}

Size lastSize = new Size(Width, Height);

SizeChanged += (s, e) =>
{
lastSize = new Size(Width, Height);
};

Closed += (s, e) =>
{
ApplicationDataContainer appDataContainer = appData.LocalSettings.CreateContainer(containerName, ApplicationDataCreateDisposition.Always);
appDataContainer.Values[valueName] = lastSize;
};
}

// Adjusts the NavigationView margin based on the window state
Expand All @@ -75,14 +111,6 @@ private void AdjustNavigationViewMargin(bool? force = null)

private void RootGrid_Loaded(object sender, RoutedEventArgs e)
{
// We need to set the minimum size here because the XamlRoot is not available in the constructor.
WindowHelper.SetWindowMinSize(this, 640, 500);

if (sender is FrameworkElement rootGrid && rootGrid.XamlRoot is not null)
{
rootGrid.XamlRoot.Changed += RootGridXamlRoot_Changed;
}

NavigationOrientationHelper.UpdateNavigationViewForElement(NavigationOrientationHelper.IsLeftMode());
TitleBarHelper.ApplySystemThemeToCaptionButtons(this, RootGrid.ActualTheme);
}
Expand All @@ -109,11 +137,6 @@ private void RootGrid_PointerPressed(object sender, PointerRoutedEventArgs e)
}
}

private void RootGridXamlRoot_Changed(XamlRoot sender, XamlRootChangedEventArgs args)
{
WindowHelper.SetWindowMinSize(this, 640, 500);
}

private void SetWindowProperties()
{
#if DEBUG || DEBUG_UNPACKAGED
Expand All @@ -126,6 +149,9 @@ private void SetWindowProperties()
this.SetTitleBar(titleBar);
this.AppWindow.SetIcon("Assets/Tiles/GalleryIcon.ico");
this.AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;

MinWidth = 640;
MinHeight = 500;
}

private void OnPaneDisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args)
Expand Down
1 change: 1 addition & 0 deletions WinUIGallery/Models/ControlInfoData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public partial class ControlInfoDataItem
public bool IsNew { get; set; }
public bool IsUpdated { get; set; }
public bool IsPreview { get; set; }
public bool IsExperimental { get; set; }
public ObservableCollection<ControlInfoDocLink> Docs { get; set; } = [];

public bool IncludedInBuild { get; set; }
Expand Down
Loading