Skip to content

Commit 162d08f

Browse files
committed
TitleBar Captions buttons automatically adjust WindowStyle to match flow direction
1 parent 25d5ba9 commit 162d08f

File tree

3 files changed

+52
-13
lines changed

3 files changed

+52
-13
lines changed

components/TitleBar/src/NativeMethods.cs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,21 @@ public enum WindowMessage : int
1919
[Flags]
2020
public enum WindowStyle : uint
2121
{
22-
WS_SYSMENU = 0x80000
22+
WS_SYSMENU = 0x80000,
23+
}
24+
25+
[Flags]
26+
public enum WindowStyleExtended : ulong
27+
{
28+
WS_EX_LAYOUTRTL= 0x00400000L,
2329
}
2430

2531
[Flags]
2632
public enum WindowLongIndexFlags : int
2733
{
2834
GWL_WNDPROC = -4,
29-
GWL_STYLE = -16
35+
GWL_STYLE = -16,
36+
GWL_EXSTYLE = -20,
3037
}
3138

3239
[Flags]
@@ -44,43 +51,50 @@ public enum SystemCommand
4451
SC_KEYMENU = 0xF100
4552
}
4653

54+
// TODO: Check for typing online. IntPtr, int, or long?
55+
4756
[DllImport("user32.dll", EntryPoint = "GetWindowLongW", SetLastError = false)]
48-
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
57+
public static extern int GetWindowLongW(IntPtr hWnd, int nIndex);
58+
59+
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", SetLastError = false)]
60+
public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
4961

5062
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtrW", SetLastError = false)]
51-
public static extern int GetWindowLongPtr(IntPtr hWnd, int nIndex);
63+
public static extern int GetWindowLongPtrW(IntPtr hWnd, int nIndex);
5264

5365
public static int GetWindowLongAuto(IntPtr hWnd, int nIndex)
5466
{
5567
if (IntPtr.Size is 8)
5668
{
57-
return GetWindowLongPtr(hWnd, nIndex);
69+
return GetWindowLongPtrW(hWnd, nIndex);
5870
}
5971
else
6072
{
61-
return GetWindowLong(hWnd, nIndex);
73+
return GetWindowLongW(hWnd, nIndex);
6274
}
6375
}
6476

6577
[DllImport("user32.dll", EntryPoint = "FindWindowExW", SetLastError = true, CharSet = CharSet.Unicode)]
6678
public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);
6779

68-
6980
[DllImport("user32.dll", EntryPoint = "SetWindowLongW", SetLastError = false)]
70-
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
81+
public static extern IntPtr SetWindowLongW(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
7182

72-
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtrW", SetLastError = false)]
83+
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = false)]
7384
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
7485

86+
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtrW", SetLastError = false)]
87+
public static extern IntPtr SetWindowLongPtrW(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
88+
7589
public static IntPtr SetWindowLongAuto(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
7690
{
7791
if (IntPtr.Size is 8)
7892
{
79-
return SetWindowLongPtr(hWnd, nIndex, dwNewLong);
93+
return SetWindowLongPtrW(hWnd, nIndex, dwNewLong);
8094
}
8195
else
8296
{
83-
return SetWindowLong(hWnd, nIndex, dwNewLong);
97+
return SetWindowLongW(hWnd, nIndex, dwNewLong);
8498
}
8599
}
86100

components/TitleBar/src/TitleBar.WASDK.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
// See the LICENSE file in the project root for more information.
44

55
#if WINDOWS_WINAPPSDK && !HAS_UNO
6-
using Windows.Graphics;
76
using Microsoft.UI;
87
using Microsoft.UI.Input;
98
using Microsoft.UI.Windowing;
109
using Microsoft.UI.Xaml.Media;
10+
using System.Runtime.InteropServices;
11+
using Windows.Graphics;
1112

1213
namespace CommunityToolkit.WinUI.Controls;
1314

@@ -100,6 +101,30 @@ private void UpdateCaptionButtons(FrameworkElement rootElement)
100101
Window.AppWindow.TitleBar.ButtonForegroundColor = Colors.Black;
101102
Window.AppWindow.TitleBar.ButtonInactiveForegroundColor = Colors.DarkGray;
102103
}
104+
105+
// Set the caption buttons to match the flow direction of the app
106+
UpdateCaptionButtonsDirection(rootElement.FlowDirection);
107+
}
108+
109+
private void UpdateCaptionButtonsDirection(FlowDirection direction)
110+
{
111+
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this.Window);
112+
113+
if (hwnd != 0)
114+
{
115+
var exStyle = NativeMethods.GetWindowLongPtr(hwnd, (int)NativeMethods.WindowLongIndexFlags.GWL_EXSTYLE);
116+
117+
if (direction == FlowDirection.RightToLeft)
118+
{
119+
exStyle |= (nint)NativeMethods.WindowStyleExtended.WS_EX_LAYOUTRTL;
120+
}
121+
else
122+
{
123+
exStyle &= (nint)NativeMethods.WindowStyleExtended.WS_EX_LAYOUTRTL;
124+
}
125+
126+
NativeMethods.SetWindowLongPtr(hwnd, (int)NativeMethods.WindowLongIndexFlags.GWL_EXSTYLE, exStyle);
127+
}
103128
}
104129

105130
private void ResetWASDKTitleBar()

components/TitleBar/src/WndProcHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void RegisterInputNonClientPointerSourceWndProc(WNDPROC wndProc)
4444

4545
if (inputNonClientPointerSourceHandle != IntPtr.Zero)
4646
{
47-
int style = NativeMethods.GetWindowLongAuto(Handle, (int)NativeMethods.WindowLongIndexFlags.GWL_STYLE);
47+
IntPtr style = NativeMethods.GetWindowLongAuto(Handle, (int)NativeMethods.WindowLongIndexFlags.GWL_STYLE);
4848
NativeMethods.SetWindowLongAuto(Handle, (int)NativeMethods.WindowLongIndexFlags.GWL_STYLE, (IntPtr)(style & ~(int)NativeMethods.WindowStyle.WS_SYSMENU));
4949

5050
newInputNonClientPointerSourceWndProc = wndProc;

0 commit comments

Comments
 (0)