2009-08-04 61 views
0

我正在制作一个使用XAML创建PNG按钮的原型。基本思想是,可以从本地化的字符串生成漂亮的渐变图像按钮,而不是通过任何类型的图形部门创建它们。将XAML按钮渲染为PNG时的动态高度和宽度

我发现的最直接的例子实际上是构建一个C#程序集和call it from PHP。我将它转换为纯C#。这是我的基本工作原型的样子。

XAML文件看起来像:

<UserControl 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 
Width="640" Height="480"> 

<Grid x:Name="LayoutRoot"> 
    <Button HorizontalAlignment="Left" VerticalAlignment="Top" Content="Add To Cart" FontFamily="Arial" FontSize="11" Height="24" FontWeight="Bold" Margin="0,3,0,0"> 
     <Button.Background> 
      <LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> 
       <GradientStop Color="#FFF3F3F3" Offset="0"/> 
       <GradientStop Color="#FFEBEBEB" Offset="0.5"/> 
       <GradientStop Color="#FFDDDDDD" Offset="0.502"/> 
       <GradientStop Color="#FFCDCDCD" Offset="1"/> 
      </LinearGradientBrush> 
     </Button.Background> 
    </Button> 
</Grid> 

的Program.cs的样子:

class Program 
{ 
    static void Main(string[] args) 
    { 
     FileInfo xamlFile = new FileInfo("Button.xaml"); 
     var inputXaml = File.ReadAllText(xamlFile.FullName); 
     Thread pngCreationThread = new Thread((ThreadStart) delegate() 
      { 
       GenImageFromXaml(inputXaml); 
      }); 
     pngCreationThread.IsBackground = true; 
     pngCreationThread.SetApartmentState(ApartmentState.STA); 
     pngCreationThread.Start(); 
     pngCreationThread.Join(); 
    } 
    public static void GenImageFromXaml(string xaml) 
    { 
     var element = (FrameworkElement)XamlReader.Parse(xaml); 
     var pngBytes = GetPngImage(element); 

     using(BinaryWriter binWriter = 
     new BinaryWriter(File.Open(@"output.png", FileMode.Create))) 
     { 
      binWriter.Write(pngBytes); 
     } 
    } 
    private static byte[] GetPngImage(FrameworkElement element) 
    { 
     var size = new Size(element.Width, element.Height); 
     element.Measure(size); 
     element.Arrange(new Rect(size)); 
     var renderTarget = 
      new RenderTargetBitmap((int)element.RenderSize.Width, 
           (int)element.RenderSize.Height, 
           96, 96, 
           PixelFormats.Pbgra32); 
     var sourceBrush = new VisualBrush(element); 
     var drawingVisual = new DrawingVisual(); 
     using (DrawingContext drawingContext = drawingVisual.RenderOpen()) 
     { 
      drawingContext.DrawRectangle(
       sourceBrush, null, new Rect(
             new Point(0, 0), 
             new Point(element.RenderSize.Width, 
             element.RenderSize.Height))); 
     } 
     renderTarget.Render(drawingVisual); 
     var pngEncoder = new PngBitmapEncoder(); 
     pngEncoder.Frames.Add(BitmapFrame.Create(renderTarget)); 
     using (var outputStream = new MemoryStream()) 
     { 
      pngEncoder.Save(outputStream); 
      return outputStream.ToArray(); 
     } 
    } 
} 

我要的是一个可以作为模板与实际XAML文件换出按钮中的字符串。我的原型在基本级别上工作,从输入的XAML文件中渲染图像。

但是,XAML文件明确指定了高度和宽度。这将是一个问题,因为按钮本身的字符串是动态提供的,因为事先不会知道宽度,并且任何字体修改都会混淆它。

我正在寻找的是一种在运行时计算高度和宽度或基于文本字符串预先计算它们的直接方法。有任何想法吗?

回答

2

你可以尝试follwing

1不要在XAML中设置宽度和高度

2更换你测量/安排该电话:

​​3210

措施都将根据该DesiredSize财产在你通过它的大小上,这可能是你想要的大小。

3(不确定是否需要)将Grid(LayoutRoot)设置为Top/Left对齐方式,因为Grid默认采用所有可用大小,您不需要。

+0

我今天试试。我曾尝试将宽度和高度留下,但是(如你的第二点处理)尺寸计算抛出空指针。我认为必须有一种方法来衡量按钮占用的实际空间,看起来你的例子就是这样。 – 2009-08-04 13:12:39