2

I'm building a WinUI 3 desktop application with a custom TitleBar. I've applied FlowDirection="RightToLeft" to the main grid in my MainWindow.xaml, but the caption buttons (minimize, maximize, close) and the title alignment remain in left-to-right layout.

<Window
    x:Class="YourNamespace.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:YourNamespace">
    
    <Window.SystemBackdrop>
        <MicaBackdrop />
    </Window.SystemBackdrop>

    <Grid x:Name="MainGrid" RowDefinitions="auto,*">
        <TitleBar
            Title="Custom Title Bar"
            IsBackButtonEnabled="True"
            IsBackButtonVisible="True"
            Subtitle="Beta">
            <TitleBar.RightHeader>
                <PersonPicture Height="25" Initials="JD" />
            </TitleBar.RightHeader>
        </TitleBar>
        <StackPanel Grid.Row="1">
            <Button Content="Click" />
        </StackPanel>
    </Grid>
</Window>

Code behind file:

public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        MainGrid.FlowDirection = FlowDirection.RightToLeft;

        ExtendsContentIntoTitleBar = true;

        this.AppWindow.TitleBar.IconShowOptions = Microsoft.UI.Windowing.IconShowOptions.ShowIconAndSystemMenu;
        this.AppWindow.TitleBar.ButtonBackgroundColor = Microsoft.UI.Colors.Transparent;
        this.AppWindow.TitleBar.PreferredHeightOption = Microsoft.UI.Windowing.TitleBarHeightOption.Tall;
    }
} 

What I expect:

The custom TitleBar content and caption buttons should appear mirrored, with caption buttons on the left side when FlowDirection.RightToLeft is applied.

What happens instead: Only the internal elements (MainGrid) respect RightToLeft.

The caption buttons and title remain in LeftToRight layout.

Question: How can I force the caption buttons and title bar in a WinUI 3 custom title bar to follow FlowDirection.RightToLeft? Is this a known limitation or am I missing a specific setting?

Thanks!

1 Answer 1

1

I tried the following code from the GitHub repo, and it seems to be working:

<Window
    x:Class="WinUIApp3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:WinUIApp3"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid x:Name="TitleBarPageWindowGrid" RowDefinitions="Auto,*">
        <TitleBar x:Name="AppTitleBar"
            Title="TITLE"
            Grid.Row="0"
            Subtitle="SUBTITLE" />
    </Grid>

</Window>
public sealed partial class MainWindow : Window
{
    const int GWL_EXSTYLE = -20;

    const int WS_EX_LAYOUTRTL = 0x00400000;

    public MainWindow()
    {
        InitializeComponent();
        ExtendsContentIntoTitleBar = true;
        SetTitleBar(AppTitleBar);
        TitleBarPageWindowGrid.FlowDirection = FlowDirection.RightToLeft;
        UpdateCaptionButtonDirection(FlowDirection.RightToLeft);
    }

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

    [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
    internal static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);

    private static nint GetWindowHandleForCurrentWindow(object target) =>
        WinRT.Interop.WindowNative.GetWindowHandle(target);
    private void UpdateCaptionButtonDirection(FlowDirection direction)
    {
        var hwnd = GetWindowHandleForCurrentWindow(this);

        if (hwnd != 0)
        {
            var exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE);

            if (direction == FlowDirection.RightToLeft)
            {
                exStyle |= WS_EX_LAYOUTRTL;
            }
            else
            {
                exStyle &= ~WS_EX_LAYOUTRTL;
            }

            SetWindowLongPtr(hwnd, GWL_EXSTYLE, exStyle);
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

It works! Thanks @AndrewKeepCoding — this worked perfectly, just as I wanted. I really appreciate your response!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.