简体   繁体   English

在WPF中使用另一个控件作为不透明蒙板?

[英]Use another control as an opacity mask in WPF?

I'm trying to use the OpacityMask property combined with a VisualBrush so that when you drag an image over another control (such as another image, rectangle, or any other control), the part of the image that is over the second control has a different opacity. 我正在尝试将OpacityMask属性与VisualBrush结合使用,以便当您将图像拖到另一个控件(例如另一个图像,矩形或任何其他控件)上时,第二个控件上方的图像部分具有不同的不透明度。 That is, the image has some non-zero base opacity, and any part of the image that is over another control has a different (again, non-zero) opacity. 也就是说,图像具有一些非零基础不透明度,并且图像中任何位于另一个控件上的部分具有不同的(再次,非零)不透明度。

Is this possible simply using VisualBrush and OpacityMask? 这可以简单地使用VisualBrush和OpacityMask吗? Or is a more complex approach required? 或者需要更复杂的方法?

Thanks! 谢谢!

Edit: I'm trying to make the image have some lower opacity (such as 0.5), and the part being dragged over the control have a higher opacity (such as 1.0). 编辑:我正在尝试使图像具有较低的不透明度(例如0.5),并且在控件上拖动的部分具有较高的不透明度(例如1.0)。 I originally left out this detail, which is important to the approach taken. 我最初忽略了这个细节,这对采取的方法很重要。

In addition to ima's answer, I have figured this out using an opacity mask. 除了ima的答案之外,我还使用不透明蒙版来解决这个问题。 I use the following code hooked into the LayoutUpdated event for the image. 我使用以下代码连接到图像的LayoutUpdated事件。

// Make a visual brush out of the masking control.
VisualBrush brush = new VisualBrush(maskingControl);
// Set desired opacity.
brush.Opacity = 1.0;
// Get the offset between the two controls.
Point offset = controlBeingMasked.TranslatePoint(new Point(0, 0), maskingControl);
// Determine the difference in scaling.
Point scale = new Point(maskingControl.ActualWidth / controlBeingMasked.ActualWidth, 
    maskingControl.ActualHeight / controlBeingMasked.ActualHeight);
TransformGroup group = new TransformGroup();
// Set the scale of the mask.
group.Children.Add(new ScaleTransform(scale.X, scale.Y, 0, 0));
// Translate the mask so that it always stays in place.
group.Children.Add(new TranslateTransform(-offset.X, -offset.Y));
// Rotate it by the reverse of the control, to keep it oriented correctly.
// (I am using a ScatterViewItem, which exposes an ActualOrientation property)
group.Children.Add(new RotateTransform(-controlBeingMasked.ActualOrientation, 0, 0));
brush.Transform = group;
controlBeingMasked.OpacityMask = brush;

If you want a desired base opacity, use two images; 如果您想要所需的基本不透明度,请使用两个图像; one that's always at the base opacity, and another that uses the opacity mask that sits on top of it. 一个始终处于基本不透明度的一个,另一个使用位于其顶部的不透明蒙板。 If you want the base opacity to be higher than the masked opacity, then it might be easier to use ima's approach. 如果您希望基本不透明度高于蒙版不透明度,那么使用ima的方法可能更容易。

One advantage of this solution as opposed to the maskless approach is that if the masking control moves, changes size, etc., this will automatically pick up the change without having to keep another control in sync with it. 与无掩模方法相反,该解决方案的一个优点是,如果掩蔽控制移动,改变大小等,这将自动获取改变而不必保持另一个控制与其同步。

Here's how it looks: 以下是它的外观:
(source: yfrog.com ) (来源: yfrog.com

  • No masks 没有面具
  • Define visual brush for the control 为控件定义可视刷
  • Paint shape right on top of the control with that brush 使用该画笔在控件顶部绘制形状
  • Drag image between the shape and the control 在形状和控件之间拖动图像
  • Set opacity of the brush to achieve desired effect 设置画笔的不透明度以达到所需效果

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM