Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何比较属于同一逻辑/可视树的两个WPF控件的相对Z顺序?_C#_Wpf_Wpf Controls - Fatal编程技术网

C# 如何比较属于同一逻辑/可视树的两个WPF控件的相对Z顺序?

C# 如何比较属于同一逻辑/可视树的两个WPF控件的相对Z顺序?,c#,wpf,wpf-controls,C#,Wpf,Wpf Controls,是否可以比较两个WPF控件的相对Z顺序(哪个将绘制在顶部),而不管它们在逻辑/可视树结构中的关系以及使用的布局容器如何 我需要它来确定控件中可能被其他控件重叠的可见区域。我的计划是从控件几何图形开始,并与所有控件的几何图形相交,这些几何图形将使用组合几何图形(GeometryCombineMode属性设置为“排除”) 更新: 如果大家都感兴趣,我已经使用GDI32API来计算可见区域。 我昨晚遇到了类似的问题。我的目标是确定一个控件是否会在另一个控件之前绘制。我搜索了大约45分钟,但找不到AP

是否可以比较两个WPF控件的相对Z顺序(哪个将绘制在顶部),而不管它们在逻辑/可视树结构中的关系以及使用的布局容器如何

我需要它来确定控件中可能被其他控件重叠的可见区域。我的计划是从控件几何图形开始,并与所有控件的几何图形相交,这些几何图形将使用组合几何图形(GeometryCombineMode属性设置为“排除”)

更新: 如果大家都感兴趣,我已经使用GDI32API来计算可见区域。


我昨晚遇到了类似的问题。我的目标是确定一个控件是否会在另一个控件之前绘制。我搜索了大约45分钟,但找不到API提供的解决方案,所以我必须遍历可视化树,找出哪一个将绘制在顶部。所以,我想根据我的研究,我的答案是否定的,你不能在不看视觉树的情况下比较相对z顺序

如果您仍然需要,下面是我用来查找控件相对z顺序的代码(INFORTOF方法),它还考虑了手动设置控件的.ZOrder属性(适用于我的代码,但未经过彻底测试,如果控件的ZOrder属性设置为负值,则不起作用)

private bool informontof(框架元素c1、框架元素c2){
Panel root=FindWindowRoot(c1);//查找文档的根,假设c1和c2是同一文档的一部分
Assert(root!=null,“ui元素的根不是包含子元素的窗口或面板”);
int z1=Math.Max(Panel.GetZIndex(c1),GetDrawOrder(root,c1));
int z2=Math.Max(Panel.GetZIndex(c2),GetDrawOrder(root,c2));
返回z1>z2;
}
私有面板FindWindowRoot(FrameworkElement子级)
{
框架元素当前=子元素;
while(当前窗口==null)
{
当前=(FrameworkElement)VisualTreeHelper.GetParent(当前);
}
返回((窗口)当前)。内容为面板;
}
私有int GetDrawOrder(面板根,FrameworkElement针)
{
int结果=0;
框架元素当前=根;
Queue toSearch=新队列();
搜索排队(当前);
while(指针!=当前)
{
如果(当前为面板)
{
面板p=(面板)电流;
foreach(p.Children中的FrameworkElement FrameworkElement)
{
搜索队列(frameworkElement);
}
}
如果(当前为ContentControl)
{
ContentControl cc=(ContentControl)当前;
if(cc.Content as FrameworkElement!=null)
搜索队列(抄送内容作为框架元素);
}
current=toSearch.Dequeue();
结果++;
}
返回结果;
}

我使用了类似的方法来确定zOrder。另外,如果有人感兴趣,我已经使用gdi32区域来计算可见区域。
    [DllImport("gdi32.dll")]
    static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);

    [DllImport("gdi32.dll")]
    static extern int CombineRgn(IntPtr hrgnDest, IntPtr hrgnSrc1, IntPtr hrgnSrc2, int fnCombineMode);

    [DllImport("gdi32.dll")]
    static extern int GetRegionData(IntPtr hRgn, uint dwCount, IntPtr lpRgnData);

    [DllImport("gdi32.dll")]
    static extern bool SetRectRgn(IntPtr hRgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);

    [DllImport("gdi32.dll")]
    static extern bool DeleteObject(IntPtr hObject);
private bool InFrontOf(FrameworkElement c1, FrameworkElement c2){
    Panel root = FindWindowRoot(c1); // Find the root of the document, assumes that c1 and c2 are part of the same document
    Trace.Assert(root != null, "root of ui element is not a window or a panel that contains children");

    int z1 = Math.Max(Panel.GetZIndex(c1), GetDrawOrder(root, c1));
    int z2 = Math.Max(Panel.GetZIndex(c2), GetDrawOrder(root, c2));

    return z1 > z2;
}



private Panel FindWindowRoot(FrameworkElement child)
{
    FrameworkElement current = child;
    while(current as Window == null)
    {
        current = (FrameworkElement)VisualTreeHelper.GetParent(current); 
    }
    return ((Window)current).Content as Panel;
}

private int GetDrawOrder(Panel root, FrameworkElement needle)
{
    int result = 0;
    FrameworkElement current = root;
    Queue<FrameworkElement> toSearch = new Queue<FrameworkElement>();
    toSearch.Enqueue(current);
    while(needle != current)
    {
        if(current is Panel)
        {
            Panel p = (Panel) current;
            foreach (FrameworkElement frameworkElement in p.Children)
            {
                toSearch.Enqueue(frameworkElement);
            }
        }
        if (current is ContentControl)
        {
            ContentControl cc = (ContentControl)current;
            if(cc.Content as FrameworkElement != null)
                toSearch.Enqueue(cc.Content as FrameworkElement);
        }
        current = toSearch.Dequeue();
        result++;
    }
    return result;
}