Предположим, мне нужно установить маску непрозрачности для элемента управления WPF, которая выделяет его часть в точном положении (предположим, квадрат 50x50 в (50; 50) положении). Для этого я создаю DrawingGroup, содержащую 2 объекта GeometryDrawing: 1 полупрозрачный прямоугольник для всего фактического размера элемента управления и 1 непрозрачный прямоугольник для выделенной области. Затем я создаю DrawingBrush из этой DrawingGroup, присваиваю ему свойство Stretch значение None и задаю эту кисть как OpacityMask для элемента управления, который необходимо замаскировать.
Все это работает нормально, пока ничто не "торчит" за пределы указанного контроля. Но если элемент управления рисует что-то вне его границ, внешняя точка становится отправной точкой, из которой применяется маска непрозрачности (если кисть выровнена по этой стороне), и вся маска смещается на это расстояние, что приводит к неожиданному поведению.
Кажется, я не могу найти способ применить маску из границ элемента управления или, по крайней мере, получить фактические границы элемента управления (включая прилипающие части), чтобы я мог соответствующим образом настроить свою маску.
Любые идеи высоко ценятся!
Обновление: вот простой тестовый пример XAML и скриншоты, демонстрирующие проблему:
У нас есть 2 вложенных Границы и Холст в последнем с вышеупомянутым квадратом:
<Border Padding="20" Background="DarkGray" Width="240" Height="240">
<Border Background="LightBlue">
<Canvas>
<Rectangle Canvas.Left="50" Canvas.Top="50" Width="50" Height="50"
Stroke="Red" StrokeThickness="2"
Fill="White"
/>
</Canvas>
</Border>
</Border>
Вот как это выглядит:
(источник: ailon.org)
Теперь мы добавляем OpacityMask ко второй границе, чтобы каждая его часть, кроме нашего квадрата, была полупрозрачной:
<Border.OpacityMask>
<DrawingBrush Stretch="None" AlignmentX="Left" AlignmentY="Top">
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="#30000000">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,200,200" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="Black">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="50,50,50,50" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.OpacityMask>
Все выглядит как положено:
(источник: ailon.org)
И теперь мы добавляем к холсту линию, которая будет на 10 пикселей слева от нашей границы:
<Line X1="-10" Y1="150" X2="120" Y2="150"
Stroke="Red" StrokeThickness="2"
/>
И маска смещается на 10 пикселей влево:
(источник: ailon.org)
Обновление 2: В качестве обходного пути я добавляю смехотворно большой прозрачный прямоугольник за пределы границ и корректирую свою маску соответственно, но это действительно неприятный обходной путь.
Обновление 3: Примечание: холст с прямоугольником и линией приведен в качестве примера некоторого объекта, у которого есть что-то вне его границ. В контексте этого примера это следует рассматривать как своего рода черный ящик. Вы не можете изменить его свойства, чтобы решить общую проблему. Это было бы то же самое, что просто перемещать линию, чтобы она не торчала.