|
1 | 1 | ---
|
2 | 2 | title: Build a C# .NET app with WinUI 3 and Win32 interop
|
3 | 3 | description: Build a C# .NET application with WinUI 3 and basic Win32 interop capabilities using the Platform Invocation Services, or PInvoke.
|
4 |
| -ms.date: 03/04/2025 |
| 4 | +ms.date: 03/05/2025 |
5 | 5 | ms.topic: article
|
6 | 6 | keywords: windows 11, windows 10, uwp, COM, win32, winui, interop
|
7 | 7 | ms.localizationpriority: high
|
@@ -56,6 +56,10 @@ The following code shows the MainWindow.xaml file from the initial template app,
|
56 | 56 |
|
57 | 57 | :::code language="xml" source="samples/WinUI-3-basic-win32-interop/WinUI-3-basic-win32-interop/WinUI-3-basic-win32-interop.csproj" highlight="39":::
|
58 | 58 |
|
| 59 | +1. Add a text file to your project, and name it `NativeMethods.txt`. The contents of this file inform the C#/Win32 P/Invoke Source Generator the functions and types for which you want P/Invoke source code generated. In other words, which functions and types you'll be calling and using in your C# code. |
| 60 | + |
| 61 | + :::code language="csharp" source="samples/WinUI-3-basic-win32-interop/WinUI-3-basic-win32-interop/NativeMethods.txt"::: |
| 62 | + |
59 | 63 | ### Code
|
60 | 64 |
|
61 | 65 | 1. In the `App.xaml.cs` code-behind file, we get a handle to the [**Window**](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window) by using the **WindowNative.GetWindowHandle** WinRT COM interop method (see [Retrieve a window handle (HWND)](../../develop/ui-input/retrieve-hwnd.md)).
|
@@ -95,6 +99,119 @@ In this topic we covered accessing the underlying window implementation (in this
|
95 | 99 |
|
96 | 100 | For a more extensive sample, see the [AppWindow gallery sample](https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/Windowing) in the [Windows App SDK Samples](https://github.com/microsoft/WindowsAppSDK-Samples) GitHub repo.
|
97 | 101 |
|
| 102 | +## An example to customize the window title bar |
| 103 | + |
| 104 | +In this second example, we show how to customize the window's title bar and its content. Before following along with it, review these topics: |
| 105 | + |
| 106 | +* [Install tools for the Windows App SDK](/windows/apps/windows-app-sdk/set-up-your-development-environment). |
| 107 | +* [Create your first WinUI 3 project](/windows/apps/winui/winui3/create-your-first-winui3-app). |
| 108 | + |
| 109 | +### Create a new project |
| 110 | + |
| 111 | +1. In Visual Studio, create a new C# or C++/WinRT project from the **Blank App, Packaged (WinUI 3 in Desktop)** project template. |
| 112 | + |
| 113 | +### Configuration |
| 114 | + |
| 115 | +1. Again, reference the *Microsoft.Windows.CsWin32* NuGet package just like we did in the first example. |
| 116 | + |
| 117 | +1. Add a `NativeMethods.txt` text file to your project. |
| 118 | + |
| 119 | + :::code language="csharp" source="samples/window-titlebar/window-titlebar/NativeMethods.txt"::: |
| 120 | + |
| 121 | +### MainWindow.xaml |
| 122 | + |
| 123 | +> [!NOTE] |
| 124 | +> If you need an icon file to use with this walkthrough, then you can download the [`computer.ico` file](https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/netds/wlan/WirelessHostedNetwork/HostedNetwork/res/computer.ico) from the **WirelessHostednetwork** sample app. Place that file in your `Assets` folder, and add the file to your project as content. You'll then be able to refer to the file using the url `Assets/computer.ico`. |
| 125 | +> |
| 126 | +> Otherwise, feel free to use an icon file that you already have, and change the two references to it in the code listings below. |
| 127 | +
|
| 128 | +1. In the code listing below, you'll see that in `MainWindow.xaml` we've added two buttons, and specified **Click** handlers for each. In the **Click** handler for the first button (**basicButton_Click**), we set the title bar icon and text. In the second (**customButton_Click**), we demonstrate more significant customization by replacing the title bar with the content of the **StackPanel** named *customTitleBarPanel*. |
| 129 | + |
| 130 | +:::code language="xaml" source="samples/window-titlebar/window-titlebar/MainWindow.xaml"::: |
| 131 | + |
| 132 | +### MainWindow.xaml.cs/cpp |
| 133 | + |
| 134 | +1. In the code listing below for the **basicButton_Click** handler—in order to keep the custom title bar hidden—we collapse the *customTitleBarPanel* **StackPanel**, and we set the [ExtendsContentIntoTitleBar](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window.extendscontentintotitlebar) property to `false`. |
| 135 | +2. We then call **IWindowNative::get_WindowHandle** (for C#, using the interop helper method **GetWindowHandle**) to retrieve the window handle (**HWND**) of the main window. |
| 136 | +3. Next, we set the application icon (for C#, using the [PInvoke.User32](https://www.nuget.org/packages/PInvoke.User32/) NuGet package) by calling the [LoadImage](/windows/win32/api/winuser/nf-winuser-loadimagea) and [SendMessage](/windows/win32/api/winuser/nf-winuser-sendmessage) functions. |
| 137 | +4. Finally, we call [SetWindowText](/windows/win32/api/winuser/nf-winuser-setwindowtexta) to update the title bar string. |
| 138 | + |
| 139 | +:::code language="csharp" source="samples/window-titlebar/window-titlebar/MainWindow.xaml.cs" id="basicButton_Click" highlight="3-7,8-9,12-23"::: |
| 140 | + |
| 141 | +```cppwinrt |
| 142 | +// pch.h |
| 143 | +... |
| 144 | +#include <microsoft.ui.xaml.window.h> |
| 145 | +... |
| 146 | +
|
| 147 | +// MainWindow.xaml.h |
| 148 | +... |
| 149 | +void basicButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); |
| 150 | +... |
| 151 | +
|
| 152 | +// MainWindow.xaml.cpp |
| 153 | +void MainWindow::basicButton_Click(IInspectable const&, RoutedEventArgs const&) |
| 154 | +{ |
| 155 | + // Ensure the that custom title bar content is not displayed. |
| 156 | + customTitleBarPanel().Visibility(Visibility::Collapsed); |
| 157 | +
|
| 158 | + // Disable custom title bar content. |
| 159 | + ExtendsContentIntoTitleBar(false); |
| 160 | +
|
| 161 | + // Get the window's HWND |
| 162 | + auto windowNative{ this->m_inner.as<::IWindowNative>() }; |
| 163 | + HWND hWnd{ 0 }; |
| 164 | + windowNative->get_WindowHandle(&hWnd); |
| 165 | +
|
| 166 | + HICON icon{ reinterpret_cast<HICON>(::LoadImage(nullptr, L"Assets/computer.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE)) }; |
| 167 | + ::SendMessage(hWnd, WM_SETICON, 0, (LPARAM)icon); |
| 168 | +
|
| 169 | + this->Title(L"Basic customization of title bar"); |
| 170 | +} |
| 171 | +``` |
| 172 | + |
| 173 | +5. In the **customButton_Click** handler, we set the visibility of the *customTitleBarPanel* **StackPanel** to **Visible**. |
| 174 | +6. We then set the [ExtendsContentIntoTitleBar](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window.extendscontentintotitlebar) property to `true`, and call [SetTitleBar](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window.settitlebar) to display the *customTitleBarPanel* **StackPanel** as our custom title bar. |
| 175 | + |
| 176 | +:::code language="csharp" source="samples/window-titlebar/window-titlebar/MainWindow.xaml.cs" id="customButton_Click"::: |
| 177 | + |
| 178 | +```cppwinrt |
| 179 | +// MainWindow.xaml.h |
| 180 | +... |
| 181 | +void customButton_Click(Windows::Foundation::IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args); |
| 182 | +... |
| 183 | +
|
| 184 | +// MainWindow.xaml.cpp |
| 185 | +void MainWindow::customButton_Click(IInspectable const&, RoutedEventArgs const&) |
| 186 | +{ |
| 187 | + customTitleBarPanel().Visibility(Visibility::Visible); |
| 188 | +
|
| 189 | + // Enable custom title bar content. |
| 190 | + ExtendsContentIntoTitleBar(true); |
| 191 | +
|
| 192 | + // Set the content of the custom title bar. |
| 193 | + SetTitleBar(customTitleBarPanel()); |
| 194 | +} |
| 195 | +``` |
| 196 | + |
| 197 | +### App.xaml |
| 198 | + |
| 199 | +1. In the `App.xaml` file, immediately after the `<!-- Other app resources here -->` comment, we've added some custom-colored brushes for the title bar, as shown below. |
| 200 | + |
| 201 | +:::code language="csharp" source="samples/window-titlebar/window-titlebar/App.xaml"::: |
| 202 | + |
| 203 | +1. If you've been following along with these steps in your own app, then you can build your project now, and run the app. You'll see an application window similar to the following (with the custom app icon): |
| 204 | + |
| 205 | + :::image type="content" source="images/template-app-windowhandle.png" alt-text="Template app with no customization.":::<br/>*Template app.* |
| 206 | + |
| 207 | +- Here's the basic custom title bar: |
| 208 | + |
| 209 | + :::image type="content" source="images/template-app-windowhandle-basic-custom.png" alt-text="Template app with custom application icon.":::<br/>*Template app with custom application icon.* |
| 210 | + |
| 211 | +- Here's the fully custom title bar: |
| 212 | + |
| 213 | + :::image type="content" source="images/template-app-windowhandle-full-custom.png" alt-text="Template app with custom title bar.":::<br/>*Template app with custom title bar.* |
| 214 | + |
98 | 215 | ## See also
|
99 | 216 |
|
100 | 217 | - [Windows App SDK](../../windows-app-sdk/index.md)
|
|
0 commit comments