Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create vector images for WPF

Tags:

wpf

I want to use vector images in my WPF-application (for buttons and menus). How do I do that? Which tools should I use? Can someone show my a complete example?

like image 294
PEK Avatar asked Feb 08 '15 19:02

PEK


People also ask

Does WPF support SVG?

Supported SVG ElementsThe WPF SVG render engine supports the following SVG elements: Path - <path>


2 Answers

If you've got VS2013, you should have Blend. If not, you can add it from Add/Remove Programs, by modifying your Studio installation and checking the box.

Once you've got Blend, you can build vector images using the slightly too basic tools it provides; but more useful is its ability to import Adobe Illustrator files. This is still the benchmark vector graphics application to work in. This is great if you have a designer to build the assets, or have the skills to do that yourself.

If you need something between the basics of Blend and the all-singing Illustrator, Expression Design is a decent enough option (as already mentioned by @pek).

like image 75
kidshaw Avatar answered Sep 20 '22 14:09

kidshaw


Tools to create XAML vector images

Probably the best application to create XAML vector images is Microsoft Expression Design. It’s a free tool that could be downloaded from https://www.microsoft.com/en-gb/download/details.aspx?id=36180

When you have installed Expression Design, launch it and select Edit -> Options -> Clipboards (XAML). Change Clipboard format to XAML WPF Resource Dictionary. Also change Group By to Document (otherwise each layer will be an image).

Edit your image in Expression Design. When you are done, select everything and open the Edit menu and then Copy XAML. Paste this in appropriate XAML-file. You see in the example below how it should look like. One thing to note is that you need to change DrawingImage tag to DrawingBrush.

When you are drawing the image set the document size to the size you want in your WPF-application (like 32x32 pixels). It not necessary but make the work easier. Before copy the image to XAML you probably want to make a transparent rectangle that has the same size as the document (otherwise the margins could be wrong). Or you could add this manually in the drawing group children:

<GeometryDrawing Brush="#00FFFFFF" Geometry="M 0,0L 32,0L 32,32L 0,32L 0,0 Z " />

If you are using Inkscape

Inkscape has support to generate XAML-files. However - this is probably not the format you want! WPF has two different ways to handle graphics in XAML – shapes and geometries. You can find more details about this here: http://www.intertech.com/Blog/WPF-Shapes-vs-WPF-Geometries/.

But in short shapes has support for inputs, while geometries is just pure drawing and therefor more lightweight.

Inkscape generate files in shape-format, which is good for some cases but not for images that should be used in buttons and similar. So what you want is to get your images into Expression Design. You could do that by saving your image as a PDF-file, change the file extension to AI and then in Expression Design use File, Import Adobe Illustrator File. Using EPS is another option.

Most things could be imported to Expression Design. But it might be some issues with borders for instance. When you have got what you want to Expression Design it’s probably better to do all the work in there. If needed you could export your images to SVG which could be used in Inkscape, that normally works without any problems.

Example

When you have created XAML-code for the image it’s then quite straight forward. Below is an example where a vector image is used on a menu and two button.

If you want to draw a very thin line (1 pixel), you may want to add RenderOptions.EdgeMode="Aliased" and SnapsToDevicePixels="True" to the attributes to the control that is drawing the image.

Another thing to have in mind is what to do when a button is disabled. In the example below the image looks the same no matter if the button is enabled or not (this is true for ordinary bitmaps too). Changing the opacity to 50% is one approach that looks quite OK. Converting it grey scale is harder but there is solutions for this too.

Sample of vector images in a WPF application

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    x:Class="VectorGraphicsDemo.MainWindow"
    Title="MainWindow"
    Height="350"
    Width="616">

<Window.Resources>
    <!-- Note: When Expression Designed generated the code it was generated
         as DrawingBrush. Remember to change this to DrawingImage. -->
    <DrawingImage x:Key="TestImage">
        <DrawingImage.Drawing>
            <DrawingGroup>
                <GeometryDrawing Brush="#00FFFFFF"
                                 Geometry="M 0,0L 32,0L 32,32L 0,32L 0,0 Z " />
                <GeometryDrawing Brush="#FFFF0000"
                                 Geometry="F1 M 6.25,3.97918L 23.125,3.97918L 23.125,16.1458L 6.25,16.1458L 6.25,3.97918 Z ">
                    <GeometryDrawing.Pen>
                        <Pen LineJoin="Round"
                             Brush="#FF000000" />
                    </GeometryDrawing.Pen>
                </GeometryDrawing>
                <GeometryDrawing Brush="#FF00C800"
                                 Geometry="F1 M 21.8542,11.0625C 26.399,11.0625 30.0833,14.7468 30.0833,19.2917C 30.0833,23.8365 26.399,27.5208 21.8542,27.5208C 17.3093,27.5208 13.625,23.8365 13.625,19.2917C 13.625,14.7468 17.3093,11.0625 21.8542,11.0625 Z ">
                    <GeometryDrawing.Pen>
                        <Pen LineJoin="Round"
                             Brush="#FF000000" />
                    </GeometryDrawing.Pen>
                </GeometryDrawing>
                <GeometryDrawing Brush="#FFFFFF00"
                                 Geometry="F1 M 16.8731,14.9035L 11.9668,16.2498L 8.58953,12.5761L 8.25831,17.6042L 3.62852,19.7405L 8.33013,21.5017L 8.84603,26.4958L 12.083,22.5562L 17.0316,23.5064L 14.3306,19.3103L 16.8731,14.9035 Z ">
                    <GeometryDrawing.Pen>
                        <Pen LineJoin="Round"
                             Brush="#FF000000" />
                    </GeometryDrawing.Pen>
                </GeometryDrawing>
            </DrawingGroup>
        </DrawingImage.Drawing>
    </DrawingImage>

    <DrawingImage x:Key="TestThinLineImage">
        <DrawingImage.Drawing>
            <DrawingGroup>
                <GeometryDrawing Brush="#00FFFFFF"
                                 Geometry="M 0,0L 32,0L 32,32L 0,32L 0,0 Z " />
                <GeometryDrawing Geometry="F1 M 2,2L 30,2L 30,30L 2,30L 2,2 Z ">
                    <GeometryDrawing.Pen>
                        <Pen LineJoin="Round"
                             Brush="#FF000000" />
                    </GeometryDrawing.Pen>
                </GeometryDrawing>
                <GeometryDrawing Geometry="F1 M 7,8L 25,8L 25,24L 7,24L 7,8 Z ">
                    <GeometryDrawing.Pen>
                        <Pen LineJoin="Round"
                             Brush="#FFFF0000" />
                    </GeometryDrawing.Pen>
                </GeometryDrawing>
            </DrawingGroup>
        </DrawingImage.Drawing>
    </DrawingImage>
