如何在装饰器下为控件赋予玻璃外观



当一个装饰器放在windows 10用户控件上时,我正试图"模糊"它。

更确切地说,我在wpf用户窗口中有一个数据网格控件。选择数据网格中的单元格后,将在数据网格控件上创建一个编辑装饰器。

public DataGridAnnotationAdorner(DataGrid adornedDataGrid, IVisit visit, DateTime TableDate)
: base(adornedDataGrid)
{
Control = new DataGridAnnotationControl(visit, TableDate);
AddLogicalChild(Control);
AddVisualChild(Control);
Loaded += DataGridAnnotationAdorner_Loaded;    
}
private void DataGridAnnotationAdorner_Loaded(object sender, RoutedEventArgs e)
{
EnableBlur(AdornedElement);
}

加载的事件然后调用(相当标准的(Blurr/glass效果方法:

internal void EnableBlur(UIElement dataGrid)
{
HwndSource source = (HwndSource)PresentationSource.FromVisual(dataGrid);
IntPtr hwnd = source.Handle;
var accent = new AccentPolicy();
accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND;
var accentStructSize = Marshal.SizeOf(accent);
var accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
var data = new WindowCompositionAttributeData();
data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY;
data.SizeOfData = accentStructSize;
data.Data = accentPtr;
SetWindowCompositionAttribute(hwnd, ref data);
Marshal.FreeHGlobal(accentPtr);
}

未报告错误。。。。但这是行不通的。

那么,我如何给装饰器下的控件一个"玻璃"外观呢?

TIA-

我不确定我能给你一个完整的解决方案,但我至少可以解释为什么你的尝试不起作用,也许可以为你指明正确的方向。

在WinForms(我认为还有C++(中,每个控件都有自己的"迷你窗口"。我的意思是,操作系统赋予每个控件自己的"句柄",操作系统将它们视为屏幕上的单个实体。WPF不同,窗口中"单独控件"的幻觉是由WPF框架创建的。据操作系统所知,只有一个实体:Window和所有其他逻辑都由WPF内部处理。不过,这只是大多数是真的,我稍后会提到。

我之所以提到这一点,是因为您的代码行PresentationSource.FromVisual(dataGrid)将为您提供承载DataGridWindow的句柄,而不是DataGrid本身独有的句柄(因为DataGrid没有句柄(。因此,使用该句柄所做的所有其他操作实际上都是针对整个WPFWindow的。

WPFWindow内部的所有呈现都由WPF框架(加上您的代码(内部处理,而不是由操作系统直接处理(如WinForms和C++(,因此使用告诉操作系统如何呈现某些内容的本地方法无法在Window内部的特定元素上工作。

在我看来,有两种方法可以用来创造这种效果:

  • 你可以尝试在WPF中重现"玻璃般"的效果。这会涉及重新创建或掌握使用的任何算法在视觉上扭曲一个区域以产生这种效果,然后以某种方式将其实现为控件。我真的不知道去哪里从不仅仅是谷歌开始。

  • 您可以尝试利用有自己句柄的其他WPF元素。

    • 我所知道的有自己句柄的两个主要WPF元素是WindowPopup。你可能可以创建一个,并将其定位在你需要的地方,就像你目前对你的爱人所做的那样。不过,这会很棘手,因为这些元素实际上是在生成它们的Window之外的,并且没有真正链接到它。因此,当你在桌面上移动主Window时,Popup或子Window不会随之移动。你还可以在WPF窗口和你创建的弹出窗口之间拖动其他窗口(但不确定(。

    • 在这个标题下可能还有另一种可能性,那就是WindowsFormsHost控件。这是一个WPF控件,在WPF窗口中承载WinForms控件。内部托管的WinForms控件可能由操作系统提供了自己的句柄(因为WinForms就是这样操作的(。这可能是你最好的选择,但我从未尝试过,我不知道WindowsFormsHost将如何与它周围或下面的其他元素交互。因此,它也可能根本不适合你的需要。

祝你好运。

最新更新