WinUI3窗口最大化后拖拽区域异常问题及延迟修复方案
UWP自定义标题栏SetDragRegion方法异常问题及修复
问题现象
- 调试阶段,
captionsregion和TabViewItem均不可拖拽,功能正常 - 窗口最大化后,TabViewItem变为可拖拽移动,且失去拖出窗口的功能
- 新增标签后拖拽区域恢复正常,但这不是理想解决方案
相关代码
TabViewControl可视化树
<Grid> <TabView x:Name="MyTabView" Background="Transparent" AddTabButtonClick="MyTabView_AddTabButtonClick" TabCloseRequested="MyTabView_TabCloseRequested"> <!--自定义左侧区域--> <TabView.TabStripHeader> <Border x:Name="MyCustomMenuRegion" MinWidth="0" Background="Transparent" IsHitTestVisible="False"/> </TabView.TabStripHeader> <!--默认首页标签--> <TabViewItem Header="Home" Background="Transparent" IsClosable="False" MaxHeight="40" MaxWidth="50"> </TabViewItem> <!--自定义右侧拖拽区域--> <TabView.TabStripFooter> <Border x:Name="CustomDragRegion" MinWidth="0" Background="Transparent" IsHitTestVisible="False" SizeChanged="CustomDragRegion_SizeChanged"/> </TabView.TabStripFooter> </TabView> </Grid>
UserWindow(MainWindow)可视化树
<Grid> <Grid.RowDefinitions> <RowDefinition Height="40" x:Name="TitleBarRegion"/> <RowDefinition Height="*" x:Name="ContentRegion"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" x:Name="ControlRegion"/> </Grid.ColumnDefinitions> <myUICrl:MyTitleRegionControl x:Name="MyTitleRegion" Grid.Row="0" Grid.Column="0" Canvas.ZIndex="0"/> <myUICrl:MyCaptionsRegionControl x:Name="MyCaptionsRegion" Grid.Row="0" Grid.Column="1" Canvas.ZIndex="2" HorizontalAlignment="Right"/> <myUICrl:MyTabViewControl x:Name="MyTabView" Grid.Row="0" Grid.Column="0" Canvas.ZIndex="1"/> </Grid>
后台SetDragRegion相关代码
private void MyUserWindow_SizeChanged(object sender, WindowSizeChangedEventArgs args) { this.MyCaptionsRegion.OnWindowStateChanged(); if (this.MyTitleRegion.XamlRoot != null) { SetRegionsForCustomTitleBar(); } } internal void SetRegionsForCustomTitleBar() { double scale = this.MyTitleRegion.XamlRoot.RasterizationScale; // 设置标题栏宽度 SetTitleBarWidth(this.AppWindow, this.MyTitleRegion, scale); // 设置标题栏可拖拽区域 SetDraggableArea(this.AppWindow, this.MyTabView, scale); // 设置标题栏按钮不可拖拽区域 SetNonDraggableRegion(this.AppWindow, this.MyCaptionsRegion, scale); } private void SetTitleBarWidth(AppWindow myAppWindow, MyTitleRegionControl myTitleRegion, double scale) { myTitleRegion.GetHeaderDefinition().Width = new GridLength(myAppWindow.TitleBar.LeftInset / scale); myTitleRegion.GetFooterDefinition().Width = new GridLength(myAppWindow.TitleBar.RightInset / scale); } private void SetDraggableArea(AppWindow myAppWindow, MyTabViewControl myTabView, double scale) { Border myCustomDragRegion = myTabView.GetCustomDragRegion(); GeneralTransform customDragRegionTransform = myCustomDragRegion.TransformToVisual(null); Rect customDragRegionBounds = customDragRegionTransform.TransformBounds(new Rect(0, 0, myCustomDragRegion.ActualWidth, myCustomDragRegion.ActualHeight)); RectInt32 customDragRegionRect = GetRect(customDragRegionBounds, scale); Trace.WriteLine($"[SetDraggableArea] Bounds: X={customDragRegionBounds.X}, Y={customDragRegionBounds.Y}, W={customDragRegionBounds.Width}, H={customDragRegionBounds.Height}"); Trace.WriteLine($"[SetDraggableArea] Scaled Rect: X={customDragRegionRect.X}, Y={customDragRegionRect.Y}, W={customDragRegionRect.Width}, H={customDragRegionRect.Height}"); myAppWindow.TitleBar.SetDragRectangles(GetRectArray(customDragRegionRect)); } private void SetNonDraggableRegion(AppWindow myAppWindow, MyCaptionsRegionControl myCaptionsRegion, double scale) { GeneralTransform captionsRegionTransform = myCaptionsRegion.TransformToVisual(null); Rect captionsRegionBounds = captionsRegionTransform.TransformBounds(new Rect(0, 0, myCaptionsRegion.ActualWidth, myCaptionsRegion.ActualHeight)); RectInt32 captionsRegionRect = GetRect(captionsRegionBounds, scale); InputNonClientPointerSource nonClientInputSrc = InputNonClientPointerSource.GetForWindowId(myAppWindow.Id); nonClientInputSrc.SetRegionRects(NonClientRegionKind.Passthrough, GetRectArray(captionsRegionRect)); } private RectInt32 GetRect(Rect bounds, double scale) { return new RectInt32 ( _X: (int)Math.Round(bounds.X * scale), _Y: (int)Math.Round(bounds.Y * scale), _Width: (int)Math.Round(bounds.Width * scale), _Height: (int)Math.Round(bounds.Height * scale) ); } private RectInt32[] GetRectArray(RectInt32 rect) { return new RectInt32[] { rect }; }
测试数据
- 启动时:
[SetDraggableArea] Bounds: X=97, Y=0, W=1327, H=40 [SetDraggableArea] Scaled Rect: X=97, Y=0, W=1327, H=40 - 最大化后:
[SetDraggableArea] Bounds: X=97, Y=0, W=1823, H=40 [SetDraggableArea] Scaled Rect: X=97, Y=0, W=1823, H=40 - 恢复后:
[SetDraggableArea] Bounds: X=97, Y=0, W=1327, H=40 [SetDraggableArea] Scaled Rect: X=97, Y=0, W=1327, H=40
修复方案
- 移除
MyUserWindow_SizeChanged事件中的SetRegionsForCustomTitleBar调用:
private void MyUserWindow_SizeChanged(object sender, WindowSizeChangedEventArgs args) { this.MyCaptionsRegion.OnWindowStateChanged(); }
- 给
TabStripFooter的CustomDragRegion添加SizeChanged事件,需加入50ms延迟否则问题仍存在:
private async void CustomDragRegion_SizeChanged(object sender, SizeChangedEventArgs args) { await Task.Delay(50); ManageWindows.GetUserWindow().SetRegionsForCustomTitleBar(); }
内容的提问来源于stack exchange,提问作者Pain Nncera
相关产品推荐
相关产品推荐