</Window.Resources>
<Grid>

    <!-- Menu with image -->
    <Menu HorizontalAlignment="Stretch"
          VerticalAlignment="Top">
        <MenuItem Header="Hello">
            <MenuItem Header="World">
                <MenuItem.Icon>
                    <Image Source="{StaticResource TestImage}" />
                </MenuItem.Icon>
            </MenuItem>
        </MenuItem>
    </Menu>

    <!-- Small standard image -->
    <Button HorizontalAlignment="Left"
            Margin="12,66,0,0"
            VerticalAlignment="Top"
            Width="142"
            Height="43">
        <StackPanel Orientation="Horizontal">
            <Image x:Name="imageSmall"
                   Source="{StaticResource TestImage}"
                   Height="32"
                   Width="32" />
            <Label VerticalAlignment="Center"
                   Content="Small image" />
        </StackPanel>
    </Button>

    <!-- Large standard image -->
    <Button HorizontalAlignment="Left"
            Margin="12,149,0,0"
            VerticalAlignment="Top"
            Width="142"
            Height="75">
        <StackPanel Orientation="Horizontal">
            <Image x:Name="imageLarge"
                   Source="{StaticResource TestImage}"
                   Height="64"
                   Width="64">
            </Image>
            <Label VerticalAlignment="Center"
                   Content="Large image" />
        </StackPanel>
    </Button>

    <!-- Small image with thin line with antialising enabled - looks bad! -->
    <Button HorizontalAlignment="Left"
            Margin="180,67,0,0"
            VerticalAlignment="Top"
            Width="177"
            Height="43">
        <StackPanel Orientation="Horizontal">
            <Image x:Name="imageSmall1"
                   Source="{StaticResource TestThinLineImage}"
                   Height="32"
                   Width="32" />
            <Label VerticalAlignment="Center"
                   Content="Small thin anti alias" />
        </StackPanel>
    </Button>

    <!-- Large image with thin line with antialising enabled - looks bad! -->
    <Button HorizontalAlignment="Left"
            Margin="180,149,0,0"
            VerticalAlignment="Top"
            Width="177"
            Height="75">
        <StackPanel Orientation="Horizontal">
            <Image Source="{StaticResource TestThinLineImage}"
                   Height="64"
                   Width="64">
            </Image>
            <Label VerticalAlignment="Center"
                   Content="Large thin anti alias" />
        </StackPanel>
    </Button>

    <!-- Small image with thin line with antialising disabled - looks OK! -->
    <Button HorizontalAlignment="Left"
            Margin="391,67,0,0"
            VerticalAlignment="Top"
            Width="177"
            Height="43">
        <StackPanel Orientation="Horizontal">
            <Image SnapsToDevicePixels="True"
                   RenderOptions.EdgeMode="Aliased"
                   Source="{StaticResource TestThinLineImage}"
                   Height="32"
                   Width="32" />
            <Label VerticalAlignment="Center"
                   Content="Small thin alias" />
        </StackPanel>
    </Button>

    <!-- Large image with thin line with antialising disabled - looks OK! -->
    <Button HorizontalAlignment="Left"
            SnapsToDevicePixels="True"
            RenderOptions.EdgeMode="Aliased"
            Margin="391,149,0,0"
            VerticalAlignment="Top"
            Width="177"
            Height="75">
        <StackPanel Orientation="Horizontal">
            <Image Source="{StaticResource TestThinLineImage}"
                   Height="64"
                   Width="64" />
            <Label VerticalAlignment="Center"
                   Content="Large thin alias" />
        </StackPanel>
    </Button>
</Grid>

like image 39
PEK Avatar answered Sep 19 '22 14:09

PEK