- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我希望在我的 WPF 应用程序中有半透明的表单/弹出窗口,而我所追求的正是在 Windows 10 中实现的相同类型的航空主题深色玻璃状模糊,如下所示:
到目前为止,我只能在网上找到资源来解释如何将这种模糊效果应用于容器内部的所有内容,这与我所追求的完全相反,或者应用相同的有点模糊了表单/弹出窗口后面的所有内容。
我知道 SetWindowCompositionAttribute(此处显示:Native Aero Blur without Glass Effect on Borderless WPF Window 并在此处进一步解释:http://withinrafael.com/adding-the-aero-glass-blur-to-your-windows-10-apps/)
但这些说明仅将效果添加到应用程序的整个窗口,这并不是我所追求的。
我想将效果应用到我的应用程序中的选定元素(例如边框);
... 就像这样。
我该怎么做呢?
最佳答案
希望现在回答您的问题还为时不晚。在我看来,获得您希望的结果的解决方案由 ShaderEffect 表示。类。
我的方法有一些局限性,但我想它可以改进以解决这些问题。
首先让我们看看结果:
我的想法是创建一个自定义的 ShaderEffect
,我称之为 BlurRectEffect
。要了解此类,您可以阅读 this很好的教程。
public class RectBlurEffect : ShaderEffect
{
private static PixelShader pixelShader = new PixelShader();
private static PropertyInfo propertyInfo;
public static readonly DependencyProperty InputProperty =
ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(RectBlurEffect), 0);
public static readonly DependencyProperty UpLeftCornerProperty =
DependencyProperty.Register("UpLeftCorner", typeof(Point), typeof(RectBlurEffect),
new UIPropertyMetadata(new Point(0, 0), PixelShaderConstantCallback(0)));
public static readonly DependencyProperty LowRightCornerProperty =
DependencyProperty.Register("LowRightCorner", typeof(Point), typeof(RectBlurEffect),
new UIPropertyMetadata(new Point(1, 1), PixelShaderConstantCallback(1)));
public static readonly DependencyProperty FrameworkElementProperty =
DependencyProperty.Register("FrameworkElement", typeof(FrameworkElement), typeof(RectBlurEffect),
new PropertyMetadata(null, OnFrameworkElementPropertyChanged));
static RectBlurEffect()
{
pixelShader.UriSource = Global.MakePackUri("RectBlurEffect.ps");
propertyInfo = typeof(RectBlurEffect).GetProperty("InheritanceContext",
BindingFlags.Instance | BindingFlags.NonPublic);
}
public RectBlurEffect()
{
PixelShader = pixelShader;
UpdateShaderValue(InputProperty);
UpdateShaderValue(UpLeftCornerProperty);
UpdateShaderValue(LowRightCornerProperty);
}
public Brush Input
{
get { return (Brush)GetValue(InputProperty); }
set { SetValue(InputProperty, value); }
}
public Point UpLeftCorner
{
get { return (Point)GetValue(UpLeftCornerProperty); }
set { SetValue(UpLeftCornerProperty, value); }
}
public Point LowRightCorner
{
get { return (Point)GetValue(LowRightCornerProperty); }
set { SetValue(LowRightCornerProperty, value); }
}
public FrameworkElement FrameworkElement
{
get { return (FrameworkElement)GetValue(FrameworkElementProperty); }
set { SetValue(FrameworkElementProperty, value); }
}
private FrameworkElement GetInheritanceContext()
{
return propertyInfo.GetValue(this, null) as FrameworkElement;
}
private void UpdateEffect(object sender, EventArgs args)
{
Rect underRectangle;
Rect overRectangle;
Rect intersect;
FrameworkElement under = GetInheritanceContext();
FrameworkElement over = this.FrameworkElement;
Point origin = under.PointToScreen(new Point(0, 0));
underRectangle = new Rect(origin.X, origin.Y, under.ActualWidth, under.ActualHeight);
origin = over.PointToScreen(new Point(0, 0));
overRectangle = new Rect(origin.X, origin.Y, over.ActualWidth, over.ActualHeight);
intersect = Rect.Intersect(overRectangle, underRectangle);
if (intersect.IsEmpty)
{
UpLeftCorner = new Point(0, 0);
LowRightCorner = new Point(0, 0);
}
else
{
origin = new Point(intersect.X, intersect.Y);
origin = under.PointFromScreen(origin);
UpLeftCorner = new Point(origin.X / under.ActualWidth,
origin.Y / under.ActualHeight);
LowRightCorner = new Point(UpLeftCorner.X + (intersect.Width / under.ActualWidth),
UpLeftCorner.Y + (intersect.Height / under.ActualHeight));
}
}
private static void OnFrameworkElementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
RectBlurEffect rectBlurEffect = (RectBlurEffect)d;
FrameworkElement frameworkElement = args.OldValue as FrameworkElement;
if (frameworkElement != null)
{
frameworkElement.LayoutUpdated -= rectBlurEffect.UpdateEffect;
}
frameworkElement = args.NewValue as FrameworkElement;
if (frameworkElement != null)
{
frameworkElement.LayoutUpdated += rectBlurEffect.UpdateEffect;
}
}
}
此类计算受影响控件和重叠控件之间的交集。然后它将这些信息发送到所谓的“像素着色器”文件(一个 .fx 文件,它将被编译成一个 .ps 文件)。
现在我们需要创建 RectBlueEffect.fx 文件。它使用 HLSL - (i.e. High Level Shading Language) .这里是它的内容:
sampler2D rectBlurEffect : register(S0);
float2 upperLeftCorner : register(C0);
float2 lowerRightCorner : register(C1);
float Angle : register(C2);
float BlurAmount : register(C3);
float PI = 3.14159265358979323846;
float EPSILON = 0.0001;
float ComputeGaussian(float n)
{
float theta = 2.0f + EPSILON; //float.Epsilon;
return theta = (float)((1.0 / sqrt(2 * PI * theta)) *
exp(-(n * n) / (2 * theta * theta)));
}
float4 gaussianblur(float2 texCoord: TEXCOORD0) : COLOR
{
float SampleWeights[7];
float2 SampleOffsets[15];
// The first sample always has a zero offset.
float2 initer = { 0.0f, 0.0f };
SampleWeights[0] = ComputeGaussian(0);
SampleOffsets[0] = initer;
// Maintain a sum of all the weighting values.
float totalWeights = SampleWeights[0];
// Add pairs of additional sample taps, positioned
// along a line in both directions from the center.
for (int i = 0; i < 7 / 2; i++)
{
// Store weights for the positive and negative taps.
float weight = ComputeGaussian(i + 1);
SampleWeights[i * 2 + 1] = weight;
SampleWeights[i * 2 + 2] = weight;
totalWeights += weight * 2;
float sampleOffset = i * 2 + 1.5f;
float2 delta = { (1.0f / 512), 0 };
delta = delta * sampleOffset;
// Store texture coordinate offsets for the positive and negative taps.
SampleOffsets[i * 2 + 1] = delta;
SampleOffsets[i * 2 + 2] = -delta;
}
// Normalize the list of sample weightings, so they will always sum to one.
for (int j = 0; j < 7; j++)
{
SampleWeights[j] /= totalWeights;
}
float4 color = 0.0f;
for (int k = 0; k < 7; k++)
{
color += tex2D(rectBlurEffect,
texCoord + SampleOffsets[k]) * SampleWeights[k];
}
return color;
}
float4 directionalBlur(float2 uv : TEXCOORD) : COLOR
{
float4 c = 0;
float rad = Angle * 0.0174533f;
float xOffset = cos(rad);
float yOffset = sin(rad);
for (int i = 0; i < 12; i++)
{
uv.x = uv.x - BlurAmount * xOffset;
uv.y = uv.y - BlurAmount * yOffset;
c += tex2D(rectBlurEffect, uv);
}
c /= 12;
return c;
}
float4 main(float2 uv : TEXCOORD) : COLOR
{
if (uv.x < upperLeftCorner.x || uv.y < upperLeftCorner.y || uv.x > lowerRightCorner.x || uv.y > lowerRightCorner.y)
{
return tex2D(rectBlurEffect, uv);
}
return gaussianblur(uv);
}
如您所见,如果像素位于矩形之外(两个控件区域之间的交叉点),则不会应用任何效果。否则 main
方法使用效果(即高斯模糊)。
你可以找到here我称为 gaussianblur
的方法的实现。看看最后的答案。
现在我们必须编译 RectBlueEffect.fx
文件。您可以在前面的链接(教程)或 here 中找到一些说明。 .
XAML 是我解决方案的最后一部分:
<Grid>
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<Border Background="Brown" BorderThickness="0" Name="tb">
<TextBlock Text="Hello World!" Margin="4" Padding="10"
FontSize="30" FontWeight="Bold" Foreground="Yellow"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
TextAlignment="Center" />
<Border.Effect>
<local:RectBlurEffect FrameworkElement="{Binding ElementName=Border, Mode=OneTime}" />
</Border.Effect>
</Border>
<TextBlock Background="Khaki" Text="I should be partially blurred!" Margin="4" Padding="10"
Foreground="DarkGreen" FontSize="30" TextWrapping="Wrap" FontFamily="Cambria"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
TextAlignment="Center">
<TextBlock.Effect>
<local:RectBlurEffect FrameworkElement="{Binding ElementName=Border, Mode=OneTime}" />
</TextBlock.Effect>
</TextBlock>
</StackPanel>
<Border Name="Border" Width="200" Height="260" BorderThickness="0"
Background="Black" Opacity=".6" Panel.ZIndex="20">
<TextBlock Text="Pretend I'm a border dumped over a grid" TextWrapping="Wrap"
HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="16"
Foreground="AntiqueWhite" Background="Transparent"
Margin="8" />
</Border>
</Grid>
如您所料,我的解决方案只允许重叠矩形(或正方形),但不适用于椭圆、圆形或不规则多边形。当然,一切都取决于您在 .fx 文件中编写的 HLSL 代码。
关于c# - 对所选容器后面的所有内容应用模糊,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33570639/
我正在尝试用 Swift 编写这段 JavaScript 代码:k_combinations 到目前为止,我在 Swift 中有这个: import Foundation import Cocoa e
我是一名优秀的程序员,十分优秀!