【问题标题】:Why Color.A = 255 on Color doesn't make it fully opaque?为什么 Color.A = 255 on Color 不能使它完全不透明?
【发布时间】:2014-06-29 20:42:06
【问题描述】:

我创建了一个显示色谱的自定义控件。 我正在重写 OnRender() 方法以使用颜色绘制控件。 由于某种原因,“计算”的颜色(R G B 值)具有一定的透明度,即使我将 Alpha 值 (A) 设置为最大可能值 (255)。 我创建了一个测试窗口,在背景上显示一些文本,我的控件和一个带有 LinearGradient 背景的边框,文本可以在我的控件后面看到,但在边框后面看不到,这清楚地表明我的控件设置了一些透明度. 即使我设置 A=255,为什么我的计算颜色具有透明度的任何想法? 我很感激任何建议。 谢谢!

这是我的 Window.xaml 和我的控件的 .cs:

MainWindow.xaml

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Views="clr-namespace:ColorBarTest.Views"
        x:Class="ColorBarTest.MainWindow"
        Title="MainWindow" Height="671.622" Width="720.102">

    <Grid>
        <TextBlock Margin="0,66,0,558" HorizontalAlignment="Left" Width="218"><Run Text="TESTING THE OPACITY O"/><Run Text="F C"/><Run Text="OLOR BAR"/></TextBlock>
        <Views:TestRender Margin="0,65,671,0" />
        <Border Margin="100,65,671,0"/>
        <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="577" Margin="105,65,0,0" VerticalAlignment="Top" Width="42">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="Red" Offset="1"/>
                    <GradientStop Color="Magenta"/>
                </LinearGradientBrush>
            </Border.Background>
        </Border>
    </Grid>
</Window>

TestRender.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ColorBarTest.Views
{
    public class TestRender : Control
    {
        private int Max = 99;
        private int Min = 1;

        private Color StartColor = Colors.Red;

        private Color EndColor = Colors.Fuchsia;

        static TestRender()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TestRender), new FrameworkPropertyMetadata(typeof(TestRender)));
        }

        protected override void OnRender(DrawingContext drawingContext)
        {

            for (double pixel = 0; pixel < ActualHeight; pixel++)
            {
                var value = ConvertYPixelToColorHandleValue(pixel);
                var color = CalculateRGBA(value);
                var brush = new SolidColorBrush(color);
                brush.Opacity = 1.0f;
                var pen = new Pen(brush, 1.0f);
                drawingContext.DrawLine(pen, new Point(0, pixel), new Point(ActualWidth, pixel));
                //Console.WriteLine("Value: {0}", value);
            }
            var pen2 = new Pen(new SolidColorBrush(Colors.Red), 5.0d);
            var pen3 = new Pen(new SolidColorBrush(Colors.Fuchsia), 5.0d);
            drawingContext.DrawLine(pen3, new Point(0, 0), new Point(ActualWidth, 0));
            drawingContext.DrawLine(pen2, new Point(0, ActualHeight), new Point(ActualWidth, ActualHeight));

        }

        private float ConvertYPixelToColorHandleValue(double tickDrawY)
        {
            var pixelPercent = ((tickDrawY) / (float)ActualHeight);

            return (Max - (float)(pixelPercent * (Max - Min)));
        }


        public Color CalculateRGBA(double value)
        {
            var rate = (float)((value - Min) / (Max - Min));
            float posRate = rate - 1;
            // Interpolate the color, there will be a HSV interpolation also
            return RgbLinearInterpolate(posRate);
        }

        public Color RgbLinearInterpolate(double rate)
        {
            var nr = 1.0 - rate;
            var r = (byte)((nr * StartColor.R) + (rate * EndColor.R));
            var g = (byte)((nr * StartColor.G) + (rate * EndColor.G));
            var b = (byte)((nr * StartColor.B) + (rate * EndColor.B));

            return new Color { R = r, G = g, B = b, A = 255 };
        }
    }
}

看起来是这样的:

【问题讨论】:

  • 将自定义控件包裹在边框中会发生什么?
  • 只是猜测,但像你这样用 1 像素的笔逐行绘制可能会出错。
  • 我不认为 Alpha 通道像那个人那样工作,你设置的百分比从 0 到 1,1 是实心的,0 是不透明的,例如 0.5 是半不透明的。尝试 0 而不是 255 amigo。
  • @ChrisW。来自Color.AThe sRGB alpha channel value of the color, a value between 0 and 255. 0 是完全透明的,255 是完全不透明的。不要与例如 Opacity 混淆。一个画笔,它是一个介于 0 和 1 之间的值。
  • @XAMlMAX - 感谢您的回复。我将控件包裹在 Border 中,它仍然是透明的。

标签: c# wpf xaml colors


【解决方案1】:

在 OnRender 的顶部,添加以下内容:

this.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);

或者,将您的 xaml 更改为:

<Views:TestRender Margin="0,65,671,0" RenderOptions.EdgeMode="Aliased" />

或者,您可以尝试绘制重叠的矩形:

//drawingContext.DrawLine(pen, new Point(0, pixel), new Point(ActualWidth, pixel));
drawingContext.DrawRectangle(brush, pen, new Rect(new Point(0, pixel - 0.25), new Point(ActualWidth, pixel + 0.25)));

【讨论】:

  • +1。作为旁注,OP 可以使用 Snoop 来查看问题(在控件上放大)。
  • @franssu - 好主意。顺便说一句,您的评论让我认为是抗锯齿使文本能够“窥视”。为您的原始评论 +1!
  • J.H.非常感谢!那行得通!感谢@franssu 以及您的 cmets!
猜你喜欢
  • 2012-02-05
  • 2014-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-13
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多