WPF的类库现在锁死不让继承实现自定义的Brush,因为基类的brush含有抽象而且是internal的一些函数,像internal abstract System.Windows.Media.Composition.DUCE.ResourceHandle AddRefOnChannelCore(System.Windows.Media.Composition.DUCE.Channel channel),就没法继承实现,而且一般的DrawingBrush, ImageBrush都是sealed。而我这次需要一个相当于2维的GradientBrush一样的东西来实现传入一个颜色矩阵,画出一副ColorMap的东西。因为直接从brush继承设置想直接从imagesource继承都不可能,只好用MarkupExtension的方法绕:
using
System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;
using System.Windows.Media.Animation;
using System.ComponentModel;
[MarkupExtensionReturnType( typeof (Brush))]
class BilinearGradientBrushExtension:MarkupExtension,INotifyPropertyChanged
{
List < Color > colorMatrix = new List < Color > ();
int countX, countY;
private void OnPropertyChanged( string propertyName)
{
if ( this .PropertyChanged != null )
{
this .PropertyChanged( this , new PropertyChangedEventArgs(propertyName));
}
}
public List < Color > ColorMatrix
{
get { return colorMatrix; }
set { colorMatrix = value ; OnPropertyChanged( " ColorMatrix " ); }
}
public int CountY
{
get { return countY; }
set { countY = value; }
}
public int CountX
{
get { return countX; }
set { countX = value; }
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
int i = ColorMatrix.Count;
int [] pixelValues = GeneratePixelValues();
WriteableBitmap bmp = new WriteableBitmap(countX, countY, 96 , 96 , PixelFormats.Pbgra32, null );
bmp.WritePixels( new Int32Rect( 0 , 0 , countX, countY), pixelValues, pixelValues.Length, 0 );
ImageBrush brush = new ImageBrush(bmp);
return brush;
}
private int [] GeneratePixelValues()
{
int pixelCount = countX * countY;
int [] pixelValues = new int [pixelCount];
for ( int i = 0 ; i < countY; i ++ )
{
for ( int j = 0 ; j < countX; j ++ )
{
Color c = ColorMatrix[i * countY + j];
byte a = ( byte )c.A;
byte r = ( byte )c.R;
byte g = ( byte )c.G;
byte b = ( byte )c.B;
pixelValues[i * countY + j] = (a << 24 ) + (r << 16 ) + (g << 8 ) + b;
}
}
return pixelValues;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows;
using System.Windows.Media.Animation;
using System.ComponentModel;
[MarkupExtensionReturnType( typeof (Brush))]
class BilinearGradientBrushExtension:MarkupExtension,INotifyPropertyChanged
{
List < Color > colorMatrix = new List < Color > ();
int countX, countY;
private void OnPropertyChanged( string propertyName)
{
if ( this .PropertyChanged != null )
{
this .PropertyChanged( this , new PropertyChangedEventArgs(propertyName));
}
}
public List < Color > ColorMatrix
{
get { return colorMatrix; }
set { colorMatrix = value ; OnPropertyChanged( " ColorMatrix " ); }
}
public int CountY
{
get { return countY; }
set { countY = value; }
}
public int CountX
{
get { return countX; }
set { countX = value; }
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
int i = ColorMatrix.Count;
int [] pixelValues = GeneratePixelValues();
WriteableBitmap bmp = new WriteableBitmap(countX, countY, 96 , 96 , PixelFormats.Pbgra32, null );
bmp.WritePixels( new Int32Rect( 0 , 0 , countX, countY), pixelValues, pixelValues.Length, 0 );
ImageBrush brush = new ImageBrush(bmp);
return brush;
}
private int [] GeneratePixelValues()
{
int pixelCount = countX * countY;
int [] pixelValues = new int [pixelCount];
for ( int i = 0 ; i < countY; i ++ )
{
for ( int j = 0 ; j < countX; j ++ )
{
Color c = ColorMatrix[i * countY + j];
byte a = ( byte )c.A;
byte r = ( byte )c.R;
byte g = ( byte )c.G;
byte b = ( byte )c.B;
pixelValues[i * countY + j] = (a << 24 ) + (r << 16 ) + (g << 8 ) + b;
}
}
return pixelValues;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
对应的xaml:
<
l:BilinearGradientBrushExtension
x:Name
="contur"
CountX
="2"
CountY
="2"
>
< l:BilinearGradientBrushExtension .ColorMatrix >
< Color A ="100" R ="255" G ="0" B ="0" />
< Color A ="100" R ="0" G ="255" B ="0" />
< Color A ="100" R ="155" G ="155" B ="155" />
< Color A ="100" R ="0" G ="0" B ="255" />
</ l:BilinearGradientBrushExtension.ColorMatrix >
</ l:BilinearGradientBrushExtension >
< l:BilinearGradientBrushExtension .ColorMatrix >
< Color A ="100" R ="255" G ="0" B ="0" />
< Color A ="100" R ="0" G ="255" B ="0" />
< Color A ="100" R ="155" G ="155" B ="155" />
< Color A ="100" R ="0" G ="0" B ="255" />
</ l:BilinearGradientBrushExtension.ColorMatrix >
</ l:BilinearGradientBrushExtension >
产生的图片:
不过使用MarkupExtension的方法有个问题,就是产生的图像是静态的,颜色没办法在运行时改变,而且不能使用DependencyProperty,我试过INotifyProperty,会抛异常,暂时没有其他方法。