组合纯色笔刷

发布于 2024-07-22 09:19:32 字数 143 浏览 9 评论 0 原文

有没有办法创建一种由 2 个纯色画笔混合而成的“纯色画笔”?

对于背景颜色,我希望能够使用对其他画笔的 DynamicReference。 而另一种颜色(前面)可能是具有不透明度的静态颜色。

如果这确实没有道理,请随时要求澄清!

Is there a way to create a kind of "solidcolorbrush" that is a mixture of 2 solidcolor brushes?

For the back color, i would like to be able to use a DynamicReference to some other brush. While the other color (in the front) could be a static color with opacity.

Feel free to ask for clarification if this doesnt really make sence!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

〆凄凉。 2024-07-29 09:19:32

我遇到了同样的问题。 我通常只使用一个 xaml 来表示基本的深色、基本的灯光,然后使用一个 xaml 来表示每种颜色(蓝色、红色等)。 口音是稍微透视的,当选择较暗的主题和较暗的背景时,它会变暗。

当创建具有辅助强调色的主题以在应用程序中具有更多对比度时(例如,选择浅色主题时为灰色,选择深色主题时为强调色),我需要用两种颜色构建画笔,否则我将不得不创建每种颜色都有一个深色和浅色主题。

我使用的是:

<DrawingBrush x:Key="SecondaryAccentColorBrush" Viewport="0,0,1,1" TileMode="Tile">
    <DrawingBrush.Drawing>
        <DrawingGroup>
            <GeometryDrawing>
                <GeometryDrawing.Geometry>
                    <RectangleGeometry Rect="0,0,1,1" />
                </GeometryDrawing.Geometry>
                <GeometryDrawing.Brush>
                    <SolidColorBrush Color="{DynamicResource AccentColor}"/>
                </GeometryDrawing.Brush>
            </GeometryDrawing>
            <GeometryDrawing>
                <GeometryDrawing.Geometry>
                    <RectangleGeometry Rect="0,0,1,1" />
                </GeometryDrawing.Geometry>
                <GeometryDrawing.Brush>
                    <SolidColorBrush Color="{DynamicResource Gray10}"/>
                </GeometryDrawing.Brush>
            </GeometryDrawing>
        </DrawingGroup>
    </DrawingBrush.Drawing>
</DrawingBrush>

当主题切换时,“Gray10”的 alpha 在 00 和 FF 之间切换,因此画笔显示灰色或强调色。

I ran into the same problem. I normally just use one xaml each for the basic darks, the basic lights, and then one for each colour accent (blue, red etc). The accent is slightly lookthrough which makes it darker when then darker theme is selected with a darker background.

When creating a theme with a secondary accent colour to have more contrast in the app (for example gray when light theme is selected, accent colour when dark theme), I needed to construct a brush out of two colours as otherwise I would have to create a dark and light theme for each colour.

Here is what I use:

<DrawingBrush x:Key="SecondaryAccentColorBrush" Viewport="0,0,1,1" TileMode="Tile">
    <DrawingBrush.Drawing>
        <DrawingGroup>
            <GeometryDrawing>
                <GeometryDrawing.Geometry>
                    <RectangleGeometry Rect="0,0,1,1" />
                </GeometryDrawing.Geometry>
                <GeometryDrawing.Brush>
                    <SolidColorBrush Color="{DynamicResource AccentColor}"/>
                </GeometryDrawing.Brush>
            </GeometryDrawing>
            <GeometryDrawing>
                <GeometryDrawing.Geometry>
                    <RectangleGeometry Rect="0,0,1,1" />
                </GeometryDrawing.Geometry>
                <GeometryDrawing.Brush>
                    <SolidColorBrush Color="{DynamicResource Gray10}"/>
                </GeometryDrawing.Brush>
            </GeometryDrawing>
        </DrawingGroup>
    </DrawingBrush.Drawing>
</DrawingBrush>

When the theme is switched, the alpha of "Gray10" switches between 00 and FF, thus the brush shows either gray or the accent colour.

梦回旧景 2024-07-29 09:19:32

遗憾的是,WPF 中不支持自定义画笔(画笔类型被标记为“内部”且无法继承),因此无法像普通 SolidColorBrush 一样创建由两个画笔混合而成的画笔,并且可以从 XAML 使用该画笔。

