diff --git a/Samples/CustomControls/CppApp/App.xaml b/Samples/CustomControls/CppApp/App.xaml new file mode 100644 index 000000000..4ddf47626 --- /dev/null +++ b/Samples/CustomControls/CppApp/App.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CppApp/App.xaml.cpp b/Samples/CustomControls/CppApp/App.xaml.cpp new file mode 100644 index 000000000..869a8fd9e --- /dev/null +++ b/Samples/CustomControls/CppApp/App.xaml.cpp @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" + +#include "App.xaml.h" +#include "MainWindow.xaml.h" + +namespace winrt +{ + using namespace Windows::Foundation; + using namespace Microsoft::UI::Xaml; +} + +namespace winrt::CppApp::implementation +{ + App::App() + { + InitializeComponent(); + +#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION + UnhandledException([](winrt::IInspectable const&, winrt::UnhandledExceptionEventArgs const& e) + { + if (IsDebuggerPresent()) + { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); +#endif + } + + void App::OnLaunched(winrt::LaunchActivatedEventArgs const&) + { + window = winrt::make(); + window.Activate(); + } +} diff --git a/Samples/CustomControls/CppApp/App.xaml.h b/Samples/CustomControls/CppApp/App.xaml.h new file mode 100644 index 000000000..31b689b93 --- /dev/null +++ b/Samples/CustomControls/CppApp/App.xaml.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "App.xaml.g.h" +#include "pch.h" + +namespace winrt::CppApp::implementation +{ + struct App : AppT + { + App(); + + void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&); + + private: + Microsoft::UI::Xaml::Window window{ nullptr }; + }; +} diff --git a/Samples/CustomControls/CppApp/Assets/SplashScreen.png b/Samples/CustomControls/CppApp/Assets/SplashScreen.png new file mode 100644 index 000000000..184821318 Binary files /dev/null and b/Samples/CustomControls/CppApp/Assets/SplashScreen.png differ diff --git a/Samples/CustomControls/CppApp/Assets/Square150x150Logo.png b/Samples/CustomControls/CppApp/Assets/Square150x150Logo.png new file mode 100644 index 000000000..a50c70379 Binary files /dev/null and b/Samples/CustomControls/CppApp/Assets/Square150x150Logo.png differ diff --git a/Samples/CustomControls/CppApp/Assets/Square44x44Logo.png b/Samples/CustomControls/CppApp/Assets/Square44x44Logo.png new file mode 100644 index 000000000..844b60c20 Binary files /dev/null and b/Samples/CustomControls/CppApp/Assets/Square44x44Logo.png differ diff --git a/Samples/CustomControls/CppApp/Assets/Wide310x150Logo.png b/Samples/CustomControls/CppApp/Assets/Wide310x150Logo.png new file mode 100644 index 000000000..b5d5f2c42 Binary files /dev/null and b/Samples/CustomControls/CppApp/Assets/Wide310x150Logo.png differ diff --git a/Samples/CustomControls/CppApp/Assets/logo.png b/Samples/CustomControls/CppApp/Assets/logo.png new file mode 100644 index 000000000..fd2293e7b Binary files /dev/null and b/Samples/CustomControls/CppApp/Assets/logo.png differ diff --git a/Samples/CustomControls/CppApp/Assets/windows-sdk.ico b/Samples/CustomControls/CppApp/Assets/windows-sdk.ico new file mode 100644 index 000000000..3ad20c7c2 Binary files /dev/null and b/Samples/CustomControls/CppApp/Assets/windows-sdk.ico differ diff --git a/Samples/CustomControls/CppApp/CppApp.vcxproj b/Samples/CustomControls/CppApp/CppApp.vcxproj new file mode 100644 index 000000000..55f473f09 --- /dev/null +++ b/Samples/CustomControls/CppApp/CppApp.vcxproj @@ -0,0 +1,226 @@ + + + + + + + + true + true + true + {34a4ad19-a703-47f3-b279-e505c6a2a935} + CppApp + CppApp + + $(RootNamespace) + en-US + 16.0 + false + true + Windows Store + 10.0 + 10.0 + 10.0.17763.0 + true + true + + + + + Debug + Win32 + + + Debug + x64 + + + Debug + arm64 + + + Release + Win32 + + + Release + x64 + + + Release + arm64 + + + + Application + Unicode + true + + + true + true + + + false + true + false + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + + + + MainPage.xaml + Code + + + + App.xaml + + + MainWindow.xaml + + + + Scenario1_CustomControl.xaml + Code + + + Scenario2_UserControl.xaml + Code + + + SettingsPage.xaml + Code + + + + + + Designer + + + + Designer + + + Designer + + + Designer + + + Designer + + + + + MainPage.xaml + Code + + + Create + + + App.xaml + + + MainWindow.xaml + + + + + Scenario1_CustomControl.xaml + Code + + + Scenario2_UserControl.xaml + Code + + + SettingsPage.xaml + Code + + + + + Code + + + + + + + + + + + + + + + + + + + + {bcc816dc-0f01-4f0f-8506-df6afefaea92} + + + + + Designer + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + \ No newline at end of file diff --git a/Samples/CustomControls/CppApp/CppApp.vcxproj.filters b/Samples/CustomControls/CppApp/CppApp.vcxproj.filters new file mode 100644 index 000000000..c37af41cd --- /dev/null +++ b/Samples/CustomControls/CppApp/CppApp.vcxproj.filters @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + {$guid1} + + + + + + + + + + + + \ No newline at end of file diff --git a/Samples/CustomControls/CppApp/MainPage.xaml b/Samples/CustomControls/CppApp/MainPage.xaml new file mode 100644 index 000000000..3c50ce2e0 --- /dev/null +++ b/Samples/CustomControls/CppApp/MainPage.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CppApp/MainPage.xaml.cpp b/Samples/CustomControls/CppApp/MainPage.xaml.cpp new file mode 100644 index 000000000..5831c8651 --- /dev/null +++ b/Samples/CustomControls/CppApp/MainPage.xaml.cpp @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "MainPage.xaml.h" +#if __has_include("MainPage.g.cpp") +#include "MainPage.g.cpp" +#endif + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; + using namespace Microsoft::UI::Xaml::Controls; + using namespace Microsoft::UI::Xaml::Media; + using namespace Microsoft::UI::Xaml::Media::Animation; + using namespace Microsoft::UI::Xaml::Navigation; + using namespace Windows::UI::Xaml::Interop; +} + +namespace winrt::CppApp::implementation +{ + CppApp::MainPage MainPage::current{ nullptr }; + + MainPage::MainPage() + { + InitializeComponent(); + MainPage::current = *this; + } + + void MainPage::NotifyUser(hstring const& strMessage, InfoBarSeverity const& severity) + { + // If called from the UI thread, then update immediately. + // Otherwise, schedule a task on the UI thread to perform the update. + if (this->DispatcherQueue().HasThreadAccess()) + { + UpdateStatus(strMessage, severity); + } + else + { + DispatcherQueue().TryEnqueue([strongThis = get_strong(), this, strMessage, severity] + { UpdateStatus(strMessage, severity); }); + } + } + + void MainPage::UpdateStatus(hstring const& strMessage, InfoBarSeverity severity) + { + infoBar().Message(strMessage); + infoBar().IsOpen(!strMessage.empty()); + infoBar().Severity(severity); + } + + void MainPage::NavView_Loaded(IInspectable const&, RoutedEventArgs const&) + { + for (auto&& s : Scenarios()) + { + FontIcon fontIcon{}; + fontIcon.FontFamily(winrt::FontFamily(L"Segoe MDL2 Assets")); + fontIcon.Glyph(L"\uE82D"); + + NavigationViewItem navViewItem{}; + navViewItem.Content(box_value(s.Title)); + navViewItem.Tag(box_value(s.ClassName)); + navViewItem.Icon(fontIcon); + NavView().MenuItems().Append(navViewItem); + } + + // NavView doesn't load any page by default, so load home page. + NavView().SelectedItem(NavView().MenuItems().GetAt(0)); + + // If navigation occurs on SelectionChanged, this isn't needed. + // Because we use ItemInvoked to navigate, we need to call Navigate + // here to load the home page. + if (Scenarios().Size() > 0) + { + NavView_Navigate(Scenarios().GetAt(0).ClassName, nullptr); + } + } + + + void MainPage::NavView_ItemInvoked(NavigationView const&, NavigationViewItemInvokedEventArgs const& args) + { + if (args.IsSettingsInvoked() == true) + { + hstring xamltypename = winrt::xaml_typename().Name; + NavView_Navigate(xamltypename, args.RecommendedNavigationTransitionInfo()); + } + else if (args.InvokedItemContainer() != nullptr) + { + auto navItemTag = winrt::unbox_value(args.InvokedItemContainer().Tag()); + if (navItemTag != L"") + { + NavView_Navigate(navItemTag, args.RecommendedNavigationTransitionInfo()); + } + } + } + + void MainPage::NavView_Navigate(hstring navItemTag, NavigationTransitionInfo const&) + { + TypeName pageType; + + if (navItemTag == winrt::xaml_typename().Name) + { + pageType = winrt::xaml_typename(); + } + else + { + pageType.Name = navItemTag; + pageType.Kind = TypeKind::Metadata; + } + + // Get the page type before navigation so you can prevent duplicate + // entries in the backstack. + TypeName prePageType = ContentFrame().CurrentSourcePageType(); + + // Only navigate if the selected page isn't currently loaded. + if (prePageType.Name != pageType.Name) + { + DrillInNavigationTransitionInfo drillIn; + ContentFrame().Navigate(pageType, nullptr, drillIn); + } + } + + void MainPage::NavView_BackRequested(NavigationView const&, NavigationViewBackRequestedEventArgs const&) + { + if (ContentFrame().CanGoBack()) + { + ContentFrame().GoBack(); + } + } + + void MainPage::ContentFrame_Navigated(IInspectable const&, NavigationEventArgs const& e) + { + NavView().IsBackEnabled(ContentFrame().CanGoBack()); + + if (ContentFrame().SourcePageType().Name == winrt::xaml_typename().Name) + { + // SettingsItem is not part of NavView.MenuItems, and doesn't have a Tag. + NavView().SelectedItem((NavView().SettingsItem().as())); + NavView().Header(winrt::box_value(L"Settings")); + } + else + { + for (auto&& item : NavView().MenuItems()) + { + auto navViewItem = item.try_as(); + if (navViewItem != nullptr && + winrt::unbox_value(navViewItem.Tag()) == e.SourcePageType().Name) + { + NavView().SelectedItem(navViewItem); + NavView().Header(navViewItem.Content()); + break; + } + } + } + } +} diff --git a/Samples/CustomControls/CppApp/MainPage.xaml.h b/Samples/CustomControls/CppApp/MainPage.xaml.h new file mode 100644 index 000000000..1ae128920 --- /dev/null +++ b/Samples/CustomControls/CppApp/MainPage.xaml.h @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "MainPage.g.h" + +namespace winrt::CppApp::implementation +{ + struct MainPage : MainPageT + { + MainPage(); + static CppApp::MainPage Current() { return current; } + static Windows::Foundation::Collections::IVector Scenarios() { return scenariosInner; } + void NotifyUser(hstring const& strMessage, Microsoft::UI::Xaml::Controls::InfoBarSeverity const& severity); + void UpdateStatus(hstring const& strMessage, Microsoft::UI::Xaml::Controls::InfoBarSeverity severity); + void NavView_Loaded(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e); + void NavView_ItemInvoked(Microsoft::UI::Xaml::Controls::NavigationView const& sender, Microsoft::UI::Xaml::Controls::NavigationViewItemInvokedEventArgs const& args); + void NavView_Navigate(hstring navItemTag, Microsoft::UI::Xaml::Media::Animation::NavigationTransitionInfo const& transitionInfo); + void NavView_BackRequested(Microsoft::UI::Xaml::Controls::NavigationView const& sender, Microsoft::UI::Xaml::Controls::NavigationViewBackRequestedEventArgs const& args); + void ContentFrame_Navigated(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Navigation::NavigationEventArgs const& e); + + private: + static Windows::Foundation::Collections::IVector scenariosInner; + static CppApp::MainPage current; + }; +} + +namespace winrt::CppApp::factory_implementation +{ + struct MainPage : MainPageT + { + }; +} diff --git a/Samples/CustomControls/CppApp/MainWindow.xaml b/Samples/CustomControls/CppApp/MainWindow.xaml new file mode 100644 index 000000000..a1f056aea --- /dev/null +++ b/Samples/CustomControls/CppApp/MainWindow.xaml @@ -0,0 +1,13 @@ + + + + + diff --git a/Samples/CustomControls/CppApp/MainWindow.xaml.cpp b/Samples/CustomControls/CppApp/MainWindow.xaml.cpp new file mode 100644 index 000000000..4b6d72bf9 --- /dev/null +++ b/Samples/CustomControls/CppApp/MainWindow.xaml.cpp @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "MainWindow.xaml.h" +#if __has_include("MainWindow.g.cpp") +#include "MainWindow.g.cpp" + +#include "microsoft.ui.xaml.window.h" +#include "SampleConfiguration.h" +#endif + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; +} + +namespace winrt::CppApp::implementation +{ + MainWindow::MainWindow() + { + InitializeComponent(); + + Title(winrt::CppApp::SampleConfig::FeatureName); + + HWND hwnd = GetWindowHandle(); + LoadIcon(hwnd, L"Assets/windows-sdk.ico"); + SetWindowSize(hwnd, 1050, 800); + PlacementCenterWindowInMonitorWin32(hwnd); + } + + HWND MainWindow::GetWindowHandle() + { + if (_hwnd == nullptr) + { + Window window = *this; + window.as()->get_WindowHandle(&_hwnd); + } + return _hwnd; + } + + void MainWindow::LoadIcon(HWND hwnd, wchar_t const* iconPath) + { + HANDLE hSmallIcon = LoadImageW(nullptr, iconPath, IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + LR_LOADFROMFILE | LR_SHARED); + SendMessageW(hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast(hSmallIcon)); + + HANDLE hBigIcon = LoadImageW(nullptr, iconPath, IMAGE_ICON, + GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), + LR_LOADFROMFILE | LR_SHARED); + SendMessageW(hwnd, WM_SETICON, ICON_BIG, reinterpret_cast(hBigIcon)); + } + + void MainWindow::SetWindowSize(HWND hwnd, int width, int height) + { + // Win32 uses pixels and WinUI 3 uses effective pixels, so you should apply the DPI scale factor + const UINT dpi = GetDpiForWindow(hwnd); + const float scalingFactor = static_cast(dpi) / 96; + const int widthScaled = static_cast(width * scalingFactor); + const int heightScaled = static_cast(height * scalingFactor); + + SetWindowPos(hwnd, nullptr, 0, 0, widthScaled, heightScaled, SWP_NOMOVE | SWP_NOZORDER); + } + + void MainWindow::PlacementCenterWindowInMonitorWin32(HWND hwnd) + { + RECT windowMontiorRectToAdjust; + GetWindowRect(hwnd, &windowMontiorRectToAdjust); + ClipOrCenterRectToMonitorWin32(windowMontiorRectToAdjust); + SetWindowPos(hwnd, nullptr, windowMontiorRectToAdjust.left, + windowMontiorRectToAdjust.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + } + + void MainWindow::ClipOrCenterRectToMonitorWin32(RECT& adjustedWindowRect) + { + MONITORINFO mi{ sizeof(mi) }; + GetMonitorInfoW(MonitorFromRect(&adjustedWindowRect, MONITOR_DEFAULTTONEAREST), &mi); + + const auto& rcWork = mi.rcWork; + const int w = adjustedWindowRect.right - adjustedWindowRect.left; + const int h = adjustedWindowRect.bottom - adjustedWindowRect.top; + + adjustedWindowRect.left = rcWork.left + (rcWork.right - rcWork.left - w) / 2; + adjustedWindowRect.top = rcWork.top + (rcWork.bottom - rcWork.top - h) / 2; + adjustedWindowRect.right = adjustedWindowRect.left + w; + adjustedWindowRect.bottom = adjustedWindowRect.top + h; + } +} diff --git a/Samples/CustomControls/CppApp/MainWindow.xaml.h b/Samples/CustomControls/CppApp/MainWindow.xaml.h new file mode 100644 index 000000000..27c0f2b66 --- /dev/null +++ b/Samples/CustomControls/CppApp/MainWindow.xaml.h @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "MainWindow.g.h" +#include "pch.h" + +namespace winrt::CppApp::implementation +{ + struct MainWindow : MainWindowT + { + MainWindow(); + + private: + HWND _hwnd{ nullptr }; + void SetWindowSize(HWND hwnd, const int width, const int height); + HWND GetWindowHandle(); + void LoadIcon(HWND hwnd, wchar_t const* iconName); + void ClipOrCenterRectToMonitorWin32(RECT& rc); + void PlacementCenterWindowInMonitorWin32(HWND hwnd); + }; +} + +namespace winrt::CppApp::factory_implementation +{ + struct MainWindow : MainWindowT + { + }; +} diff --git a/Samples/CustomControls/CppApp/Package.appxmanifest b/Samples/CustomControls/CppApp/Package.appxmanifest new file mode 100644 index 000000000..8b228300d --- /dev/null +++ b/Samples/CustomControls/CppApp/Package.appxmanifest @@ -0,0 +1,59 @@ + + + + + + + + CppApp + Microsoft Corporation + Assets\logo.png + + + + + + + + + + + + + + + + + + + + + + + + + WinRT.Host.dll + + + + + + + + + + + diff --git a/Samples/CustomControls/CppApp/Project.idl b/Samples/CustomControls/CppApp/Project.idl new file mode 100644 index 000000000..ac4531be7 --- /dev/null +++ b/Samples/CustomControls/CppApp/Project.idl @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace CppApp +{ + /* The following code is scenario/feature-specific IDL. + Samples authors should modify these runtime classes as appropriate. */ + + [default_interface] + runtimeclass Scenario1_CustomControl : Microsoft.UI.Xaml.Controls.Page + { + Scenario1_CustomControl(); + } + + [default_interface] + runtimeclass Scenario2_UserControl : Microsoft.UI.Xaml.Controls.Page + { + Scenario2_UserControl(); + } + + /* The following code is template-specific IDL. + These runtime classes are the same across all C++/WinRT WinUI samples. */ + + runtimeclass MainPage : Microsoft.UI.Xaml.Controls.Page + { + MainPage(); + static MainPage Current(); + void NotifyUser(String strMessage, Microsoft.UI.Xaml.Controls.InfoBarSeverity severity); + } + + // To use Scenario in a winrt::Windows::Foundation::Collections::IVector, Scenario should be a WinRT type + struct Scenario + { + String Title; + String ClassName; + }; + + [default_interface] + runtimeclass MainWindow : Microsoft.UI.Xaml.Window + { + MainWindow(); + } + + [default_interface] + runtimeclass SettingsPage : Microsoft.UI.Xaml.Controls.Page + { + SettingsPage(); + } +} diff --git a/Samples/CustomControls/CppApp/SampleConfiguration.cpp b/Samples/CustomControls/CppApp/SampleConfiguration.cpp new file mode 100644 index 000000000..5923ca31b --- /dev/null +++ b/Samples/CustomControls/CppApp/SampleConfiguration.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "pch.h" +#include "SampleConfiguration.h" +#include "MainPage.xaml.h" + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; + using namespace Windows::Foundation::Collections; +} + +namespace winrt::CppApp +{ + IVector implementation::MainPage::scenariosInner = single_threaded_observable_vector( + { + Scenario{ L"Custom Control", hstring(name_of())}, + Scenario{ L"User Control", hstring(name_of())} + }); + + hstring SampleConfig::FeatureName{ L"CppApp" }; + ElementTheme SampleConfig::CurrentTheme{ ElementTheme::Default }; +} diff --git a/Samples/CustomControls/CppApp/SampleConfiguration.h b/Samples/CustomControls/CppApp/SampleConfiguration.h new file mode 100644 index 000000000..26cb27c95 --- /dev/null +++ b/Samples/CustomControls/CppApp/SampleConfiguration.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "pch.h" + +namespace winrt::CppApp +{ + struct SampleConfig + { + public: + static hstring FeatureName; + static Microsoft::UI::Xaml::ElementTheme CurrentTheme; + }; +} diff --git a/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml b/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml new file mode 100644 index 000000000..74e05e00c --- /dev/null +++ b/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + Reference a Custom WinUI Button type from a C# component. + + + + + + + + + diff --git a/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml.cpp b/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml.cpp new file mode 100644 index 000000000..f347b0b31 --- /dev/null +++ b/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml.cpp @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "Scenario1_CustomControl.xaml.h" +#if __has_include("Scenario1_CustomControl.g.cpp") +#include "Scenario1_CustomControl.g.cpp" +#endif + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; + using namespace Microsoft::UI::Xaml::Controls; + using namespace Windows::Foundation; +} + +namespace winrt::CppApp::implementation +{ + MainPage Scenario1_CustomControl::rootPage{ nullptr }; + + Scenario1_CustomControl::Scenario1_CustomControl() + { + InitializeComponent(); + Scenario1_CustomControl::rootPage = MainPage::Current(); + } +} diff --git a/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml.h b/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml.h new file mode 100644 index 000000000..f71045304 --- /dev/null +++ b/Samples/CustomControls/CppApp/Scenario1_CustomControl.xaml.h @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "Scenario1_CustomControl.g.h" + +namespace winrt::CppApp::implementation +{ + struct Scenario1_CustomControl : Scenario1_CustomControlT + { + Scenario1_CustomControl(); + //void SuccessMessage_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&); + //void ErrorMessage_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&); + //void InformationalMessage_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&); + //void ClearMessage_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Microsoft::UI::Xaml::RoutedEventArgs const&); + private: + static CppApp::MainPage rootPage; + }; +} + +namespace winrt::CppApp::factory_implementation +{ + struct Scenario1_CustomControl : Scenario1_CustomControlT + { + }; +} diff --git a/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml b/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml new file mode 100644 index 000000000..d066b8b61 --- /dev/null +++ b/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + Reference a Custom User Control from a C# Component. + + + + + + + + + + diff --git a/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml.cpp b/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml.cpp new file mode 100644 index 000000000..f6437ed72 --- /dev/null +++ b/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml.cpp @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "Scenario2_UserControl.xaml.h" +#if __has_include("Scenario2_UserControl.g.cpp") +#include "Scenario2_UserControl.g.cpp" +#endif + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; +} + +namespace winrt::CppApp::implementation +{ + Scenario2_UserControl::Scenario2_UserControl() + { + InitializeComponent(); + } +} diff --git a/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml.h b/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml.h new file mode 100644 index 000000000..689313632 --- /dev/null +++ b/Samples/CustomControls/CppApp/Scenario2_UserControl.xaml.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "Scenario2_UserControl.g.h" + +namespace winrt::CppApp::implementation +{ + struct Scenario2_UserControl : Scenario2_UserControlT + { + Scenario2_UserControl(); + }; +} + +namespace winrt::CppApp::factory_implementation +{ + struct Scenario2_UserControl : Scenario2_UserControlT + { + }; +} diff --git a/Samples/CustomControls/CppApp/SettingsPage.xaml b/Samples/CustomControls/CppApp/SettingsPage.xaml new file mode 100644 index 000000000..5a4e12dc0 --- /dev/null +++ b/Samples/CustomControls/CppApp/SettingsPage.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + Light + + + + + Dark + + + + + Default + + + + + + + + + + + diff --git a/Samples/CustomControls/CppApp/SettingsPage.xaml.cpp b/Samples/CustomControls/CppApp/SettingsPage.xaml.cpp new file mode 100644 index 000000000..b889cc401 --- /dev/null +++ b/Samples/CustomControls/CppApp/SettingsPage.xaml.cpp @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "SettingsPage.xaml.h" +#if __has_include("SettingsPage.g.cpp") +#include "SettingsPage.g.cpp" +#endif +#include + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; + using namespace Microsoft::UI::Xaml::Controls; + using namespace Microsoft::UI::Xaml::Navigation; + using namespace Windows::Foundation; +} + +namespace winrt::CppApp::implementation +{ + SettingsPage::SettingsPage() + { + InitializeComponent(); + } + + void SettingsPage::OnNavigatedTo(NavigationEventArgs const&) + { + for (UIElement&& c : themePanel().Children()) + { + auto tag = c.as().Tag().as(); + if (tag == SampleConfig::CurrentTheme) + { + auto radioButton = c.as(); + radioButton.IsChecked(true); + } + } + } + + void SettingsPage::OnThemeRadioButtonChecked(IInspectable const& sender, RoutedEventArgs const&) + { + auto radiobutton = sender.as(); + auto selectedTheme = unbox_value(radiobutton.Tag()); + + auto content = MainPage::Current().Content().as(); + if (content != nullptr) + { + content.RequestedTheme(selectedTheme); + SampleConfig::CurrentTheme = content.RequestedTheme(); + } + } +} diff --git a/Samples/CustomControls/CppApp/SettingsPage.xaml.h b/Samples/CustomControls/CppApp/SettingsPage.xaml.h new file mode 100644 index 000000000..0fd19146c --- /dev/null +++ b/Samples/CustomControls/CppApp/SettingsPage.xaml.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "SettingsPage.g.h" + +namespace winrt::CppApp::implementation +{ + struct SettingsPage : SettingsPageT + { + SettingsPage(); + void OnNavigatedTo(Microsoft::UI::Xaml::Navigation::NavigationEventArgs const& e); + void OnThemeRadioButtonChecked(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e); + }; +} + +namespace winrt::CppApp::factory_implementation +{ + struct SettingsPage : SettingsPageT + { + }; +} diff --git a/Samples/CustomControls/CppApp/Styles.xaml b/Samples/CustomControls/CppApp/Styles.xaml new file mode 100644 index 000000000..748aef03d --- /dev/null +++ b/Samples/CustomControls/CppApp/Styles.xaml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CppApp/app.manifest b/Samples/CustomControls/CppApp/app.manifest new file mode 100644 index 000000000..6f36cae81 --- /dev/null +++ b/Samples/CustomControls/CppApp/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/Samples/CustomControls/CppApp/packages.config b/Samples/CustomControls/CppApp/packages.config new file mode 100644 index 000000000..bc372d9a9 --- /dev/null +++ b/Samples/CustomControls/CppApp/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Samples/CustomControls/CppApp/pch.cpp b/Samples/CustomControls/CppApp/pch.cpp new file mode 100644 index 000000000..40e691ba7 --- /dev/null +++ b/Samples/CustomControls/CppApp/pch.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" diff --git a/Samples/CustomControls/CppApp/pch.h b/Samples/CustomControls/CppApp/pch.h new file mode 100644 index 000000000..697356a9f --- /dev/null +++ b/Samples/CustomControls/CppApp/pch.h @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include +#include +#include +#include + +// Undefine GetCurrentTime macro to prevent +// conflict with Storyboard::GetCurrentTime +#undef GetCurrentTime + +#include +#include +#include +#include //For using xaml_typename + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/Samples/CustomControls/CppAppUnpackaged/App.xaml b/Samples/CustomControls/CppAppUnpackaged/App.xaml new file mode 100644 index 000000000..62ea30142 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/App.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CppAppUnpackaged/App.xaml.cpp b/Samples/CustomControls/CppAppUnpackaged/App.xaml.cpp new file mode 100644 index 000000000..37cff0524 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/App.xaml.cpp @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" + +#include "App.xaml.h" +#include "MainWindow.xaml.h" + +namespace winrt +{ + using namespace Windows::Foundation; + using namespace Microsoft::UI::Xaml; +} + +namespace winrt::CppAppUnpackaged::implementation +{ + App::App() + { + InitializeComponent(); + +#if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION + UnhandledException([](winrt::IInspectable const&, winrt::UnhandledExceptionEventArgs const& e) + { + if (IsDebuggerPresent()) + { + auto errorMessage = e.Message(); + __debugbreak(); + } + }); +#endif + } + + void App::OnLaunched(winrt::LaunchActivatedEventArgs const&) + { + window = winrt::make(); + window.Activate(); + } +} diff --git a/Samples/CustomControls/CppAppUnpackaged/App.xaml.h b/Samples/CustomControls/CppAppUnpackaged/App.xaml.h new file mode 100644 index 000000000..804665645 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/App.xaml.h @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "App.xaml.g.h" +#include "pch.h" + +namespace winrt::CppAppUnpackaged::implementation +{ + struct App : AppT + { + App(); + + void OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&); + + private: + Microsoft::UI::Xaml::Window window{ nullptr }; + }; +} diff --git a/Samples/CustomControls/CppAppUnpackaged/Assets/SplashScreen.png b/Samples/CustomControls/CppAppUnpackaged/Assets/SplashScreen.png new file mode 100644 index 000000000..184821318 Binary files /dev/null and b/Samples/CustomControls/CppAppUnpackaged/Assets/SplashScreen.png differ diff --git a/Samples/CustomControls/CppAppUnpackaged/Assets/Square150x150Logo.png b/Samples/CustomControls/CppAppUnpackaged/Assets/Square150x150Logo.png new file mode 100644 index 000000000..a50c70379 Binary files /dev/null and b/Samples/CustomControls/CppAppUnpackaged/Assets/Square150x150Logo.png differ diff --git a/Samples/CustomControls/CppAppUnpackaged/Assets/Square44x44Logo.png b/Samples/CustomControls/CppAppUnpackaged/Assets/Square44x44Logo.png new file mode 100644 index 000000000..844b60c20 Binary files /dev/null and b/Samples/CustomControls/CppAppUnpackaged/Assets/Square44x44Logo.png differ diff --git a/Samples/CustomControls/CppAppUnpackaged/Assets/Wide310x150Logo.png b/Samples/CustomControls/CppAppUnpackaged/Assets/Wide310x150Logo.png new file mode 100644 index 000000000..b5d5f2c42 Binary files /dev/null and b/Samples/CustomControls/CppAppUnpackaged/Assets/Wide310x150Logo.png differ diff --git a/Samples/CustomControls/CppAppUnpackaged/Assets/logo.png b/Samples/CustomControls/CppAppUnpackaged/Assets/logo.png new file mode 100644 index 000000000..fd2293e7b Binary files /dev/null and b/Samples/CustomControls/CppAppUnpackaged/Assets/logo.png differ diff --git a/Samples/CustomControls/CppAppUnpackaged/Assets/windows-sdk.ico b/Samples/CustomControls/CppAppUnpackaged/Assets/windows-sdk.ico new file mode 100644 index 000000000..3ad20c7c2 Binary files /dev/null and b/Samples/CustomControls/CppAppUnpackaged/Assets/windows-sdk.ico differ diff --git a/Samples/CustomControls/CppAppUnpackaged/CppAppUnpackaged.vcxproj b/Samples/CustomControls/CppAppUnpackaged/CppAppUnpackaged.vcxproj new file mode 100644 index 000000000..447bf23e8 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/CppAppUnpackaged.vcxproj @@ -0,0 +1,224 @@ + + + + + + + + true + true + true + {b71d15ef-f17b-4e8f-b023-08c4e3b32dab} + CppAppUnpackaged + CppAppUnpackaged + + $(RootNamespace) + en-US + 16.0 + false + false + Windows Store + 10.0 + 10.0 + 10.0.17763.0 + true + true + None + + + + + Debug + Win32 + + + Debug + x64 + + + Debug + arm64 + + + Release + Win32 + + + Release + x64 + + + Release + arm64 + + + + Application + v143 + Unicode + true + + + true + true + + + false + true + false + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + + + + MainPage.xaml + Code + + + + App.xaml + + + MainWindow.xaml + + + + Scenario1_CustomControl.xaml + Code + + + Scenario2_UserControl.xaml + Code + + + SettingsPage.xaml + Code + + + + + + Designer + + + + Designer + + + Designer + + + Designer + + + Designer + + + + + MainPage.xaml + Code + + + Create + + + App.xaml + + + MainWindow.xaml + + + + + Scenario1_CustomControl.xaml + Code + + + Scenario2_UserControl.xaml + Code + + + SettingsPage.xaml + Code + + + + + Code + + + + + + + + + + + + + + + + + {bcc816dc-0f01-4f0f-8506-df6afefaea92} + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + \ No newline at end of file diff --git a/Samples/CustomControls/CppAppUnpackaged/CppAppUnpackaged.vcxproj.filters b/Samples/CustomControls/CppAppUnpackaged/CppAppUnpackaged.vcxproj.filters new file mode 100644 index 000000000..213754c34 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/CppAppUnpackaged.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + {$guid1} + + + + + + + + + \ No newline at end of file diff --git a/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml b/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml new file mode 100644 index 000000000..162fae80c --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml.cpp b/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml.cpp new file mode 100644 index 000000000..e32fc129a --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml.cpp @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "MainPage.xaml.h" +#if __has_include("MainPage.g.cpp") +#include "MainPage.g.cpp" +#endif + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; + using namespace Microsoft::UI::Xaml::Controls; + using namespace Microsoft::UI::Xaml::Media; + using namespace Microsoft::UI::Xaml::Media::Animation; + using namespace Microsoft::UI::Xaml::Navigation; + using namespace Windows::UI::Xaml::Interop; +} + +namespace winrt::CppAppUnpackaged::implementation +{ + CppAppUnpackaged::MainPage MainPage::current{ nullptr }; + + MainPage::MainPage() + { + InitializeComponent(); + MainPage::current = *this; + } + + void MainPage::NotifyUser(hstring const& strMessage, InfoBarSeverity const& severity) + { + // If called from the UI thread, then update immediately. + // Otherwise, schedule a task on the UI thread to perform the update. + if (this->DispatcherQueue().HasThreadAccess()) + { + UpdateStatus(strMessage, severity); + } + else + { + DispatcherQueue().TryEnqueue([strongThis = get_strong(), this, strMessage, severity] + { UpdateStatus(strMessage, severity); }); + } + } + + void MainPage::UpdateStatus(hstring const& strMessage, InfoBarSeverity severity) + { + infoBar().Message(strMessage); + infoBar().IsOpen(!strMessage.empty()); + infoBar().Severity(severity); + } + + void MainPage::NavView_Loaded(IInspectable const&, RoutedEventArgs const&) + { + for (auto&& s : Scenarios()) + { + FontIcon fontIcon{}; + fontIcon.FontFamily(winrt::FontFamily(L"Segoe MDL2 Assets")); + fontIcon.Glyph(L"\uE82D"); + + NavigationViewItem navViewItem{}; + navViewItem.Content(box_value(s.Title)); + navViewItem.Tag(box_value(s.ClassName)); + navViewItem.Icon(fontIcon); + NavView().MenuItems().Append(navViewItem); + } + + // NavView doesn't load any page by default, so load home page. + NavView().SelectedItem(NavView().MenuItems().GetAt(0)); + + // If navigation occurs on SelectionChanged, this isn't needed. + // Because we use ItemInvoked to navigate, we need to call Navigate + // here to load the home page. + if (Scenarios().Size() > 0) + { + NavView_Navigate(Scenarios().GetAt(0).ClassName, nullptr); + } + } + + + void MainPage::NavView_ItemInvoked(NavigationView const&, NavigationViewItemInvokedEventArgs const& args) + { + if (args.IsSettingsInvoked() == true) + { + hstring xamltypename = winrt::xaml_typename().Name; + NavView_Navigate(xamltypename, args.RecommendedNavigationTransitionInfo()); + } + else if (args.InvokedItemContainer() != nullptr) + { + auto navItemTag = winrt::unbox_value(args.InvokedItemContainer().Tag()); + if (navItemTag != L"") + { + NavView_Navigate(navItemTag, args.RecommendedNavigationTransitionInfo()); + } + } + } + + void MainPage::NavView_Navigate(hstring navItemTag, NavigationTransitionInfo const&) + { + TypeName pageType; + + if (navItemTag == winrt::xaml_typename().Name) + { + pageType = winrt::xaml_typename(); + } + else + { + pageType.Name = navItemTag; + pageType.Kind = TypeKind::Metadata; + } + + // Get the page type before navigation so you can prevent duplicate + // entries in the backstack. + TypeName prePageType = ContentFrame().CurrentSourcePageType(); + + // Only navigate if the selected page isn't currently loaded. + if (prePageType.Name != pageType.Name) + { + DrillInNavigationTransitionInfo drillIn; + ContentFrame().Navigate(pageType, nullptr, drillIn); + } + } + + void MainPage::NavView_BackRequested(NavigationView const&, NavigationViewBackRequestedEventArgs const&) + { + if (ContentFrame().CanGoBack()) + { + ContentFrame().GoBack(); + } + } + + void MainPage::ContentFrame_Navigated(IInspectable const&, NavigationEventArgs const& e) + { + NavView().IsBackEnabled(ContentFrame().CanGoBack()); + + if (ContentFrame().SourcePageType().Name == winrt::xaml_typename().Name) + { + // SettingsItem is not part of NavView.MenuItems, and doesn't have a Tag. + NavView().SelectedItem((NavView().SettingsItem().as())); + NavView().Header(winrt::box_value(L"Settings")); + } + else + { + for (auto&& item : NavView().MenuItems()) + { + auto navViewItem = item.try_as(); + if (navViewItem != nullptr && + winrt::unbox_value(navViewItem.Tag()) == e.SourcePageType().Name) + { + NavView().SelectedItem(navViewItem); + NavView().Header(navViewItem.Content()); + break; + } + } + } + } +} diff --git a/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml.h b/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml.h new file mode 100644 index 000000000..1fcec1038 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/MainPage.xaml.h @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "MainPage.g.h" + +namespace winrt::CppAppUnpackaged::implementation +{ + struct MainPage : MainPageT + { + MainPage(); + static CppAppUnpackaged::MainPage Current() { return current; } + static Windows::Foundation::Collections::IVector Scenarios() { return scenariosInner; } + void NotifyUser(hstring const& strMessage, Microsoft::UI::Xaml::Controls::InfoBarSeverity const& severity); + void UpdateStatus(hstring const& strMessage, Microsoft::UI::Xaml::Controls::InfoBarSeverity severity); + void NavView_Loaded(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& e); + void NavView_ItemInvoked(Microsoft::UI::Xaml::Controls::NavigationView const& sender, Microsoft::UI::Xaml::Controls::NavigationViewItemInvokedEventArgs const& args); + void NavView_Navigate(hstring navItemTag, Microsoft::UI::Xaml::Media::Animation::NavigationTransitionInfo const& transitionInfo); + void NavView_BackRequested(Microsoft::UI::Xaml::Controls::NavigationView const& sender, Microsoft::UI::Xaml::Controls::NavigationViewBackRequestedEventArgs const& args); + void ContentFrame_Navigated(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::Navigation::NavigationEventArgs const& e); + + private: + static Windows::Foundation::Collections::IVector scenariosInner; + static CppAppUnpackaged::MainPage current; + }; +} + +namespace winrt::CppAppUnpackaged::factory_implementation +{ + struct MainPage : MainPageT + { + }; +} diff --git a/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml b/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml new file mode 100644 index 000000000..beaa656a9 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml @@ -0,0 +1,13 @@ + + + + + diff --git a/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml.cpp b/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml.cpp new file mode 100644 index 000000000..64dc05ebb --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml.cpp @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "MainWindow.xaml.h" +#if __has_include("MainWindow.g.cpp") +#include "MainWindow.g.cpp" + +#include "microsoft.ui.xaml.window.h" +#include "SampleConfiguration.h" +#endif + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; +} + +namespace winrt::CppAppUnpackaged::implementation +{ + MainWindow::MainWindow() + { + InitializeComponent(); + + Title(winrt::CppAppUnpackaged::SampleConfig::FeatureName); + + HWND hwnd = GetWindowHandle(); + LoadIcon(hwnd, L"Assets/windows-sdk.ico"); + SetWindowSize(hwnd, 1050, 800); + PlacementCenterWindowInMonitorWin32(hwnd); + } + + HWND MainWindow::GetWindowHandle() + { + if (_hwnd == nullptr) + { + Window window = *this; + window.as()->get_WindowHandle(&_hwnd); + } + return _hwnd; + } + + void MainWindow::LoadIcon(HWND hwnd, wchar_t const* iconPath) + { + HANDLE hSmallIcon = LoadImageW(nullptr, iconPath, IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), + LR_LOADFROMFILE | LR_SHARED); + SendMessageW(hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast(hSmallIcon)); + + HANDLE hBigIcon = LoadImageW(nullptr, iconPath, IMAGE_ICON, + GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), + LR_LOADFROMFILE | LR_SHARED); + SendMessageW(hwnd, WM_SETICON, ICON_BIG, reinterpret_cast(hBigIcon)); + } + + void MainWindow::SetWindowSize(HWND hwnd, int width, int height) + { + // Win32 uses pixels and WinUI 3 uses effective pixels, so you should apply the DPI scale factor + const UINT dpi = GetDpiForWindow(hwnd); + const float scalingFactor = static_cast(dpi) / 96; + const int widthScaled = static_cast(width * scalingFactor); + const int heightScaled = static_cast(height * scalingFactor); + + SetWindowPos(hwnd, nullptr, 0, 0, widthScaled, heightScaled, SWP_NOMOVE | SWP_NOZORDER); + } + + void MainWindow::PlacementCenterWindowInMonitorWin32(HWND hwnd) + { + RECT windowMontiorRectToAdjust; + GetWindowRect(hwnd, &windowMontiorRectToAdjust); + ClipOrCenterRectToMonitorWin32(windowMontiorRectToAdjust); + SetWindowPos(hwnd, nullptr, windowMontiorRectToAdjust.left, + windowMontiorRectToAdjust.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + } + + void MainWindow::ClipOrCenterRectToMonitorWin32(RECT& adjustedWindowRect) + { + MONITORINFO mi{ sizeof(mi) }; + GetMonitorInfoW(MonitorFromRect(&adjustedWindowRect, MONITOR_DEFAULTTONEAREST), &mi); + + const auto& rcWork = mi.rcWork; + const int w = adjustedWindowRect.right - adjustedWindowRect.left; + const int h = adjustedWindowRect.bottom - adjustedWindowRect.top; + + adjustedWindowRect.left = rcWork.left + (rcWork.right - rcWork.left - w) / 2; + adjustedWindowRect.top = rcWork.top + (rcWork.bottom - rcWork.top - h) / 2; + adjustedWindowRect.right = adjustedWindowRect.left + w; + adjustedWindowRect.bottom = adjustedWindowRect.top + h; + } +} diff --git a/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml.h b/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml.h new file mode 100644 index 000000000..119debdb0 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/MainWindow.xaml.h @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "MainWindow.g.h" +#include "pch.h" + +namespace winrt::CppAppUnpackaged::implementation +{ + struct MainWindow : MainWindowT + { + MainWindow(); + + private: + HWND _hwnd{ nullptr }; + void SetWindowSize(HWND hwnd, const int width, const int height); + HWND GetWindowHandle(); + void LoadIcon(HWND hwnd, wchar_t const* iconName); + void ClipOrCenterRectToMonitorWin32(RECT& rc); + void PlacementCenterWindowInMonitorWin32(HWND hwnd); + }; +} + +namespace winrt::CppAppUnpackaged::factory_implementation +{ + struct MainWindow : MainWindowT + { + }; +} diff --git a/Samples/CustomControls/CppAppUnpackaged/Project.idl b/Samples/CustomControls/CppAppUnpackaged/Project.idl new file mode 100644 index 000000000..c0b042982 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/Project.idl @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace CppAppUnpackaged +{ + /* The following code is scenario/feature-specific IDL. + Samples authors should modify these runtime classes as appropriate. */ + + [default_interface] + runtimeclass Scenario1_CustomControl : Microsoft.UI.Xaml.Controls.Page + { + Scenario1_CustomControl(); + } + + [default_interface] + runtimeclass Scenario2_UserControl : Microsoft.UI.Xaml.Controls.Page + { + Scenario2_UserControl(); + } + + /* The following code is template-specific IDL. + These runtime classes are the same across all C++/WinRT WinUI samples. */ + + runtimeclass MainPage : Microsoft.UI.Xaml.Controls.Page + { + MainPage(); + static MainPage Current(); + void NotifyUser(String strMessage, Microsoft.UI.Xaml.Controls.InfoBarSeverity severity); + } + + // To use Scenario in a winrt::Windows::Foundation::Collections::IVector, Scenario should be a WinRT type + struct Scenario + { + String Title; + String ClassName; + }; + + [default_interface] + runtimeclass MainWindow : Microsoft.UI.Xaml.Window + { + MainWindow(); + } + + [default_interface] + runtimeclass SettingsPage : Microsoft.UI.Xaml.Controls.Page + { + SettingsPage(); + } +} diff --git a/Samples/CustomControls/CppAppUnpackaged/SampleConfiguration.cpp b/Samples/CustomControls/CppAppUnpackaged/SampleConfiguration.cpp new file mode 100644 index 000000000..a4ddefd1f --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/SampleConfiguration.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "pch.h" +#include "SampleConfiguration.h" +#include "MainPage.xaml.h" + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; + using namespace Windows::Foundation::Collections; +} + +namespace winrt::CppAppUnpackaged +{ + IVector implementation::MainPage::scenariosInner = single_threaded_observable_vector( + { + Scenario{ L"Scenario 1", hstring(name_of())}, + Scenario{ L"Scenario 2", hstring(name_of())} + }); + + hstring SampleConfig::FeatureName{ L"CppAppUnpackaged" }; + ElementTheme SampleConfig::CurrentTheme{ ElementTheme::Default }; +} diff --git a/Samples/CustomControls/CppAppUnpackaged/SampleConfiguration.h b/Samples/CustomControls/CppAppUnpackaged/SampleConfiguration.h new file mode 100644 index 000000000..f2c662d34 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/SampleConfiguration.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include "pch.h" + +namespace winrt::CppAppUnpackaged +{ + struct SampleConfig + { + public: + static hstring FeatureName; + static Microsoft::UI::Xaml::ElementTheme CurrentTheme; + }; +} diff --git a/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml b/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml new file mode 100644 index 000000000..7c97b10c0 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + Reference a Custom WinUI Button type from a C# component. + + + + + + + + diff --git a/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml.cpp b/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml.cpp new file mode 100644 index 000000000..b18dd876f --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml.cpp @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "Scenario1_CustomControl.xaml.h" +#if __has_include("Scenario1_CustomControl.g.cpp") +#include "Scenario1_CustomControl.g.cpp" +#endif + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; + using namespace Microsoft::UI::Xaml::Controls; + using namespace Windows::Foundation; +} + +namespace winrt::CppAppUnpackaged::implementation +{ + MainPage Scenario1_CustomControl::rootPage{ nullptr }; + + Scenario1_CustomControl::Scenario1_CustomControl() + { + InitializeComponent(); + Scenario1_CustomControl::rootPage = MainPage::Current(); + } +} diff --git a/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml.h b/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml.h new file mode 100644 index 000000000..b49ced08a --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/Scenario1_CustomControl.xaml.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "Scenario1_CustomControl.g.h" + +namespace winrt::CppAppUnpackaged::implementation +{ + struct Scenario1_CustomControl : Scenario1_CustomControlT + { + Scenario1_CustomControl(); + private: + static CppAppUnpackaged::MainPage rootPage; + }; +} + +namespace winrt::CppAppUnpackaged::factory_implementation +{ + struct Scenario1_CustomControl : Scenario1_CustomControlT + { + }; +} diff --git a/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml b/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml new file mode 100644 index 000000000..f167a8988 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + Reference a Custom User Control from a C# Component. + + + + + + + + + + diff --git a/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml.cpp b/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml.cpp new file mode 100644 index 000000000..b36d7bd6b --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml.cpp @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "Scenario2_UserControl.xaml.h" +#if __has_include("Scenario2_UserControl.g.cpp") +#include "Scenario2_UserControl.g.cpp" +#endif + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; +} + +namespace winrt::CppAppUnpackaged::implementation +{ + Scenario2_UserControl::Scenario2_UserControl() + { + InitializeComponent(); + } +} diff --git a/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml.h b/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml.h new file mode 100644 index 000000000..34f644fb8 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/Scenario2_UserControl.xaml.h @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "Scenario2_UserControl.g.h" + +namespace winrt::CppAppUnpackaged::implementation +{ + struct Scenario2_UserControl : Scenario2_UserControlT + { + Scenario2_UserControl(); + }; +} + +namespace winrt::CppAppUnpackaged::factory_implementation +{ + struct Scenario2_UserControl : Scenario2_UserControlT + { + }; +} diff --git a/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml b/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml new file mode 100644 index 000000000..b508656a1 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + Light + + + + + Dark + + + + + Default + + + + + + + + + + + diff --git a/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml.cpp b/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml.cpp new file mode 100644 index 000000000..2b476a140 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml.cpp @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" +#include "SettingsPage.xaml.h" +#if __has_include("SettingsPage.g.cpp") +#include "SettingsPage.g.cpp" +#endif +#include + +namespace winrt +{ + using namespace Microsoft::UI::Xaml; + using namespace Microsoft::UI::Xaml::Controls; + using namespace Microsoft::UI::Xaml::Navigation; + using namespace Windows::Foundation; +} + +namespace winrt::CppAppUnpackaged::implementation +{ + SettingsPage::SettingsPage() + { + InitializeComponent(); + } + + void SettingsPage::OnNavigatedTo(NavigationEventArgs const&) + { + for (UIElement&& c : themePanel().Children()) + { + auto tag = c.as().Tag().as(); + if (tag == SampleConfig::CurrentTheme) + { + auto radioButton = c.as(); + radioButton.IsChecked(true); + } + } + } + + void SettingsPage::OnThemeRadioButtonChecked(IInspectable const& sender, RoutedEventArgs const&) + { + auto radiobutton = sender.as(); + auto selectedTheme = unbox_value(radiobutton.Tag()); + + auto content = MainPage::Current().Content().as(); + if (content != nullptr) + { + content.RequestedTheme(selectedTheme); + SampleConfig::CurrentTheme = content.RequestedTheme(); + } + } +} diff --git a/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml.h b/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml.h new file mode 100644 index 000000000..356d79efd --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/SettingsPage.xaml.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once + +#include "SettingsPage.g.h" + +namespace winrt::CppAppUnpackaged::implementation +{ + struct SettingsPage : SettingsPageT + { + SettingsPage(); + void OnNavigatedTo(Microsoft::UI::Xaml::Navigation::NavigationEventArgs const& e); + void OnThemeRadioButtonChecked(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e); + }; +} + +namespace winrt::CppAppUnpackaged::factory_implementation +{ + struct SettingsPage : SettingsPageT + { + }; +} diff --git a/Samples/CustomControls/CppAppUnpackaged/Styles.xaml b/Samples/CustomControls/CppAppUnpackaged/Styles.xaml new file mode 100644 index 000000000..a16ffe768 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/Styles.xaml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CppAppUnpackaged/app.manifest b/Samples/CustomControls/CppAppUnpackaged/app.manifest new file mode 100644 index 000000000..2691059c1 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/app.manifest @@ -0,0 +1,31 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + + + + + + + + diff --git a/Samples/CustomControls/CppAppUnpackaged/packages.config b/Samples/CustomControls/CppAppUnpackaged/packages.config new file mode 100644 index 000000000..83878b848 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Samples/CustomControls/CppAppUnpackaged/pch.cpp b/Samples/CustomControls/CppAppUnpackaged/pch.cpp new file mode 100644 index 000000000..40e691ba7 --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/pch.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "pch.h" diff --git a/Samples/CustomControls/CppAppUnpackaged/pch.h b/Samples/CustomControls/CppAppUnpackaged/pch.h new file mode 100644 index 000000000..697356a9f --- /dev/null +++ b/Samples/CustomControls/CppAppUnpackaged/pch.h @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#pragma once +#include +#include +#include +#include + +// Undefine GetCurrentTime macro to prevent +// conflict with Storyboard::GetCurrentTime +#undef GetCurrentTime + +#include +#include +#include +#include //For using xaml_typename + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/Samples/CustomControls/CsApp/App.xaml b/Samples/CustomControls/CsApp/App.xaml new file mode 100644 index 000000000..cf0977d69 --- /dev/null +++ b/Samples/CustomControls/CsApp/App.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CsApp/App.xaml.cs b/Samples/CustomControls/CsApp/App.xaml.cs new file mode 100644 index 000000000..178198118 --- /dev/null +++ b/Samples/CustomControls/CsApp/App.xaml.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.UI.Xaml; + +namespace CsApp +{ + public partial class App : Application + { + private Window mainWindow; + + public App() + { + this.InitializeComponent(); + } + + protected override void OnLaunched(LaunchActivatedEventArgs args) + { + mainWindow = new MainWindow(); + mainWindow.Activate(); + } + } +} diff --git a/Samples/CustomControls/CsApp/Assets/SplashScreen.png b/Samples/CustomControls/CsApp/Assets/SplashScreen.png new file mode 100644 index 000000000..184821318 Binary files /dev/null and b/Samples/CustomControls/CsApp/Assets/SplashScreen.png differ diff --git a/Samples/CustomControls/CsApp/Assets/Square150x150Logo.png b/Samples/CustomControls/CsApp/Assets/Square150x150Logo.png new file mode 100644 index 000000000..a50c70379 Binary files /dev/null and b/Samples/CustomControls/CsApp/Assets/Square150x150Logo.png differ diff --git a/Samples/CustomControls/CsApp/Assets/Square44x44Logo.png b/Samples/CustomControls/CsApp/Assets/Square44x44Logo.png new file mode 100644 index 000000000..844b60c20 Binary files /dev/null and b/Samples/CustomControls/CsApp/Assets/Square44x44Logo.png differ diff --git a/Samples/CustomControls/CsApp/Assets/Wide310x150Logo.png b/Samples/CustomControls/CsApp/Assets/Wide310x150Logo.png new file mode 100644 index 000000000..b5d5f2c42 Binary files /dev/null and b/Samples/CustomControls/CsApp/Assets/Wide310x150Logo.png differ diff --git a/Samples/CustomControls/CsApp/Assets/logo.png b/Samples/CustomControls/CsApp/Assets/logo.png new file mode 100644 index 000000000..fd2293e7b Binary files /dev/null and b/Samples/CustomControls/CsApp/Assets/logo.png differ diff --git a/Samples/CustomControls/CsApp/Assets/windows-sdk.ico b/Samples/CustomControls/CsApp/Assets/windows-sdk.ico new file mode 100644 index 000000000..16b6a4021 Binary files /dev/null and b/Samples/CustomControls/CsApp/Assets/windows-sdk.ico differ diff --git a/Samples/CustomControls/CsApp/CsApp.csproj b/Samples/CustomControls/CsApp/CsApp.csproj new file mode 100644 index 000000000..6e07d6ee6 --- /dev/null +++ b/Samples/CustomControls/CsApp/CsApp.csproj @@ -0,0 +1,44 @@ + + + WinExe + net6.0-windows10.0.19041.0 + 10.0.17763.0 + CsApp + app.manifest + x86;x64;arm64 + win10-x86;win10-x64;win10-arm64 + true + true + Properties\PublishProfiles\win10-$(Platform).pubxml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CsApp/MainPage.xaml b/Samples/CustomControls/CsApp/MainPage.xaml new file mode 100644 index 000000000..e241f55e1 --- /dev/null +++ b/Samples/CustomControls/CsApp/MainPage.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CsApp/MainPage.xaml.cs b/Samples/CustomControls/CsApp/MainPage.xaml.cs new file mode 100644 index 000000000..96466e5e3 --- /dev/null +++ b/Samples/CustomControls/CsApp/MainPage.xaml.cs @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Navigation; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace CsApp +{ + public partial class MainPage : Page + { + public static MainPage Current; + public List Scenarios => this.scenarios; + + public MainPage() + { + InitializeComponent(); + + // This is a static public property that allows downstream pages to get a handle to the MainPage instance + // in order to call methods that are in this class. + Current = this; + } + + public void NotifyUser(string strMessage, InfoBarSeverity severity, bool isOpen = true) + { + // If called from the UI thread, then update immediately. + // Otherwise, schedule a task on the UI thread to perform the update. + if (DispatcherQueue.HasThreadAccess) + { + UpdateStatus(strMessage, severity, isOpen); + } + else + { + DispatcherQueue.TryEnqueue(() => + { + UpdateStatus(strMessage, severity, isOpen); + }); + } + } + + private void UpdateStatus(string strMessage, InfoBarSeverity severity, bool isOpen) + { + infoBar.Message = strMessage; + infoBar.IsOpen = isOpen; + infoBar.Severity = severity; + } + + private void NavView_Loaded(object sender, RoutedEventArgs e) + { + foreach (Scenario item in scenarios) + { + NavView.MenuItems.Add(new NavigationViewItem + { + Content = item.Title, + Tag = item.ClassName, + Icon = new FontIcon() { FontFamily = new("Segoe MDL2 Assets"), Glyph = "\uE82D" } + }); + } + + // NavView doesn't load any page by default, so load home page. + NavView.SelectedItem = NavView.MenuItems[0]; + + // If navigation occurs on SelectionChanged, this isn't needed. + // Because we use ItemInvoked to navigate, we need to call Navigate + // here to load the home page. + if (scenarios is not null && scenarios.Count > 0) + { + NavView_Navigate(scenarios.First().ClassName, new Microsoft.UI.Xaml.Media.Animation.EntranceNavigationTransitionInfo()); + } + } + + private void NavView_Navigate(string navItemTag, Microsoft.UI.Xaml.Media.Animation.NavigationTransitionInfo transitionInfo) + { + Type page; + + if (navItemTag == nameof(SettingsPage)) + { + page = typeof(SettingsPage); + } + else + { + Scenario item = scenarios.First(p => p.ClassName.Equals(navItemTag)); + page = Type.GetType(item.ClassName); + } + + // Get the page type before navigation so you can prevent duplicate + // entries in the backstack. + var preNavPageType = ContentFrame.CurrentSourcePageType; + + // Only navigate if the selected page isn't currently loaded. + if ((page is not null) && !Type.Equals(preNavPageType, page)) + { + ContentFrame.Navigate(page, null, transitionInfo); + } + } + + private void NavView_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args) + { + if (ContentFrame.CanGoBack) + { + ContentFrame.GoBack(); + } + } + + private void NavView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) + { + var naViewItemInvoked = (NavigationViewItem)args.InvokedItemContainer; + + if (args.IsSettingsInvoked) + { + NavView_Navigate(nameof(SettingsPage), args.RecommendedNavigationTransitionInfo); + } + else if (args.InvokedItemContainer is not null) + { + var navItemTag = args.InvokedItemContainer.Tag?.ToString(); + if (!string.IsNullOrEmpty(navItemTag)) + { + NavView_Navigate(navItemTag, new Microsoft.UI.Xaml.Media.Animation.EntranceNavigationTransitionInfo()); + } + } + } + + private void ContentFrame_Navigated(object sender, NavigationEventArgs e) + { + NavView.IsBackEnabled = ContentFrame.CanGoBack; + + if (ContentFrame.SourcePageType == typeof(SettingsPage)) + { + // SettingsItem is not part of NavView.MenuItems, and doesn't have a Tag. + NavView.SelectedItem = (NavigationViewItem)NavView.SettingsItem; + NavView.Header = "Settings"; + } + else if (ContentFrame.SourcePageType != null) + { + var item = scenarios.First(p => p.ClassName == e.SourcePageType.FullName); + var menuItems = NavView.MenuItems; + + NavView.SelectedItem = NavView.MenuItems + .OfType() + .First(n => n.Tag.Equals(item.ClassName)); + + NavView.Header = + ((NavigationViewItem)NavView.SelectedItem)?.Content?.ToString(); + } + } + } +} diff --git a/Samples/CustomControls/CsApp/MainWindow.xaml b/Samples/CustomControls/CsApp/MainWindow.xaml new file mode 100644 index 000000000..05fba2604 --- /dev/null +++ b/Samples/CustomControls/CsApp/MainWindow.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/Samples/CustomControls/CsApp/MainWindow.xaml.cs b/Samples/CustomControls/CsApp/MainWindow.xaml.cs new file mode 100644 index 000000000..c371fcb0a --- /dev/null +++ b/Samples/CustomControls/CsApp/MainWindow.xaml.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.UI.Xaml; +using System; +using System.Runtime.InteropServices; +using Windows.Win32.Foundation; +using Windows.Win32.Graphics.Gdi; +using Windows.Win32.UI.Controls; +using Windows.Win32.UI.WindowsAndMessaging; +using static Windows.Win32.Constants; +using static Windows.Win32.PInvoke; + +namespace CsApp +{ + public partial class MainWindow : Window + { + public MainWindow() + { + this.InitializeComponent(); + + Title = SampleConfig.FeatureName; + + HWND hwnd = (HWND)WinRT.Interop.WindowNative.GetWindowHandle(this); + LoadIcon(hwnd, "Assets/windows-sdk.ico"); + SetWindowSize(hwnd, 1050, 800); + PlacementCenterWindowInMonitorWin32(hwnd); + } + + private unsafe void LoadIcon(HWND hwnd, string iconName) + { + const int ICON_SMALL = 0; + const int ICON_BIG = 1; + + fixed (char* nameLocal = iconName) + { + HANDLE smallIcon = LoadImage(default, + nameLocal, + GDI_IMAGE_TYPE.IMAGE_ICON, + GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXSMICON), + GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYSMICON), + IMAGE_FLAGS.LR_LOADFROMFILE | IMAGE_FLAGS.LR_SHARED); + SendMessage(hwnd, WM_SETICON, ICON_SMALL, smallIcon.Value); + } + + fixed (char* nameLocal = iconName) + { + HANDLE bigIcon = LoadImage(default, + nameLocal, + GDI_IMAGE_TYPE.IMAGE_ICON, + GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXSMICON), + GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYSMICON), + IMAGE_FLAGS.LR_LOADFROMFILE | IMAGE_FLAGS.LR_SHARED); + SendMessage(hwnd, WM_SETICON, ICON_BIG, bigIcon.Value); + } + } + + private void SetWindowSize(HWND hwnd, int width, int height) + { + // Win32 uses pixels and WinUI 3 uses effective pixels, so you should apply the DPI scale factor + uint dpi = GetDpiForWindow(hwnd); + float scalingFactor = (float)dpi / 96; + width = (int)(width * scalingFactor); + height = (int)(height * scalingFactor); + + SetWindowPos(hwnd, default, 0, 0, width, height, SET_WINDOW_POS_FLAGS.SWP_NOMOVE | SET_WINDOW_POS_FLAGS.SWP_NOZORDER); + } + + private void PlacementCenterWindowInMonitorWin32(HWND hwnd) + { + RECT windowMonitorRectToAdjust; + GetWindowRect(hwnd, out windowMonitorRectToAdjust); + ClipOrCenterRectToMonitorWin32(ref windowMonitorRectToAdjust); + SetWindowPos(hwnd, default, windowMonitorRectToAdjust.left, + windowMonitorRectToAdjust.top, 0, 0, + SET_WINDOW_POS_FLAGS.SWP_NOSIZE | + SET_WINDOW_POS_FLAGS.SWP_NOZORDER | + SET_WINDOW_POS_FLAGS.SWP_NOACTIVATE); + } + + private void ClipOrCenterRectToMonitorWin32(ref RECT adjustedWindowRect) + { + MONITORINFO mi = new MONITORINFO(); + mi.cbSize = (uint)Marshal.SizeOf(); + GetMonitorInfo(MonitorFromRect(adjustedWindowRect, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST), ref mi); + + RECT rcWork = mi.rcWork; + int w = adjustedWindowRect.right - adjustedWindowRect.left; + int h = adjustedWindowRect.bottom - adjustedWindowRect.top; + + adjustedWindowRect.left = rcWork.left + (rcWork.right - rcWork.left - w) / 2; + adjustedWindowRect.top = rcWork.top + (rcWork.bottom - rcWork.top - h) / 2; + adjustedWindowRect.right = adjustedWindowRect.left + w; + adjustedWindowRect.bottom = adjustedWindowRect.top + h; + } + } +} diff --git a/Samples/CustomControls/CsApp/NativeMethods.txt b/Samples/CustomControls/CsApp/NativeMethods.txt new file mode 100644 index 000000000..d5596147d --- /dev/null +++ b/Samples/CustomControls/CsApp/NativeMethods.txt @@ -0,0 +1,12 @@ +GetDpiForWindow +GetModuleHandle +GetMonitorInfo +GetSystemMetrics +GetWindowRect +LoadImage +MONITORINFO +MonitorFromRect +RECT +SendMessage +SetWindowPos +WM_SETICON diff --git a/Samples/CustomControls/CsApp/Package.appxmanifest b/Samples/CustomControls/CsApp/Package.appxmanifest new file mode 100644 index 000000000..f89e139c2 --- /dev/null +++ b/Samples/CustomControls/CsApp/Package.appxmanifest @@ -0,0 +1,48 @@ + + + + + + + + CsApp + Microsoft Corporation + Assets\logo.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-arm64.pubxml b/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-arm64.pubxml new file mode 100644 index 000000000..93f661786 --- /dev/null +++ b/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-arm64.pubxml @@ -0,0 +1,19 @@ + + + + + FileSystem + arm64 + win10-arm64 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + true + False + False + True + + \ No newline at end of file diff --git a/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-x64.pubxml b/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-x64.pubxml new file mode 100644 index 000000000..26ea7e55c --- /dev/null +++ b/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-x64.pubxml @@ -0,0 +1,20 @@ + + + + + FileSystem + x64 + win10-x64 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + true + False + False + True + + + \ No newline at end of file diff --git a/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-x86.pubxml b/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-x86.pubxml new file mode 100644 index 000000000..34d14d4d4 --- /dev/null +++ b/Samples/CustomControls/CsApp/Properties/PublishProfiles/win10-x86.pubxml @@ -0,0 +1,20 @@ + + + + + FileSystem + x86 + win10-x86 + bin\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\publish\ + true + False + False + True + + + \ No newline at end of file diff --git a/Samples/CustomControls/CsApp/Properties/launchSettings.json b/Samples/CustomControls/CsApp/Properties/launchSettings.json new file mode 100644 index 000000000..c75cf04da --- /dev/null +++ b/Samples/CustomControls/CsApp/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "CsApp (Package)": { + "commandName": "MsixPackage" + }, + "CsApp (Unpackaged)": { + "commandName": "Project" + } + } +} \ No newline at end of file diff --git a/Samples/CustomControls/CsApp/SampleConfiguration.cs b/Samples/CustomControls/CsApp/SampleConfiguration.cs new file mode 100644 index 000000000..676089b54 --- /dev/null +++ b/Samples/CustomControls/CsApp/SampleConfiguration.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using System.Collections.Generic; + +namespace CsApp +{ + internal static class SampleConfig + { + public const string FeatureName = "CsApp"; + public static ElementTheme CurrentTheme = ElementTheme.Default; + } + + public partial class MainPage : Page + { + private readonly List scenarios = new() + { + new Scenario() { Title = "Custom Control", ClassName = typeof(Scenario1_CustomControl).FullName }, + new Scenario() { Title = "User Control", ClassName = typeof(Scenario2_UserControl).FullName } + }; + } + + public class Scenario + { + public string Title { get; set; } + public string ClassName { get; set; } + } +} diff --git a/Samples/CustomControls/CsApp/Scenario1_CustomControl.xaml b/Samples/CustomControls/CsApp/Scenario1_CustomControl.xaml new file mode 100644 index 000000000..eda5082af --- /dev/null +++ b/Samples/CustomControls/CsApp/Scenario1_CustomControl.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + Reference a Custom WinUI Button type from a C# component. + + + + + + + + + diff --git a/Samples/CustomControls/CsApp/Scenario1_CustomControl.xaml.cs b/Samples/CustomControls/CsApp/Scenario1_CustomControl.xaml.cs new file mode 100644 index 000000000..58c1bddd2 --- /dev/null +++ b/Samples/CustomControls/CsApp/Scenario1_CustomControl.xaml.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +namespace CsApp +{ + public partial class Scenario1_CustomControl : Page + { + private MainPage rootPage = MainPage.Current; + + public Scenario1_CustomControl() + { + this.InitializeComponent(); + } + + } +} diff --git a/Samples/CustomControls/CsApp/Scenario2_UserControl.xaml b/Samples/CustomControls/CsApp/Scenario2_UserControl.xaml new file mode 100644 index 000000000..63a3d61ef --- /dev/null +++ b/Samples/CustomControls/CsApp/Scenario2_UserControl.xaml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + Reference a Custom User Control from a C# Component. + + + + + + + + + + diff --git a/Samples/CustomControls/CsApp/Scenario2_UserControl.xaml.cs b/Samples/CustomControls/CsApp/Scenario2_UserControl.xaml.cs new file mode 100644 index 000000000..cdeed77c6 --- /dev/null +++ b/Samples/CustomControls/CsApp/Scenario2_UserControl.xaml.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.UI.Xaml.Controls; + +namespace CsApp +{ + public partial class Scenario2_UserControl : Page + { + public Scenario2_UserControl() + { + this.InitializeComponent(); + } + } +} diff --git a/Samples/CustomControls/CsApp/SettingsPage.xaml b/Samples/CustomControls/CsApp/SettingsPage.xaml new file mode 100644 index 000000000..bb8090017 --- /dev/null +++ b/Samples/CustomControls/CsApp/SettingsPage.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + Light + + + + + Dark + + + + + Default + + + + + + + + + + + diff --git a/Samples/CustomControls/CsApp/SettingsPage.xaml.cs b/Samples/CustomControls/CsApp/SettingsPage.xaml.cs new file mode 100644 index 000000000..d244b0650 --- /dev/null +++ b/Samples/CustomControls/CsApp/SettingsPage.xaml.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Navigation; +using System.Linq; + +namespace CsApp +{ + public partial class SettingsPage : Page + { + public SettingsPage() + { + this.InitializeComponent(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + themePanel.Children.Cast().First(c => (ElementTheme)c.Tag == SampleConfig.CurrentTheme).IsChecked = true; + base.OnNavigatedTo(e); + } + + private void OnThemeRadioButtonChecked(object sender, RoutedEventArgs e) + { + ElementTheme selectedTheme = (ElementTheme)((RadioButton)sender).Tag; + + Grid content = MainPage.Current.Content as Grid; + if (content is not null) + { + content.RequestedTheme = selectedTheme; + SampleConfig.CurrentTheme = content.RequestedTheme; + } + } + } +} diff --git a/Samples/CustomControls/CsApp/Styles.xaml b/Samples/CustomControls/CsApp/Styles.xaml new file mode 100644 index 000000000..e79221750 --- /dev/null +++ b/Samples/CustomControls/CsApp/Styles.xaml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/CustomControls/CsApp/app.manifest b/Samples/CustomControls/CsApp/app.manifest new file mode 100644 index 000000000..f9e21aa55 --- /dev/null +++ b/Samples/CustomControls/CsApp/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/Samples/CustomControls/CsWinRTAuthoringWinUI.sln b/Samples/CustomControls/CsWinRTAuthoringWinUI.sln new file mode 100644 index 000000000..ba27c4622 --- /dev/null +++ b/Samples/CustomControls/CsWinRTAuthoringWinUI.sln @@ -0,0 +1,97 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32126.317 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppApp", "CppApp\CppApp.vcxproj", "{34A4AD19-A703-47F3-B279-E505C6A2A935}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CsApp", "CsApp\CsApp.csproj", "{4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppAppUnpackaged", "CppAppUnpackaged\CppAppUnpackaged.vcxproj", "{B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinUIComponentCs", "WinUIComponentCs\WinUIComponentCs.csproj", "{BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|arm64 = Debug|arm64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|arm64 = Release|arm64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|arm64.ActiveCfg = Debug|arm64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|arm64.Build.0 = Debug|arm64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|arm64.Deploy.0 = Debug|arm64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|x64.ActiveCfg = Debug|x64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|x64.Build.0 = Debug|x64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|x64.Deploy.0 = Debug|x64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|x86.ActiveCfg = Debug|Win32 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|x86.Build.0 = Debug|Win32 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Debug|x86.Deploy.0 = Debug|Win32 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|arm64.ActiveCfg = Release|arm64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|arm64.Build.0 = Release|arm64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|arm64.Deploy.0 = Release|arm64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|x64.ActiveCfg = Release|x64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|x64.Build.0 = Release|x64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|x64.Deploy.0 = Release|x64 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|x86.ActiveCfg = Release|Win32 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|x86.Build.0 = Release|Win32 + {34A4AD19-A703-47F3-B279-E505C6A2A935}.Release|x86.Deploy.0 = Release|Win32 + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Debug|arm64.ActiveCfg = Debug|Any CPU + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Debug|arm64.Build.0 = Debug|Any CPU + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Debug|x64.ActiveCfg = Debug|x64 + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Debug|x64.Build.0 = Debug|x64 + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Debug|x86.ActiveCfg = Debug|x86 + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Debug|x86.Build.0 = Debug|x86 + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Release|arm64.ActiveCfg = Release|Any CPU + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Release|arm64.Build.0 = Release|Any CPU + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Release|x64.ActiveCfg = Release|Any CPU + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Release|x64.Build.0 = Release|Any CPU + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Release|x86.ActiveCfg = Release|Any CPU + {BCC816DC-0F01-4F0F-8506-DF6AFEFAEA92}.Release|x86.Build.0 = Release|Any CPU + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|arm64.ActiveCfg = Debug|arm64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|arm64.Build.0 = Debug|arm64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|arm64.Deploy.0 = Debug|arm64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|x64.ActiveCfg = Debug|x64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|x64.Build.0 = Debug|x64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|x64.Deploy.0 = Debug|x64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|x86.ActiveCfg = Debug|x86 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|x86.Build.0 = Debug|x86 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Debug|x86.Deploy.0 = Debug|x86 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|arm64.ActiveCfg = Release|arm64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|arm64.Build.0 = Release|arm64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|arm64.Deploy.0 = Release|arm64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|x64.ActiveCfg = Release|x64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|x64.Build.0 = Release|x64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|x64.Deploy.0 = Release|x64 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|x86.ActiveCfg = Release|x86 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|x86.Build.0 = Release|x86 + {4B4FA4E7-D50E-4059-A906-6F78F6DFEBCD}.Release|x86.Deploy.0 = Release|x86 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|arm64.ActiveCfg = Debug|arm64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|arm64.Build.0 = Debug|arm64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|arm64.Deploy.0 = Debug|arm64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|x64.ActiveCfg = Debug|x64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|x64.Build.0 = Debug|x64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|x64.Deploy.0 = Debug|x64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|x86.ActiveCfg = Debug|Win32 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|x86.Build.0 = Debug|Win32 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Debug|x86.Deploy.0 = Debug|Win32 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|arm64.ActiveCfg = Release|arm64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|arm64.Build.0 = Release|arm64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|arm64.Deploy.0 = Release|arm64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|x64.ActiveCfg = Release|x64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|x64.Build.0 = Release|x64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|x64.Deploy.0 = Release|x64 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|x86.ActiveCfg = Release|Win32 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|x86.Build.0 = Release|Win32 + {B71D15EF-F17B-4E8F-B023-08C4E3B32DAB}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EF6C20C8-AA97-4F17-A329-7A96FC162EAD} + EndGlobalSection +EndGlobal diff --git a/Samples/CustomControls/README.md b/Samples/CustomControls/README.md new file mode 100644 index 000000000..9a9e5c32f --- /dev/null +++ b/Samples/CustomControls/README.md @@ -0,0 +1,42 @@ +--- +page_type: sample +languages: +- cpp +- csharp +products: +- windows +- windows-app-sdk +name: "C# Windows Runtime Component WinUI Controls Sample" +urlFragment: csruntimecomponent +description: "Shows how to author a Windows Runtime Component in C# with WinUI controls and how to consume it from C++ and C#." +extendedZipContent: +- path: LICENSE + target: LICENSE +--- +# Custom Controls Sample (C# Windows Runtime Component) + +This sample demonstrates how to author C# components with WinUI controls (User Control and Custom Control) using C#/WinRT, and how to consume these components from C++ and C# apps. + +The sample solution includes the following application projects: + +- **CppApp** (packaged C++ WinUI app) +- **CppAppUnpackaged** (unpackaged C++ WinUI app) +- **CsApp** (packaged C# WinUI app) + +All the application projects have a project reference to the C# Windows Runtime component library project, **WinUICsComponent**. The C# component uses the *Microsoft.Windows.CsWinRT* NuGet package to generate a Windows Runtime Component with custom WinUI controls. + +## Prerequisites + +* See [System requirements for Windows app development](https://docs.microsoft.com/windows/apps/windows-app-sdk/system-requirements). +* Make sure that your development environment is set up correctly—see [Install tools for developing apps for Windows 10 and Windows 11](https://docs.microsoft.com/windows/apps/windows-app-sdk/set-up-your-development-environment). + +## Building and running the sample + +* Open the solution file (`.sln`) in Visual Studio. +* Set one of the application projects as the startup project. +* Select `x86` as the Solution platform. There is a known issue with `x64` and `arm64` (https://github.com/microsoft/CsWinRT/issues/1093). +* From Visual Studio, either **Start Without Debugging** (Ctrl+F5) or **Start Debugging** (F5). + +## Related Links + +- [C#/WinRT Authoring](https://github.com/microsoft/CsWinRT/blob/master/docs/authoring.md) diff --git a/Samples/CustomControls/WinUIComponentCs/CustomButton.cs b/Samples/CustomControls/WinUIComponentCs/CustomButton.cs new file mode 100644 index 000000000..dd98b3368 --- /dev/null +++ b/Samples/CustomControls/WinUIComponentCs/CustomButton.cs @@ -0,0 +1,70 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Documents; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace WinUIComponentCs +{ + public sealed class CustomButton : Button + { + public string Text { get; private set; } + public bool OverrideEntered { get; set; } + + public CustomButton() + : this("CustomButton") + { + } + + public CustomButton(string text) + { + Text = text; + Content = text; + OverrideEntered = true; + } + + protected override void OnPointerEntered(global::Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) + { + if (!OverrideEntered) + { + base.OnPointerEntered(e); + return; + } + + Text = Content?.ToString(); + Content = "Entered"; + } + + protected override void OnPointerExited(global::Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e) + { + if (!OverrideEntered) + { + base.OnPointerExited(e); + return; + } + + Content = Text; + } + + protected override Size MeasureOverride(Size availableSize) + { + var size = new Size(160, 30); + base.MeasureOverride(size); + return size; + } + + public string GetText() + { + return Text; + } + } +} diff --git a/Samples/CustomControls/WinUIComponentCs/NameReporter.xaml b/Samples/CustomControls/WinUIComponentCs/NameReporter.xaml new file mode 100644 index 000000000..11ae225d1 --- /dev/null +++ b/Samples/CustomControls/WinUIComponentCs/NameReporter.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + First Name: + + + + + + Last Name: + + + +