You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
    

修复方案

  1. 移除MyUserWindow_SizeChanged事件中的SetRegionsForCustomTitleBar调用:
private void MyUserWindow_SizeChanged(object sender, WindowSizeChangedEventArgs args)
{
    this.MyCaptionsRegion.OnWindowStateChanged();
}
  1. 给TabStripFooter的CustomDragRegion添加SizeChanged事件,需加入50ms延迟否则问题仍存在:
private async void CustomDragRegion_SizeChanged(object sender, SizeChangedEventArgs args)
{
    await Task.Delay(50);
    ManageWindows.GetUserWindow().SetRegionsForCustomTitleBar();
}

内容的提问来源于stack exchange,提问作者Pain Nncera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:10:57