作为解决方法,您可以使用 MarkupExtension 来模拟自定义画笔的行为,这允许您使用 XAML 语法并提供自定义值,从而允许我们使用内置的 SolidColorBrush(无需自定义画笔)设置为混合两种颜色时获得的值:

/// <summary>
/// Markup extension to mix two SolidColorBrushes together to produce a new SolidColorBrush.
/// </summary>
[MarkupExtensionReturnType(typeof(SolidColorBrush))]
public class MixedColorBrush : MarkupExtension, INotifyPropertyChanged
{
    /// <summary>
    /// The foreground mix color; defaults to white.  
    /// If not changed, the result will always be white.
    /// </summary>
    private SolidColorBrush foreground = Brushes.White;

    /// <summary>
    /// The background mix color; defaults to black.  
    /// If not set, the result will be the foreground color.
    /// </summary>
    private SolidColorBrush background = Brushes.Black;

    /// <summary>
    /// PropertyChanged event for WPF binding.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Gets or sets the foreground mix color.
    /// </summary>
    public SolidColorBrush Foreground
    {
        get 
        { 
            return this.foreground; 
        }
        set 
        { 
            this.foreground = value; 
            this.NotifyPropertyChanged("Foreground"); 
        }
    }

    /// <summary>
    /// Gets or sets the background mix color.
    /// </summary>
    public SolidColorBrush Background
    {
        get 
        { 
            return this.background; 
        }
        set 
        { 
            this.background = value; 
            this.NotifyPropertyChanged("Background"); 
        }
    }

    /// <summary>
    /// Returns a SolidColorBrush that is set as the value of the 
    /// target property for this markup extension.
    /// </summary>
    /// <param name="serviceProvider">Object that can provide services for the markup extension.</param>
    /// <returns>The object value to set on the property where the extension is applied.</returns>
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (this.foreground != null && this.background != null)
        {
            // Create a new brush as a composite of the old ones
            // This does simple non-perceptual additive color, e.g 
            // blue + red = magenta, but you can swap in a different
            // algorithm to do subtractive color (red + yellow = orange)
            return new SolidColorBrush(this.foreground.Color + this.background.Color);
        }

        // If either of the brushes was set to null, return an empty (white) brush.
        return new SolidColorBrush();
    }

    /// <summary>
    /// Raise the property changed event.
    /// </summary>
    /// <param name="propertyName">Name of the property which has changed.</param>
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

然后可以像使用普通画笔一样从 XAML 使用该值:

<Grid>
    <Grid.Background>
        <local:MixedColorBrush Foreground="Blue" Background="Red"/>
    </Grid.Background>
</Grid>

或者通过使用标记扩展语法:

<Grid Background="{local:MixedColorBrush Foreground=Blue, Background=Red}">

此方法的缺点是您无法使用 DynamicResource 或 StaticResource 引用将值绑定到其他颜色您的应用程序中的资源。 MarkupExtension 不是 DependencyObject,资源绑定仅适用于 DependencyObject; 内置画笔是 DependencyObjects,这就是绑定适用于传统画笔的原因。

Unfortunately, custom brushes are not supported in WPF (the brush types are marked 'internal' and cannot be inherited from), so creating a brush that is a mixture of two brushes that can be used from XAML like a normal SolidColorBrush is not possible.

As a workaround, you could use a MarkupExtension to simulate the behaviour of a custom brush, which allows you to use XAML syntax and provide a custom value, which allows us to use the built-in SolidColorBrush (no custom brush necessary) set to the value you get when mixing two colors:

/// <summary>
/// Markup extension to mix two SolidColorBrushes together to produce a new SolidColorBrush.
/// </summary>
[MarkupExtensionReturnType(typeof(SolidColorBrush))]
public class MixedColorBrush : MarkupExtension, INotifyPropertyChanged
{
    /// <summary>
    /// The foreground mix color; defaults to white.  
    /// If not changed, the result will always be white.
    /// </summary>
    private SolidColorBrush foreground = Brushes.White;

    /// <summary>
    /// The background mix color; defaults to black.  
    /// If not set, the result will be the foreground color.
    /// </summary>
    private SolidColorBrush background = Brushes.Black;

    /// <summary>
    /// PropertyChanged event for WPF binding.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Gets or sets the foreground mix color.
    /// </summary>
    public SolidColorBrush Foreground
    {
        get 
        { 
            return this.foreground; 
        }
        set 
        { 
            this.foreground = value; 
            this.NotifyPropertyChanged("Foreground"); 
        }
    }

    /// <summary>
    /// Gets or sets the background mix color.
    /// </summary>
    public SolidColorBrush Background
    {
        get 
        { 
            return this.background; 
        }
        set 
        { 
            this.background = value; 
            this.NotifyPropertyChanged("Background"); 
        }
    }

    /// <summary>
    /// Returns a SolidColorBrush that is set as the value of the 
    /// target property for this markup extension.
    /// </summary>
    /// <param name="serviceProvider">Object that can provide services for the markup extension.</param>
    /// <returns>The object value to set on the property where the extension is applied.</returns>
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (this.foreground != null && this.background != null)
        {
            // Create a new brush as a composite of the old ones
            // This does simple non-perceptual additive color, e.g 
            // blue + red = magenta, but you can swap in a different
            // algorithm to do subtractive color (red + yellow = orange)
            return new SolidColorBrush(this.foreground.Color + this.background.Color);
        }

        // If either of the brushes was set to null, return an empty (white) brush.
        return new SolidColorBrush();
    }

    /// <summary>
    /// Raise the property changed event.
    /// </summary>
    /// <param name="propertyName">Name of the property which has changed.</param>
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Which can then be used from XAML as you would a normal brush:

<Grid>
    <Grid.Background>
        <local:MixedColorBrush Foreground="Blue" Background="Red"/>
    </Grid.Background>
</Grid>

Or by using the markup extension syntax:

<Grid Background="{local:MixedColorBrush Foreground=Blue, Background=Red}">

The downside to this approach is that you cannot use DynamicResource or StaticResource references to bind the values to other resources in your application. MarkupExtension is not a DependencyObject, and resource binding only works on DependencyObjects; the built-in Brushes are DependencyObjects, which is why binding works with traditional brushes.

冬天旳寂寞 2024-07-29 09:19:32

从前景和背景画笔中获取颜色,将它们混合,然后根据生成的颜色创建新的画笔。

C# 中的示例:

Color foreground = foregroundBrush.Color;
Color background = backgroundBrush.Color;

int opacity = 25;

int r = (opacity * (foreground.R - background.R) / 100) + background.R;
int g = (opacity * (foreground.G - background.G) / 100) + background.G;
int b = (opacity * (foreground.B - background.B) / 100) + background.B;

SolidColorBrush mixedBrush = new SolidColorBrush(Color.FromArgb(r, g, b));

Get the colors from the foreground and background brushes, mix them, and create a new brush from the resulting color.

Example in C#:

Color foreground = foregroundBrush.Color;
Color background = backgroundBrush.Color;

int opacity = 25;

int r = (opacity * (foreground.R - background.R) / 100) + background.R;
int g = (opacity * (foreground.G - background.G) / 100) + background.G;
int b = (opacity * (foreground.B - background.B) / 100) + background.B;

SolidColorBrush mixedBrush = new SolidColorBrush(Color.FromArgb(r, g, b));
猥︴琐丶欲为 2024-07-29 09:19:32

一种简单的方法(但可能没有优化),
创建 LinearGradientBrush 两种颜色在重复模式下的端点等于起点:

<LinearGradientBrush SpreadMethod="Repeat" EndPoint="0,0">
                                <GradientStop Color="Red" Offset="0" />
                                <GradientStop Color="Yellow" Offset="1" />
                            </LinearGradientBrush>

这个为您提供橙色画笔。

One easy way to do it (but probably not optimized),
create a LinearGradientBrush of the two colors in repeat mode with Endpoint equals to start point:

<LinearGradientBrush SpreadMethod="Repeat" EndPoint="0,0">
                                <GradientStop Color="Red" Offset="0" />
                                <GradientStop Color="Yellow" Offset="1" />
                            </LinearGradientBrush>

This one gives you an Orange brush.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文