Graphics and Multimedia 프로그래밍/WPF2016. 11. 24. 02:02
Graphics and Multimedia
https://msdn.microsoft.com/en-us/library/ms742562(v=vs.110).aspx
Windows Presentation Foundation (WPF) provides support for multimedia, vector graphics, animation, and content composition, making it easy for developers to build interesting user interfaces and content. Using Microsoft Visual Studio, you can create vector graphics or complex animations and integrate media into your applications.
This topic introduces the graphics, animation, and media features of WPF, which enable you to add graphics, transition effects, sound, and video to your applications.
Note |
---|
Using WPF types in a Windows service is strongly discouraged. If you attempt to use WPF types in a Windows service, the service may not work as expected. |
What's New with Graphics and Multimedia in WPF 4
Several changes have been made related to graphics and animations.
Layout Rounding
When an object edge falls in the middle of a pixel device, the DPI-independent graphics system can create rendering artifacts, such as blurry or semi-transparent edges. Previous versions of WPF included pixel snapping to help handle this case. Silverlight 2 introduced layout rounding, which is another way to move elements so that edges fall on whole pixel boundaries. WPF now supports layout rounding with the UseLayoutRounding attached property on FrameworkElement.
Cached Composition
By using the new BitmapCache and BitmapCacheBrush classes, you can cache a complex part of the visual tree as a bitmap and greatly improve rendering time. The bitmap remains responsive to user input, such as mouse clicks, and you can paint it onto other elements just like any brush.
Pixel Shader 3 Support
WPF 4 builds on top of the ShaderEffect support introduced in WPF 3.5 SP1 by allowing applications to write effects by using Pixel Shader (PS) version 3.0. The PS 3.0 shader model is more sophisticated than PS 2.0, which allows for even more effects on supported hardware.
Easing Functions
You can enhance animations with easing functions, which give you additional control over the behavior of animations. For example, you can apply an ElasticEase to an animation to give the animation a springy behavior. For more information, see the easing types in the System.Windows.Media.Animation namespace.
Graphics and Rendering
WPF includes support for high quality 2-D graphics. The functionality includes brushes, geometries, images, shapes and transformations. For more information, see Graphics. The rendering of graphical elements is based on the Visual class. The structure of visual objects on the screen is described by the visual tree. For more information, see WPF Graphics Rendering Overview.
2-D Shapes
WPF provides a library of commonly used, vector-drawn 2-D shapes, such as rectangles and ellipses, which the following illustration shows.
These intrinsic WPF shapes are not just shapes: they are programmable elements that implement many of the features that you expect from most common controls, which include keyboard and mouse input. The following example shows how to handle the MouseUp event raised by clicking an Ellipse element.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Window1" > <Ellipse Fill="LightBlue" MouseUp="ellipseButton_MouseUp" /> </Window>
public partial class Window1 : Window { void ellipseButton_MouseUp(object sender, MouseButtonEventArgs e) { MessageBox.Show("You clicked the ellipse!"); } }
The following illustration shows the output for the preceding XAML markup and code-behind.
For more information, see Shapes and Basic Drawing in WPF Overview. For an introductory sample, see Shape Elements Sample.
2-D Geometries
When the 2-D shapes that WPF provides are not sufficient, you can use WPF support for geometries and paths to create your own. The following illustration shows how you can use geometries to create shapes, as a drawing brush, and to clip other WPF elements.
For more information, see Geometry Overview. For an introductory sample, see Geometries Sample.
2-D Effects
WPF provides a library of 2-D classes that you can use to create a variety of effects. The 2-D rendering capability of WPF provides the ability to paint UI elements that have gradients, bitmaps, drawings, and videos; and to manipulate them by using rotation, scaling, and skewing. The following illustration gives an example of the many effects you can achieve by using WPF brushes.
For more information, see WPF Brushes Overview. For an introductory sample, see Brushes Sample.
3-D Rendering
WPF provides a set of 3-D rendering capabilities that integrate with 2-D graphics support in WPF in order for you to create more exciting layout, UI, and data visualization. At one end of the spectrum, WPF enables you to render 2-D images onto the surfaces of 3-D shapes, which the following illustration demonstrates.
For more information, see 3-D Graphics Overview. For an introductory sample, see 3-D Solids Sample.
Animation
Use animation to make controls and elements grow, shake, spin, and fade; and to create interesting page transitions, and more. Because WPF enables you to animate most properties, not only can you animate most WPF objects, you can also use WPF to animate custom objects that you create.
For more information, see Animation Overview. For an introductory sample, see Animation Example Gallery.
Media
Images, video, and audio are media-rich ways of conveying information and user experiences.
Images
Images, which include icons, backgrounds, and even parts of animations, are a core part of most applications. Because you frequently need to use images, WPF exposes the ability to work with them in a variety of ways. The following illustration shows just one of those ways.
For more information, see Imaging Overview.
Video and Audio
A core feature of the graphics capabilities of WPF is to provide native support for working with multimedia, which includes video and audio. The following example shows how to insert a media player into an application.
<MediaElement Source="media\numbers.wmv" Width="450" Height="250" />
MediaElement is capable of playing both video and audio, and is extensible enough to allow the easy creation of custom UIs.
For more information, see the Multimedia Overview.
WPF Graphics Rendering Overview
This topic provides an overview of the WPF visual layer. It focuses on the role of the Visual class for rendering support in the WPF model.
Role of the Visual Object
The Visual class is the basic abstraction from which every FrameworkElement object derives. It also serves as the entry point for writing new controls in WPF, and in many ways can be thought of as the window handle (HWND) in the Win32 application model.
The Visual object is a core WPF object, whose primary role is to provide rendering support. User interface controls, such as Button and TextBox, derive from the Visual class, and use it for persisting their rendering data. The Visual object provides support for:
Output display: Rendering the persisted, serialized drawing content of a visual.
Transformations: Performing transformations on a visual.
Clipping: Providing clipping region support for a visual.
Hit testing: Determining whether a coordinate or geometry is contained within the bounds of a visual.
Bounding box calculations: Determining the bounding rectangle of a visual.
However, the Visual object does not include support for non-rendering features, such as:
Event handling
Layout
Styles
Data binding
Globalization
Visual is exposed as a public abstract class from which child classes must be derived. The following illustration shows the hierarchy of the visual objects that are exposed in WPF.
DrawingVisual Class
The DrawingVisual is a lightweight drawing class that is used to render shapes, images, or text. This class is considered lightweight because it does not provide layout or event handling, which improves its runtime performance. For this reason, drawings are ideal for backgrounds and clip art. The DrawingVisual can be used to create a custom visual object. For more information, see Using DrawingVisual Objects.
Viewport3DVisual Class
The Viewport3DVisual provides a bridge between 2D Visual and Visual3D objects. The Visual3D class is the base class for all 3D visual elements. The Viewport3DVisual requires that you define a Camera value and a Viewport value. The camera allows you to view the scene. The viewport establishes where the projection maps onto the 2D surface. For more information on 3D in WPF, see 3-D Graphics Overview.
ContainerVisual Class
The ContainerVisual class is used as a container for a collection of Visual objects. The DrawingVisual class derives from the ContainerVisual class, allowing it to contain a collection of visual objects.
Drawing Content in Visual Objects
A Visual object stores its render data as a vector graphics instruction list. Each item in the instruction list represents a low-level set of graphics data and associated resources in a serialized format. There are four different types of render data that can contain drawing content.
Drawing content type | Description |
---|---|
Vector graphics | Represents vector graphics data, and any associated Brush and Pen information. |
Image | Represents an image within a region defined by a Rect. |
Glyph | Represents a drawing that renders a GlyphRun, which is a sequence of glyphs from a specified font resource. This is how text is represented. |
Video | Represents a drawing that renders video. |
The DrawingContext allows you to populate a Visual with visual content. When you use a DrawingContext object's draw commands, you are actually storing a set of render data that will later be used by the graphics system; you are not drawing to the screen in real-time.
When you create a WPF control, such as a Button, the control implicitly generates render data for drawing itself. For example, setting the Contentproperty of the Button causes the control to store a rendering representation of a glyph.
A Visual describes its content as one or more Drawing objects contained within a DrawingGroup. A DrawingGroup also describes opacity masks, transforms, bitmap effects, and other operations that are applied to its contents. DrawingGroup operations are applied in the following order when content is rendered: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSet, and then Transform.
The following illustration shows the order in which DrawingGroup operations are applied during the rendering sequence.
For more information, see Drawing Objects Overview.
Drawing Content at the Visual Layer
You never directly instantiate a DrawingContext; you can, however, acquire a drawing context from certain methods, such as DrawingGroup.Open and DrawingVisual.RenderOpen. The following example retrieves a DrawingContext from a DrawingVisual and uses it to draw a rectangle.
// Create a DrawingVisual that contains a rectangle. private DrawingVisual CreateDrawingVisualRectangle() { DrawingVisual drawingVisual = new DrawingVisual(); // Retrieve the DrawingContext in order to create new drawing content. DrawingContext drawingContext = drawingVisual.RenderOpen(); // Create a rectangle and draw it in the DrawingContext. Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80)); drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect); // Persist the drawing content. drawingContext.Close(); return drawingVisual; }
Enumerating Drawing Content at the Visual Layer
In addition to their other uses, Drawing objects also provide an object model for enumerating the contents of a Visual.
Note |
---|
When you are enumerating the contents of the visual, you are retrieving Drawing objects, and not the underlying representation of the render data as a vector graphics instruction list. |
The following example uses the GetDrawing method to retrieve the DrawingGroup value of a Visual and enumerate it.
public void RetrieveDrawing(Visual v) { DrawingGroup dGroup = VisualTreeHelper.GetDrawing(v); EnumDrawingGroup(dGroup); } // Enumerate the drawings in the DrawingGroup. public void EnumDrawingGroup(DrawingGroup drawingGroup) { DrawingCollection dc = drawingGroup.Children; // Enumerate the drawings in the DrawingCollection. foreach (Drawing drawing in dc) { // If the drawing is a DrawingGroup, call the function recursively. if (drawing.GetType() == typeof(DrawingGroup)) { EnumDrawingGroup((DrawingGroup)drawing); } else if (drawing.GetType() == typeof(GeometryDrawing)) { // Perform action based on drawing type. } else if (drawing.GetType() == typeof(ImageDrawing)) { // Perform action based on drawing type. } else if (drawing.GetType() == typeof(GlyphRunDrawing)) { // Perform action based on drawing type. } else if (drawing.GetType() == typeof(VideoDrawing)) { // Perform action based on drawing type. } } }
How Visual Objects are Used to Build Controls
Many of the objects in WPF are composed of other visual objects, meaning they can contain varying hierarchies of descendant objects. Many of the user interface elements in WPF, such as controls, are composed of multiple visual objects, representing different types of rendering elements. For example, the Button control can contain a number of other objects, including ClassicBorderDecorator, ContentPresenter, and TextBlock.
The following code shows a Button control defined in markup.
<Button Click="OnClick">OK</Button>
If you were to enumerate the visual objects that comprise the default Button control, you would find the hierarchy of visual objects illustrated below:
The Button control contains a ClassicBorderDecorator element, which in turn, contains a ContentPresenter element. The ClassicBorderDecoratorelement is responsible for drawing a border and a background for the Button. The ContentPresenter element is responsible for displaying the contents of the Button. In this case, since you are displaying text, the ContentPresenter element contains a TextBlock element. The fact that the Button control uses a ContentPresenter means that the content could be represented by other elements, such as an Image or a geometry, such as an EllipseGeometry.
Control Templates
The key to the expansion of a control into a hierarchy of controls is the ControlTemplate. A control template specifies the default visual hierarchy for a control. When you explicitly reference a control, you implicitly reference its visual hierarchy. You can override the default values for a control template to create a customized visual appearance for a control. For example, you could modify the background color value of the Button control so that it uses a linear gradient color value instead of a solid color value. For more information, see Button Styles and Templates.
A user interface element, such as a Button control, contains several vector graphics instruction lists that describe the entire rendering definition of a control. The following code shows a Button control defined in markup.
<Button Click="OnClick"> <Image Source="images\greenlight.jpg"></Image> </Button>
If you were to enumerate the visual objects and vector graphics instruction lists that comprise the Button control, you would find the hierarchy of objects illustrated below:
The Button control contains a ClassicBorderDecorator element, which in turn, contains a ContentPresenter element. The ClassicBorderDecoratorelement is responsible for drawing all the discrete graphic elements that make up the border and background of a button. The ContentPresenterelement is responsible for displaying the contents of the Button. In this case, since you are displaying an image, the ContentPresenter element contains a Image element.
There are a number of points to note about the hierarchy of visual objects and vector graphics instruction lists:
The ordering in the hierarchy represents the rendering order of the drawing information. From the root visual element, child elements are traversed, left to right, top to bottom. If an element has visual child elements, they are traversed before the element’s siblings.
Non-leaf node elements in the hierarchy, such as ContentPresenter, are used to contain child elements—they do not contain instruction lists.
If a visual element contains both a vector graphics instruction list and visual children, the instruction list in the parent visual element is rendered before drawings in any of the visual child objects.
The items in the vector graphics instruction list are rendered left to right.
Visual Tree
The visual tree contains all visual elements used in an application's user interface. Since a visual element contains persisted drawing information, you can think of the visual tree as a scene graph, containing all the rendering information needed to compose the output to the display device. This tree is the accumulation of all visual elements created directly by the application, whether in code or in markup. The visual tree also contains all visual elements created by the template expansion of elements such as controls and data objects.
The following code shows a StackPanel element defined in markup.
<StackPanel> <Label>User name:</Label> <TextBox /> <Button Click="OnClick">OK</Button> </StackPanel>
If you were to enumerate the visual objects that comprise the StackPanel element in the markup example, you would find the hierarchy of visual objects illustrated below:
Rendering Order
The visual tree determines the rendering order of WPF visual and drawing objects. The order of traversal starts with the root visual, which is the top-most node in the visual tree. The root visual’s children are then traversed, left to right. If a visual has children, its children are traversed before the visual’s siblings. This means that the content of a child visual is rendered in front of the visual's own content.
Root Visual
The root visual is the top-most element in a visual tree hierarchy. In most applications, the base class of the root visual is either Window or NavigationWindow. However, if you were hosting visual objects in a Win32 application, the root visual would be the top-most visual you were hosting in the Win32 window. For more information, see Tutorial: Hosting Visual Objects in a Win32 Application.
Relationship to the Logical Tree
The logical tree in WPF represents the elements of an application at run time. Although you do not manipulate this tree directly, this view of the application is useful for understanding property inheritance and event routing. Unlike the visual tree, the logical tree can represent non-visual data objects, such as ListItem. In many cases, the logical tree maps very closely to an application's markup definitions. The following code shows a DockPanel element defined in markup.
<DockPanel> <ListBox> <ListBoxItem>Dog</ListBoxItem> <ListBoxItem>Cat</ListBoxItem> <ListBoxItem>Fish</ListBoxItem> </ListBox> <Button Click="OnClick">OK</Button> </DockPanel>
If you were to enumerate the logical objects that comprise the DockPanel element in the markup example, you would find the hierarchy of logical objects illustrated below:
Both the visual tree and logical tree are synchronized with the current set of application elements, reflecting any addition, deletion, or modification of elements. However, the trees present different views of the application. Unlike the visual tree, the logical tree does not expand a control's ContentPresenter element. This means there is not a direct one-to-one correspondence between a logical tree and a visual tree for the same set of objects. In fact, invoking the LogicalTreeHelper object's GetChildren method and the VisualTreeHelper object's GetChild method using the same element as a parameter yields differing results.
For more information on the logical tree, see Trees in WPF.
Viewing the Visual Tree with XamlPad
The WPF tool, XamlPad, provides an option for viewing and exploring the visual tree that corresponds to the currently defined XAML content. Click the Show Visual Tree button on the menu bar to display the visual tree. The following illustrates the expansion of XAML content into visual tree nodes in the Visual Tree Explorer panel of XamlPad:
Notice how the Label, TextBox, and Button controls each display a separate visual object hierarchy in the Visual Tree Explorer panel of XamlPad. This is because WPF controls have a ControlTemplate that contains the visual tree of that control. When you explicitly reference a control, you implicitly reference its visual hierarchy.
Profiling Visual Performance
WPF provides a suite of performance profiling tools that allow you to analyze the run-time behavior of your application and determine the types of performance optimizations you can apply. The Visual Profiler tool provides a rich, graphical view of performance data by mapping directly to the application's visual tree. In this screenshot, the CPU Usage section of the Visual Profiler gives you a precise breakdown of an object's use of WPF services, such as rendering and layout.
Visual Rendering Behavior
WPF introduces several features that affect the rendering behavior of visual objects: retained mode graphics, vector graphics, and device independent graphics.
Retained Mode Graphics
One of the keys to understanding the role of the Visual object is to understand the difference between immediate mode and retained modegraphics systems. A standard Win32 application based on GDI or GDI+ uses an immediate mode graphics system. This means that the application is responsible for repainting the portion of the client area that is invalidated, due to an action such as a window being resized, or an object changing its visual appearance.
In contrast, WPF uses a retained mode system. This means application objects that have a visual appearance define a set of serialized drawing data. Once the drawing data is defined, the system is responsible thereafter for responding to all repaint requests for rendering the application objects. Even at run time, you can modify or create application objects, and still rely on the system for responding to paint requests. The power in a retained mode graphics system is that drawing information is always persisted in a serialized state by the application, but rendering responsibility left to the system. The following diagram shows how the application relies on WPF for responding to paint requests.
Intelligent Redrawing
One of the biggest benefits in using retained mode graphics is that WPF can efficiently optimize what needs to be redrawn in the application. Even if you have a complex scene with varying levels of opacity, you generally do not need to write special-purpose code to optimize redrawing. Compare this with Win32 programming in which you can spend a great deal of effort in optimizing your application by minimizing the amount of redrawing in the update region. See Redrawing in the Update Region for an example of the type of complexity involved in optimizing redrawing in Win32 applications.
Vector Graphics
WPF uses vector graphics as its rendering data format. Vector graphics—which include Scalable Vector Graphics (SVG), Windows metafiles (.wmf), and TrueType fonts—store rendering data and transmit it as a list of instructions that describe how to recreate an image using graphics primitives. For example, TrueType fonts are outline fonts that describe a set of lines, curves, and commands, rather than an array of pixels. One of the key benefits of vector graphics is the ability to scale to any size and resolution.
Unlike vector graphics, bitmap graphics store rendering data as a pixel-by-pixel representation of an image, pre-rendered for a specific resolution. One of the key differences between bitmap and vector graphic formats is fidelity to the original source image. For example, when the size of a source image is modified, bitmap graphics systems stretch the image, whereas vector graphics systems scale the image, preserving the image fidelity.
The following illustration shows a source image that has been resized by 300%. Notice the distortions that appear when the source image is stretched as a bitmap graphics image rather than scaled as a vector graphics image.
The following markup shows two Path elements defined. The second element uses a ScaleTransform to resize the drawing instructions of the first element by 300%. Notice that the drawing instructions in the Path elements remain unchanged.
<Path Data="M10,100 C 60,0 100,200 150,100 z" Fill="{StaticResource linearGradientBackground}" Stroke="Black" StrokeThickness="2" /> <Path Data="M10,100 C 60,0 100,200 150,100 z" Fill="{StaticResource linearGradientBackground}" Stroke="Black" StrokeThickness="2" > <Path.RenderTransform> <ScaleTransform ScaleX="3.0" ScaleY="3.0" /> </Path.RenderTransform> </Path>
About Resolution and Device-Independent Graphics
There are two system factors that determine the size of text and graphics on your screen: resolution and DPI. Resolution describes the number of pixels that appear on the screen. As the resolution gets higher, pixels get smaller, causing graphics and text to appear smaller. A graphic displayed on a monitor set to 1024 x 768 will appear much smaller when the resolution is changed to 1600 x 1200.
The other system setting, DPI, describes the size of a screen inch in pixels. Most Windows systems have a DPI of 96, which means a screen inch is 96 pixels. Increasing the DPI setting makes the screen inch larger; decreasing the DPI makes the screen inch smaller. This means that a screen inch isn't the same size as a real-world inch; on most systems, it's probably not. As you increase the DPI, DPI-aware graphics and text become larger because you've increased the size of the screen inch. Increasing the DPI can make text easier to read, especially at high resolutions.
Not all applications are DPI-aware: some use hardware pixels as the primary unit of measurement; changing the system DPI has no effect on these applications. Many other applications use DPI-aware units to describe font sizes, but use pixels to describe everything else. Making the DPI too small or too large can cause layout problems for these applications, because the applications' text scales with the system's DPI setting, but the applications' UI does not. This problem has been eliminated for applications developed using WPF.
WPF supports automatic scaling by using the device independent pixel as its primary unit of measurement, instead of hardware pixels; graphics and text scale properly without any extra work from the application developer. The following illustration shows an example of how WPF text and graphics are appear at different DPI settings.
VisualTreeHelper Class
The VisualTreeHelper class is a static helper class that provides low-level functionality for programming at the visual object level, which is useful in very specific scenarios, such as developing high-performance custom controls. In most case, the higher-level WPF framework objects, such as Canvasand TextBlock, offer greater flexibility and ease of use.
Hit Testing
The VisualTreeHelper class provides methods for hit testing on visual objects when the default hit test support does not meet your needs. You can use the HitTest methods in the VisualTreeHelper class to determine whether a geometry or point coordinate value is within the boundary of a given object, such as a control or graphic element. For example, you could use hit testing to determine whether a mouse click within the bounding rectangle of an object falls within the geometry of a circle You can also choose to override the default implementation of hit testing to perform your own custom hit test calculations.
For more information on hit testing, see Hit Testing in the Visual Layer.
Enumerating the Visual Tree
The VisualTreeHelper class provides functionality for enumerating the members of a visual tree. To retrieve a parent, call the GetParent method. To retrieve a child, or direct descendant, of a visual object, call the GetChild method. This method returns a child Visual of the parent at the specified index.
The following example shows how to enumerate all the descendants of a visual object, which is a technique you might want to use if you were interested in serializing all the rendering information of a visual object hierarchy.
// Enumerate all the descendants of the visual object. static public void EnumVisual(Visual myVisual) { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++) { // Retrieve child visual at specified index value. Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i); // Do processing of the child visual object. // Enumerate children of the child visual object. EnumVisual(childVisual); } }
In most cases, the logical tree is a more useful representation of the elements in a WPF application. Although you do not modify the logical tree directly, this view of the application is useful for understanding property inheritance and event routing. Unlike the visual tree, the logical tree can represent non-visual data objects, such as ListItem. For more information on the logical tree, see Trees in WPF.
The VisualTreeHelper class provides methods for returning the bounding rectangle of visual objects. You can return the bounding rectangle of a visual object by calling GetContentBounds. You can return the bounding rectangle of all the descendants of a visual object, including the visual object itself, by calling GetDescendantBounds. The following code shows how you would calculate the bounding rectangle of a visual object and all its descendants.
Graphics
Bitmap Effects
Bitmap Effects Overview
Bitmap effects enable designers and developers to apply visual effects to rendered Windows Presentation Foundation (WPF) content. For example, bitmap effects allow you to easily apply a DropShadowBitmapEffect effect or a blur effect to an image or a button.
Important |
---|
In the .NET Framework 4 or later, the BitmapEffect class is obsolete. If you try to use the BitmapEffect class, you will get an obsolete exception. The non-obsolete alternative to the BitmapEffect class is the Effect class. In most situations, the Effect class is significantly faster. |
WPF Bitmap Effects
Bitmap effects (BitmapEffect object) are simple pixel processing operations. A bitmap effect takes a BitmapSource as an input and produces a new BitmapSource after applying the effect, such as a blur or drop shadow. Each bitmap effect exposes properties that can control the filtering properties, such as Radius of BlurBitmapEffect.
As a special case, in WPF, effects can be set as properties on live Visual objects, such as a Button or TextBox. The pixel processing is applied and rendered at run-time. In this case, at the time of rendering, a Visual is automatically converted to its BitmapSource equivalent and is fed as input to the BitmapEffect. The output replaces the Visual object's default rendering behavior. This is why BitmapEffect objects force visuals to render in software only i.e. no hardware acceleration on visuals when effects are applied.
BlurBitmapEffect simulates an object that appears out-of-focus.
OuterGlowBitmapEffect creates a halo of color around the perimeter of an object.
DropShadowBitmapEffect creates a shadow behind an object.
BevelBitmapEffect creates a bevel which raises the surface of an image according to a specified curve.
EmbossBitmapEffect creates a bump mapping of a Visual to give the impression of depth and texture from an artificial light source.
Note |
---|
WPF bitmap effects are rendered in software mode. Any object that applies an effect will also be rendered in software. Performance is degraded the most when using Bitmap effects on large visuals or animating properties of a Bitmap effect. This is not to say that you should not use Bitmap effects in this way at all, but you should use caution and test thoroughly to ensure that your users are getting the experience you expect. |
Note |
---|
WPF bitmap effects do not support partial trust execution. An application must have full trust permissions to use bitmap effects. |
How to Apply an Effect
BitmapEffect is a property on Visual. Therefore applying effects to Visuals, such as a Button, Image, DrawingVisual, or UIElement, is as easy as setting a property. BitmapEffect can be set to a single BitmapEffect object or multiple effects can be chained by using the BitmapEffectGroup object.
The following example demonstrates how to apply a BitmapEffect in Extensible Application Markup Language (XAML).
<Button Width="200">You Can't Read This! <Button.BitmapEffect> <!-- <BitmapEffectGroup> would go here if you wanted to apply more then one effect to the Button. However, in this example only one effect is being applied so BitmapEffectGroup does not need to be included. --> <!-- The larger the Radius, the more blurring. The default range is 20. In addition, the KernelType is set to a box kernel. A box kernel creates less disruption (less blur) then the default Gaussian kernel. --> <BlurBitmapEffect Radius="10" KernelType="Box" /> </Button.BitmapEffect> </Button>
The following example demonstrates how to apply a BitmapEffect in code.
// Get a reference to the Button. Button myButton = (Button)sender; // Initialize a new BlurBitmapEffect that will be applied // to the Button. BlurBitmapEffect myBlurEffect = new BlurBitmapEffect(); // Set the Radius property of the blur. This determines how // blurry the effect will be. The larger the radius, the more // blurring. myBlurEffect.Radius = 10; // Set the KernelType property of the blur. A KernalType of "Box" // creates less blur than the Gaussian kernal type. myBlurEffect.KernelType = KernelType.Box; // Apply the bitmap effect to the Button. myButton.BitmapEffect = myBlurEffect;
Note |
---|
When a BitmapEffect is applied to a layout container, such as DockPanel or Canvas, the effect is applied to the visual tree of the element or visual, including all of its child elements. |
WPF also provides unmanaged interfaces to create custom effects that can be used in managed WPF applications. For additional reference material for creating custom bitmap effects, see the Unmanaged WPF Bitmap Effect documentation.
Brushes
WPF Brushes Overview
Everything visible on your screen is visible because it was painted by a brush. For example, a brush is used to describe the background of a button, the foreground of text, and the fill of a shape. This topic introduces the concepts of painting with Windows Presentation Foundation (WPF) brushes and provides examples. Brushes enable you to paint user interface (UI) objects with anything from simple, solid colors to complex sets of patterns and images.
Painting with a Brush
A Brush "paints" an area with its output. Different brushes have different types of output. Some brushes paint an area with a solid color, others with a gradient, pattern, image, or drawing. The following illustration shows examples of each of the different Brush types.
Most visual objects enable you to specify how they are painted. The following table lists some common objects and properties with which you can use a Brush.
Class | Brush properties |
---|---|
The following sections describe the different Brush types and provide an example of each.
Paint with a Solid Color
A SolidColorBrush paints an area with a solid Color. There are a variety of ways to specify the Color of a SolidColorBrush: for example, you can specify its alpha, red, blue, and green channels or use one of the predefined color provided by the Colors class.
The following example uses a SolidColorBrush to paint the Fill of a Rectangle. The following illustration shows the painted rectangle.
Rectangle exampleRectangle = new Rectangle(); exampleRectangle.Width = 75; exampleRectangle.Height = 75; // Create a SolidColorBrush and use it to // paint the rectangle. SolidColorBrush myBrush = new SolidColorBrush(Colors.Red); exampleRectangle.Fill = myBrush;
<Rectangle Width="75" Height="75"> <Rectangle.Fill> <SolidColorBrush Color="Red" /> </Rectangle.Fill> </Rectangle>
For more information about the SolidColorBrush class, see Painting with Solid Colors and Gradients Overview.
Paint with a Linear Gradient
A LinearGradientBrush paints an area with a linear gradient. A linear gradient blends two or more colors across a line, the gradient axis. You use GradientStop objects to specify the colors in the gradient and their positions.
The following example uses a LinearGradientBrush to paint the Fill of a Rectangle. The following illustration shows the painted rectangle.
Rectangle exampleRectangle = new Rectangle(); exampleRectangle.Width = 75; exampleRectangle.Height = 75; // Create a LinearGradientBrush and use it to // paint the rectangle. LinearGradientBrush myBrush = new LinearGradientBrush(); myBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0)); myBrush.GradientStops.Add(new GradientStop(Colors.Orange, 0.5)); myBrush.GradientStops.Add(new GradientStop(Colors.Red, 1.0)); exampleRectangle.Fill = myBrush;
<Rectangle Width="75" Height="75"> <Rectangle.Fill> <LinearGradientBrush> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Orange" Offset="0.5" /> <GradientStop Color="Red" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
For more information about the LinearGradientBrush class, see Painting with Solid Colors and Gradients Overview.
Paint with a Radial Gradient
A RadialGradientBrush paints an area with a radial gradient. A radial gradient blends two or more colors across a circle. As with the LinearGradientBrush class, you use GradientStop objects to specify the colors in the gradient and their positions.
The following example uses a RadialGradientBrush to paint the Fill of a Rectangle. The following illustration shows the painted rectangle.
Rectangle exampleRectangle = new Rectangle(); exampleRectangle.Width = 75; exampleRectangle.Height = 75; // Create a RadialGradientBrush and use it to // paint the rectangle. RadialGradientBrush myBrush = new RadialGradientBrush(); myBrush.GradientOrigin = new Point(0.75, 0.25); myBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0)); myBrush.GradientStops.Add(new GradientStop(Colors.Orange, 0.5)); myBrush.GradientStops.Add(new GradientStop(Colors.Red, 1.0)); exampleRectangle.Fill = myBrush;
<Rectangle Width="75" Height="75"> <Rectangle.Fill> <RadialGradientBrush GradientOrigin="0.75,0.25"> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Orange" Offset="0.5" /> <GradientStop Color="Red" Offset="1.0" /> </RadialGradientBrush> </Rectangle.Fill> </Rectangle>
For more information about the RadialGradientBrush class, see Painting with Solid Colors and Gradients Overview.
Paint with an Image
An ImageBrush paints an area with a ImageSource.
The following example uses an ImageBrush to paint the Fill of a Rectangle. The following illustration shows the painted rectangle.
Rectangle exampleRectangle = new Rectangle(); exampleRectangle.Width = 75; exampleRectangle.Height = 75; // Create an ImageBrush and use it to // paint the rectangle. ImageBrush myBrush = new ImageBrush(); myBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative)); exampleRectangle.Fill = myBrush;
<Rectangle Width="75" Height="75"> <Rectangle.Fill> <ImageBrush ImageSource="sampleImages\pinkcherries.jpg" /> </Rectangle.Fill> </Rectangle>
For more information about the ImageBrush class, see Painting with Images, Drawings, and Visuals.
Paint with a Drawing
A DrawingBrush paints an area with a Drawing. A Drawing can contain shapes, images, text, and media.
The following example uses a DrawingBrush to paint the Fill of a Rectangle. The following illustration shows the painted rectangle.
Rectangle exampleRectangle = new Rectangle(); exampleRectangle.Width = 75; exampleRectangle.Height = 75; // Create a DrawingBrush and use it to // paint the rectangle. DrawingBrush myBrush = new DrawingBrush(); GeometryDrawing backgroundSquare = new GeometryDrawing( Brushes.White, null, new RectangleGeometry(new Rect(0, 0, 100, 100))); GeometryGroup aGeometryGroup = new GeometryGroup(); aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 50, 50))); aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(50, 50, 50, 50))); LinearGradientBrush checkerBrush = new LinearGradientBrush(); checkerBrush.GradientStops.Add(new GradientStop(Colors.Black, 0.0)); checkerBrush.GradientStops.Add(new GradientStop(Colors.Gray, 1.0)); GeometryDrawing checkers = new GeometryDrawing(checkerBrush, null, aGeometryGroup); DrawingGroup checkersDrawingGroup = new DrawingGroup(); checkersDrawingGroup.Children.Add(backgroundSquare); checkersDrawingGroup.Children.Add(checkers); myBrush.Drawing = checkersDrawingGroup; myBrush.Viewport = new Rect(0, 0, 0.25, 0.25); myBrush.TileMode = TileMode.Tile; exampleRectangle.Fill = myBrush;
<Rectangle Width="75" Height="75"> <Rectangle.Fill> <DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile"> <DrawingBrush.Drawing> <DrawingGroup> <GeometryDrawing Brush="White"> <GeometryDrawing.Geometry> <RectangleGeometry Rect="0,0,100,100" /> </GeometryDrawing.Geometry> </GeometryDrawing> <GeometryDrawing> <GeometryDrawing.Geometry> <GeometryGroup> <RectangleGeometry Rect="0,0,50,50" /> <RectangleGeometry Rect="50,50,50,50" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Brush> <LinearGradientBrush> <GradientStop Offset="0.0" Color="Black" /> <GradientStop Offset="1.0" Color="Gray" /> </LinearGradientBrush> </GeometryDrawing.Brush> </GeometryDrawing> </DrawingGroup> </DrawingBrush.Drawing> </DrawingBrush> </Rectangle.Fill> </Rectangle>
For more information about the DrawingBrush class, see Painting with Images, Drawings, and Visuals.
Paint with a Visual
A VisualBrush paints an area with a Visual object. Examples of Visual objects include Button, Page, and MediaElement. A VisualBrush also enables you to project content from one portion of your application into another area; it's very useful for creating reflection effects and magnifying portions of the screen.
The following example uses a VisualBrush to paint the Fill of a Rectangle. The following illustration shows the painted rectangle.
Rectangle exampleRectangle = new Rectangle(); exampleRectangle.Width = 75; exampleRectangle.Height = 75; // Create a VisualBrush and use it // to paint the rectangle. VisualBrush myBrush = new VisualBrush(); // // Create the brush's contents. // StackPanel aPanel = new StackPanel(); // Create a DrawingBrush and use it to // paint the panel. DrawingBrush myDrawingBrushBrush = new DrawingBrush(); GeometryGroup aGeometryGroup = new GeometryGroup(); aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 50, 50))); aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(50, 50, 50, 50))); RadialGradientBrush checkerBrush = new RadialGradientBrush(); checkerBrush.GradientStops.Add(new GradientStop(Colors.MediumBlue, 0.0)); checkerBrush.GradientStops.Add(new GradientStop(Colors.White, 1.0)); GeometryDrawing checkers = new GeometryDrawing(checkerBrush, null, aGeometryGroup); myDrawingBrushBrush.Drawing = checkers; aPanel.Background = myDrawingBrushBrush; // Create some text. TextBlock someText = new TextBlock(); someText.Text = "Hello, World"; FontSizeConverter fSizeConverter = new FontSizeConverter(); someText.FontSize = (double)fSizeConverter.ConvertFromString("10pt"); someText.Margin = new Thickness(10); aPanel.Children.Add(someText); myBrush.Visual = aPanel; exampleRectangle.Fill = myBrush;
<Rectangle Width="75" Height="75"> <Rectangle.Fill> <VisualBrush TileMode="Tile"> <VisualBrush.Visual> <StackPanel> <StackPanel.Background> <DrawingBrush> <DrawingBrush.Drawing> <GeometryDrawing> <GeometryDrawing.Brush> <RadialGradientBrush> <GradientStop Color="MediumBlue" Offset="0.0" /> <GradientStop Color="White" Offset="1.0" /> </RadialGradientBrush> </GeometryDrawing.Brush> <GeometryDrawing.Geometry> <GeometryGroup> <RectangleGeometry Rect="0,0,50,50" /> <RectangleGeometry Rect="50,50,50,50" /> </GeometryGroup> </GeometryDrawing.Geometry> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </StackPanel.Background> <TextBlock FontSize="10pt" Margin="10">Hello, World!</TextBlock> </StackPanel> </VisualBrush.Visual> </VisualBrush> </Rectangle.Fill> </Rectangle>
For more information about the VisualBrush class, see Painting with Images, Drawings, and Visuals.
Paint using Predefined and System Brushes
For convenience, Windows Presentation Foundation (WPF) provides a set of predefined and system brushes that you can use to paint objects.
For a list of available predefined brushes, see the Brushes class. For an example showing how to use a predefined brush, see How to: Paint an Area with a Solid Color.
For a list of available system brushes, see the SystemColors class. For an example, see How to: Paint an Area with a System Brush.
Common Brush Features
Brush objects provide an Opacity property that can be used to make a brush transparent or partially transparent. An Opacity value of 0 makes a brush completely transparent, while an Opacity value of 1 makes a brush completely opaque. The following example uses the Opacity property to make a SolidColorBrush 25 percent opaque.
<Rectangle Width="100" Height="100"> <Rectangle.Fill> <SolidColorBrush Color="Blue" Opacity="0.25" /> </Rectangle.Fill> </Rectangle>
Rectangle myRectangle = new Rectangle(); myRectangle.Width = 100; myRectangle.Height = 100; SolidColorBrush partiallyTransparentSolidColorBrush = new SolidColorBrush(Colors.Blue); partiallyTransparentSolidColorBrush.Opacity = 0.25; myRectangle.Fill = partiallyTransparentSolidColorBrush;
If the brush contains colors that are partially transparent, the opacity value of the color is combined through multiplication with the opacity value of the brush. For example, if a brush has an opacity value of 0.5 and a color used in the brush also has an opacity value of 0.5, the output color has an opacity value of 0.25.
Note |
---|
It's more efficient to change the opacity value of a brush than it is to change the opacity of an entire element using its UIElement.Opacityproperty. |
You can rotate, scale, skew, and translate a brush's content by using its Transform or RelativeTransform properties. For more information, see Brush Transformation Overview.
Because they are Animatable objects, Brush objects can be animated. For more information, see Animation Overview.
Freezable Features
Because it inherits from the Freezable class, the Brush class provides several special features: Brush objects can be declared as resources, shared among multiple objects, and cloned. In addition, all the Brush types except VisualBrush can be made read-only to improve performance and made thread-safe.
For more information about the different features provided by Freezable objects, see Freezable Objects Overview.
For more information on why VisualBrush objects cannot be frozen, see the VisualBrush type page.
Brush Transformation Overview
The Brush class provides two transformation properties: Transform and RelativeTransform. The properties enable you to rotate, scale, skew, and translate a brush's contents. This topic describes the differences between these two properties and provides examples of their usage.
Prerequisites
To understand this topic, you should understand the features of the brush that you are transforming. For LinearGradientBrush and RadialGradientBrush, see the Painting with Solid Colors and Gradients Overview. For ImageBrush, DrawingBrush, or VisualBrush, see Painting with Images, Drawings, and Visuals. You should also be familiar with the 2D transforms described in the Transforms Overview.
Differences between the Transform and RelativeTransform Properties
When you apply a transform to a brush's Transform property, you need to know the size of the painted area if you want to transform the brush contents about its center. Suppose the painted area is 200 device independent pixels wide and 150 tall. If you used a RotateTransform to rotate the brush's output 45 degrees about its center, you'd give the RotateTransform a CenterX of 100 and a CenterY of 75.
When you apply a transform to a brush's RelativeTransform property, that transform is applied to the brush before its output is mapped to the painted area. The following list describes the order in which a brush’s contents are processed and transformed.
Process the brush’s contents. For a GradientBrush, this means determining the gradient area. For a TileBrush, the Viewbox is mapped to the Viewport. This becomes the brush’s output.
Project the brush’s output onto the 1 x 1 transformation rectangle.
Apply the brush’s RelativeTransform, if it has one.
Project the transformed output onto the area to paint.
Apply the brush’s Transform, if it has one.
Because the RelativeTransform is applied while the brush’s output is mapped to a 1 x 1 rectangle, transform center and offset values appear to be relative. For example, if you used a RotateTransform to rotate the brush's output 45 degrees about its center, you'd give the RotateTransform a CenterX of 0.5 and a CenterY of 0.5.
The following illustration shows the output of several brushes that have been rotated by 45 degrees using the RelativeTransform and Transformproperties.
Using RelativeTransform with a TileBrush
Because tile brushes are more complex than other brushes, applying a RelativeTransform to one might produce unexpected results. For example, take the following image.
The following example uses an ImageBrush to paint a rectangular area with the preceding image. It applies a RotateTransform to the ImageBrushobject's RelativeTransform property, and sets its Stretch property to UniformToFill, which should preserve the image's aspect ratio when it is stretched to completely fill the rectangle.
<Rectangle Width="200" Height="100" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <ImageBrush Stretch="UniformToFill"> <ImageBrush.ImageSource> <BitmapImage UriSource="sampleImages\square.jpg" /> </ImageBrush.ImageSource> <ImageBrush.RelativeTransform> <RotateTransform CenterX="0.5" CenterY="0.5" Angle="90" /> </ImageBrush.RelativeTransform> </ImageBrush> </Rectangle.Fill> </Rectangle>
This example produces the following output:
Notice that the image is distorted, even though the brush's Stretch was set to UniformToFill. That's because the relative transform is applied after the brush's Viewbox is mapped to its Viewport. The following list describes each step of the process:
Project the brush's contents (Viewbox) onto its base tile (Viewport) using the brush's Stretch setting.
Project the base tile onto the 1 x 1 transformation rectangle.
Apply the RotateTransform.
Project the transformed base tile onto the area to paint.
Example: Rotate an ImageBrush 45 Degrees
The following example applies a RotateTransform to the RelativeTransform property of an ImageBrush. The RotateTransform object's CenterX and CenterY properties are both set to 0.5, the relative coordinates of the content's center point. As a result, the brush's contents are rotated about its center.
// // Create an ImageBrush with a relative transform and // use it to paint a rectangle. // ImageBrush relativeTransformImageBrush = new ImageBrush(); relativeTransformImageBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative)); // Create a 45 rotate transform about the brush's center // and apply it to the brush's RelativeTransform property. RotateTransform aRotateTransform = new RotateTransform(); aRotateTransform.CenterX = 0.5; aRotateTransform.CenterY = 0.5; aRotateTransform.Angle = 45; relativeTransformImageBrush.RelativeTransform = aRotateTransform; // Use the brush to paint a rectangle. Rectangle relativeTransformImageBrushRectangle = new Rectangle(); relativeTransformImageBrushRectangle.Width = 175; relativeTransformImageBrushRectangle.Height = 90; relativeTransformImageBrushRectangle.Stroke = Brushes.Black; relativeTransformImageBrushRectangle.Fill = relativeTransformImageBrush;
<Rectangle Width="175" Height="90" Stroke="Black"> <Rectangle.Fill> <ImageBrush ImageSource="sampleImages\pinkcherries.jpg"> <ImageBrush.RelativeTransform> <RotateTransform CenterX="0.5" CenterY="0.5" Angle="45" /> </ImageBrush.RelativeTransform> </ImageBrush> </Rectangle.Fill> </Rectangle>
The next example also applies a RotateTransform to an ImageBrush, but uses the Transform property instead of the RelativeTransform property. To rotate the brush about its center, the RotateTransform object's CenterX and CenterY must be set to absolute coordinates. Because the rectangle being painted by the brush is 175 by 90 pixels, its center point is (87.5, 45).
// // Create an ImageBrush with a transform and // use it to paint a rectangle. // ImageBrush transformImageBrush = new ImageBrush(); transformImageBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative)); // Create a 45 rotate transform about the brush's center // and apply it to the brush's Transform property. RotateTransform anotherRotateTransform = new RotateTransform(); anotherRotateTransform.CenterX = 87.5; anotherRotateTransform.CenterY = 45; anotherRotateTransform.Angle = 45; transformImageBrush.Transform = anotherRotateTransform; // Use the brush to paint a rectangle. Rectangle transformImageBrushRectangle = new Rectangle(); transformImageBrushRectangle.Width = 175; transformImageBrushRectangle.Height = 90; transformImageBrushRectangle.Stroke = Brushes.Black; transformImageBrushRectangle.Fill = transformImageBrush;
<Rectangle Width="175" Height="90" Stroke="Black"> <Rectangle.Fill> <ImageBrush ImageSource="sampleImages\pinkcherries.jpg"> <ImageBrush.Transform> <RotateTransform CenterX="87.5" CenterY="45" Angle="45" /> </ImageBrush.Transform> </ImageBrush> </Rectangle.Fill> </Rectangle>
The following illustration shows the brush without a transform, with the transform applied to the RelativeTransform property, and with the transform applied to the Transform property.
This example is part of a larger sample. For the complete sample, see the Brushes Sample. For more information about brushes, see the WPF Brushes Overview.
Brush Transformation Overview
The Brush class provides two transformation properties: Transform and RelativeTransform. The properties enable you to rotate, scale, skew, and translate a brush's contents. This topic describes the differences between these two properties and provides examples of their usage.
Prerequisites
To understand this topic, you should understand the features of the brush that you are transforming. For LinearGradientBrush and RadialGradientBrush, see the Painting with Solid Colors and Gradients Overview. For ImageBrush, DrawingBrush, or VisualBrush, see Painting with Images, Drawings, and Visuals. You should also be familiar with the 2D transforms described in the Transforms Overview.
Differences between the Transform and RelativeTransform Properties
When you apply a transform to a brush's Transform property, you need to know the size of the painted area if you want to transform the brush contents about its center. Suppose the painted area is 200 device independent pixels wide and 150 tall. If you used a RotateTransform to rotate the brush's output 45 degrees about its center, you'd give the RotateTransform a CenterX of 100 and a CenterY of 75.
When you apply a transform to a brush's RelativeTransform property, that transform is applied to the brush before its output is mapped to the painted area. The following list describes the order in which a brush’s contents are processed and transformed.
Process the brush’s contents. For a GradientBrush, this means determining the gradient area. For a TileBrush, the Viewbox is mapped to the Viewport. This becomes the brush’s output.
Project the brush’s output onto the 1 x 1 transformation rectangle.
Apply the brush’s RelativeTransform, if it has one.
Project the transformed output onto the area to paint.
Apply the brush’s Transform, if it has one.
Because the RelativeTransform is applied while the brush’s output is mapped to a 1 x 1 rectangle, transform center and offset values appear to be relative. For example, if you used a RotateTransform to rotate the brush's output 45 degrees about its center, you'd give the RotateTransform a CenterX of 0.5 and a CenterY of 0.5.
The following illustration shows the output of several brushes that have been rotated by 45 degrees using the RelativeTransform and Transformproperties.
Using RelativeTransform with a TileBrush
Because tile brushes are more complex than other brushes, applying a RelativeTransform to one might produce unexpected results. For example, take the following image.
The following example uses an ImageBrush to paint a rectangular area with the preceding image. It applies a RotateTransform to the ImageBrushobject's RelativeTransform property, and sets its Stretch property to UniformToFill, which should preserve the image's aspect ratio when it is stretched to completely fill the rectangle.
<Rectangle Width="200" Height="100" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <ImageBrush Stretch="UniformToFill"> <ImageBrush.ImageSource> <BitmapImage UriSource="sampleImages\square.jpg" /> </ImageBrush.ImageSource> <ImageBrush.RelativeTransform> <RotateTransform CenterX="0.5" CenterY="0.5" Angle="90" /> </ImageBrush.RelativeTransform> </ImageBrush> </Rectangle.Fill> </Rectangle>
This example produces the following output:
Notice that the image is distorted, even though the brush's Stretch was set to UniformToFill. That's because the relative transform is applied after the brush's Viewbox is mapped to its Viewport. The following list describes each step of the process:
Project the brush's contents (Viewbox) onto its base tile (Viewport) using the brush's Stretch setting.
Project the base tile onto the 1 x 1 transformation rectangle.
Apply the RotateTransform.
Project the transformed base tile onto the area to paint.
Example: Rotate an ImageBrush 45 Degrees
The following example applies a RotateTransform to the RelativeTransform property of an ImageBrush. The RotateTransform object's CenterX and CenterY properties are both set to 0.5, the relative coordinates of the content's center point. As a result, the brush's contents are rotated about its center.
// // Create an ImageBrush with a relative transform and // use it to paint a rectangle. // ImageBrush relativeTransformImageBrush = new ImageBrush(); relativeTransformImageBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative)); // Create a 45 rotate transform about the brush's center // and apply it to the brush's RelativeTransform property. RotateTransform aRotateTransform = new RotateTransform(); aRotateTransform.CenterX = 0.5; aRotateTransform.CenterY = 0.5; aRotateTransform.Angle = 45; relativeTransformImageBrush.RelativeTransform = aRotateTransform; // Use the brush to paint a rectangle. Rectangle relativeTransformImageBrushRectangle = new Rectangle(); relativeTransformImageBrushRectangle.Width = 175; relativeTransformImageBrushRectangle.Height = 90; relativeTransformImageBrushRectangle.Stroke = Brushes.Black; relativeTransformImageBrushRectangle.Fill = relativeTransformImageBrush;
<Rectangle Width="175" Height="90" Stroke="Black"> <Rectangle.Fill> <ImageBrush ImageSource="sampleImages\pinkcherries.jpg"> <ImageBrush.RelativeTransform> <RotateTransform CenterX="0.5" CenterY="0.5" Angle="45" /> </ImageBrush.RelativeTransform> </ImageBrush> </Rectangle.Fill> </Rectangle>
The next example also applies a RotateTransform to an ImageBrush, but uses the Transform property instead of the RelativeTransform property. To rotate the brush about its center, the RotateTransform object's CenterX and CenterY must be set to absolute coordinates. Because the rectangle being painted by the brush is 175 by 90 pixels, its center point is (87.5, 45).
// // Create an ImageBrush with a transform and // use it to paint a rectangle. // ImageBrush transformImageBrush = new ImageBrush(); transformImageBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative)); // Create a 45 rotate transform about the brush's center // and apply it to the brush's Transform property. RotateTransform anotherRotateTransform = new RotateTransform(); anotherRotateTransform.CenterX = 87.5; anotherRotateTransform.CenterY = 45; anotherRotateTransform.Angle = 45; transformImageBrush.Transform = anotherRotateTransform; // Use the brush to paint a rectangle. Rectangle transformImageBrushRectangle = new Rectangle(); transformImageBrushRectangle.Width = 175; transformImageBrushRectangle.Height = 90; transformImageBrushRectangle.Stroke = Brushes.Black; transformImageBrushRectangle.Fill = transformImageBrush;
<Rectangle Width="175" Height="90" Stroke="Black"> <Rectangle.Fill> <ImageBrush ImageSource="sampleImages\pinkcherries.jpg"> <ImageBrush.Transform> <RotateTransform CenterX="87.5" CenterY="45" Angle="45" /> </ImageBrush.Transform> </ImageBrush> </Rectangle.Fill> </Rectangle>
The following illustration shows the brush without a transform, with the transform applied to the RelativeTransform property, and with the transform applied to the Transform property.
This example is part of a larger sample. For the complete sample, see the Brushes Sample. For more information about brushes, see the WPF Brushes Overview.
Opacity Masks Overview
Opacity masks enable you to make portions of an element or visual either transparent or partially transparent. To create an opacity mask, you apply a Brush to the OpacityMask property of an element or Visual. The brush is mapped to the element or visual, and the opacity value of each brush pixel is used to determine the resulting opacity of each corresponding pixel of the element or visual.
This topic contains the following sections.
Prerequisites
This overview assumes that you are familiar with Brush objects. For an introduction to using brushes, see Painting with Solid Colors and Gradients Overview. For information about ImageBrush and DrawingBrush, see Painting with Images, Drawings, and Visuals.
Creating Visual Effects with Opacity Masks
An opacity mask works by mapping its contents to the element or visual. The alpha channel of each of the brush's pixels are then used to determine the resulting opacity of the element or visual's corresponding pixels; the actual color of the brush is ignored. If a given portion of the brush is transparent, the corresponding portion of the element or visual becomes transparent. If a given portion of the brush is opaque, the opacity of the corresponding portion of the element or visual is unchanged. The opacity specified by the opacity mask is combined with any opacity settings present in the element or visual. For example, if an element is 25 percent opaque and an opacity mask is applied that transitions from fully opaque to fully transparent, the result is an element that transitions from 25 percent opacity to fully transparent.
Note |
---|
Although the examples in this overview demonstrate the use of opacity masks on image elements, an opacity mask may be applied to any element or Visual, including panels and controls. |
Opacity masks are used to create interesting visual effects, such as to create images or buttons that fade from view, to add textures to elements, or to combine gradients to produce glass-like surfaces. The following illustration demonstrates the use of an opacity mask. A checkered background is used to show the transparent portions of the mask.
Creating an Opacity Mask
To create an opacity mask, you create a Brush and apply it to the OpacityMask property of an element or visual. You can use any type of Brush as an opacity mask.
LinearGradientBrush, RadialGradientBrush: Used to make an element or visual fade from view.
The following image shows a LinearGradientBrush used as an opacity mask.
ImageBrush: Used to create texture and soft or torn edge effects.
The following image shows an ImageBrush used as an opacity mask.
DrawingBrush: Used to create complex opacity masks from patterns of shapes, images, and gradients.
The following image shows a DrawingBrush used as an opacity mask.
The gradient brushes (LinearGradientBrush and RadialGradientBrush) are particularly well-suited for use as an opacity mask. Because a SolidColorBrush fills an area with a uniform color, they make poor opacity masks; using a SolidColorBrush is equivalent to setting the element's or visual's OpacityMask property.
Using a Gradient as an Opacity Mask
To create a gradient fill, you specify two or more gradient stops. Each gradient stop contains describes a color and a position (see Painting with Solid Colors and Gradients Overview for more information about creating and using gradients). The process is the same when using a gradient as an opacity mask, except that, instead of blending colors, the opacity mask gradient blends alpha channel values. So the actual color of the gradient's contents do not matter; only the alpha channel, or opacity, of each color matters. The following is an example.
<!--With the opacity mask:--> <Image Width="200" Height="150" Source="sampleImages\Waterlilies.jpg" Margin="10" HorizontalAlignment="Left" Grid.Column="2" Grid.Row="3"> <Image.OpacityMask> <LinearGradientBrush StartPoint="0.1,0.1" EndPoint="0.75,0.75"> <LinearGradientBrush.GradientStops> <GradientStop Offset="0" Color="Black"/> <GradientStop Offset="1" Color="Transparent"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Image.OpacityMask> </Image>
Specifying Gradient Stops for an Opacity Mask
In the previous example, the system-defined color Black is used as the starting color of the gradient. Because all of the colors in the Colors class, except Transparent, are fully opaque, they can be used to simply define a starting color for a gradient opacity mask.
For additional control over alpha values when defining an opacity mask, you can specify the alpha channel of colors using ARGB hexadecimal notation in markup or using the Color.FromScRgb method.
Specifying Color Opacity in "XAML"
In Extensible Application Markup Language (XAML), you use ARGB hexadecimal notation to specify the opacity of individual colors. ARGB hexadecimal notation uses the following syntax:
#aarrggbb
The aa in the previous line represents a two-digit hexadecimal value used to specify the opacity of the color. The rr, gg, and bb each represent a two digit hexadecimal value used to specify the amount of red, green, and blue in the color. Each hexadecimal digit may have a value from 0-9 or A-F. 0 is the smallest value, and F is the greatest. An alpha value of 00 specifies a color that is completely transparent, while an alpha value of FF creates a color that is fully opaque. In the following example, hexadecimal ARGB notation is used to specify two colors. The first is fully opaque, while the second is completely transparent.
<Canvas.OpacityMask> <RadialGradientBrush> <RadialGradientBrush.GradientStops> <GradientStop Offset="0" Color="#FF000000"/> <GradientStop Offset="1" Color="#00000000"/> </RadialGradientBrush.GradientStops> </RadialGradientBrush> </Canvas.OpacityMask>
Using an Image as an Opacity Mask
Images can also be used as an opacity mask. The following image shows an example. A checkered background is used to show the transparent portions of the mask.
To use an image as an opacity mask, use an ImageBrush to contain the image. When creating an image to be used as an opacity mask, save the image in a format that supports multiple levels of transparency, such as Portable Network Graphics (PNG). The following example shows the code used to create the previous illustration.
<!-- With the Opacity Mask--> <Image Height="150" Width="200" Source="sampleImages/Waterlilies.jpg" HorizontalAlignment="Left" Margin="10" Grid.Column="2" Grid.Row="1"> <Image.OpacityMask> <ImageBrush ImageSource="sampleImages/tornedges.png"/> </Image.OpacityMask> </Image>
Using a Tiled Image as an Opacity Mask
In the following example, the same image is used with another ImageBrush, but the brush's tiling features are used to produce tiles of the image 50 pixels square.
<!-- With the Opacity Mask --> <Image Height="150" Width="200" Source="sampleImages/Waterlilies.jpg" HorizontalAlignment="Left" Margin="10" Grid.Column="2" Grid.Row="2"> <Image.OpacityMask> <ImageBrush Viewport="0,0,50,50" ViewportUnits="Absolute" TileMode="Tile" ImageSource="sampleImages/tornedges.png"/> </Image.OpacityMask> </Image>
Creating an Opacity Mask from a Drawing
Drawings can be used an opacity mask. The shapes contained within the drawing can themselves be filled with gradients, solid colors, images, or even other drawings. The following image shows an example of a drawing used as an opacity mask. A checkered background is used to show the transparent portions of the mask.
To use a drawing as an opacity mask, use a DrawingBrush to contain the drawing. The following example shows the code used to create the previous illustration:
<!-- With the Opacity Mask--> <Image Grid.Row="4" Grid.Column="5" Height="150" Width="200" Source="sampleImages/Waterlilies.jpg"> <Image.OpacityMask> <DrawingBrush> <DrawingBrush.Drawing> <GeometryDrawing> <GeometryDrawing.Brush> <RadialGradientBrush> <RadialGradientBrush.GradientStops> <GradientStop Offset="0" Color="Black" /> <GradientStop Offset="1" Color="Transparent" /> </RadialGradientBrush.GradientStops> </RadialGradientBrush> </GeometryDrawing.Brush> <GeometryDrawing.Geometry> <RectangleGeometry Rect="0.05,0.05 0.9,0.9" /> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Thickness="0.1" Brush="Black" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Image.OpacityMask> </Image>
Using a Tiled Drawing as an Opacity Mask
Like the ImageBrush, the DrawingBrush can be made to tile its drawing. In the following example, a drawing brush is used to create a tiled opacity mask.
<!-- With the Opacity Mask--> <Button Grid.Row="8" Grid.Column="5" Height="100" Width="200" FontFamily="MS Gothic" FontSize="16"> A Button <Button.OpacityMask> <DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile"> <DrawingBrush.Drawing> <GeometryDrawing> <GeometryDrawing.Brush> <RadialGradientBrush> <RadialGradientBrush.GradientStops> <GradientStop Offset="0" Color="Black" /> <GradientStop Offset="1" Color="Transparent" /> </RadialGradientBrush.GradientStops> </RadialGradientBrush> </GeometryDrawing.Brush> <GeometryDrawing.Geometry> <RectangleGeometry Rect="0.05,0.05 0.9,0.9" /> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Thickness="0.1" Brush="Black" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Button.OpacityMask> </Button>
Painting with Solid Colors and Gradients Overview
This topic describes how to use SolidColorBrush, LinearGradientBrush, and RadialGradientBrush objects to paint with solid colors, linear gradients, and radial gradients.
Painting an Area with a Solid Color
One of the most common operations in any platform is to paint an area with a solid Color. To accomplish this task, Windows Presentation Foundation (WPF) provides the SolidColorBrush class. The following sections describe the different ways to paint with a SolidColorBrush.
Using a SolidColorBrush in "XAML"
To paint an area with a solid color in XAML, use one of the following options.
Select a predefined solid color brush by name. For example, you can set a button's Background to "Red" or "MediumBlue". For a list of other predefined solid color brushes, see the static properties of the Brushes class. The following is an example.
<!-- This button's background is painted with a red SolidColorBrush, described using a named color. --> <Button Background="Red">A Button</Button>
Choose a color from the 32-bit color palette by specifying the amounts of red, green, and blue to combine into a single solid color. The format for specifying a color from the 32-bit palette is "#rrggbb", where rr is a two digit hexadecimal number specifying the relative amount of red, gg specifies the amount of green, and bb specifies the amount of blue. Additionally, the color can be specified as "#aarrggbb" where aa specifies the alpha value, or transparency, of the color. This approach enables you to create colors that are partially transparent. In the following example, the Background of a Button is set to fully-opaque red using hexadecimal notation.
<!-- This button's background is painted with a red SolidColorBrush, described using hexadecimal notation. --> <Button Background="#FFFF0000">A Button</Button>
Use property tag syntax to describe a SolidColorBrush. This syntax is more verbose but enables you to specify additional settings, such as the brush's opacity. In the following example, the Background properties of two Button elements are set to fully-opaque red. The first brush's color is described using a predefined color name. The second brush's color is described using hexadecimal notation.
<!-- Both of these buttons' backgrounds are painted with red SolidColorBrush objects, described using object element syntax. --> <Button>A Button <Button.Background> <SolidColorBrush Color="Red" /> </Button.Background> </Button> <Button>A Button <Button.Background> <SolidColorBrush Color="#FFFF0000" /> </Button.Background> </Button>
Painting with a SolidColorBrush in Code
To paint an area with a solid color in code, use one of the following options.
Use one of the predefined brushes provided by the Brushes class. In the following example, the Background of a Button is set to Red.
Button myButton = new Button(); myButton.Content = "A Button"; myButton.Background = Brushes.Red;
Create a SolidColorBrush and set its Color property using a Color structure. You can use a predefined color from the Colors class or you can create a Color using the static FromArgb method.
The following example shows how to set the Color property of a SolidColorBrush using a predefined color.
Button myButton = new Button(); myButton.Content = "A Button"; SolidColorBrush mySolidColorBrush = new SolidColorBrush(); mySolidColorBrush.Color = Colors.Red; myButton.Background = mySolidColorBrush;
The static FromArgb enables you to specify the color's alpha, red, green, and blue values. The typical range for each of these values is 0-255. For example, an alpha value of 0 indicates that a color is completely transparent, while a value of 255 indicates the color is completely opaque. Likewise, a red value of 0 indicates that a color has no red in it, while a value of 255 indicates a color has the maximum amount of red possible. In the following example, a brush's color is described by specifying alpha, red, green, and blue values.
Button myButton = new Button(); myButton.Content = "A Button"; SolidColorBrush mySolidColorBrush = new SolidColorBrush(); mySolidColorBrush.Color = Color.FromArgb( 255, // Specifies the transparency of the color. 255, // Specifies the amount of red. 0, // specifies the amount of green. 0); // Specifies the amount of blue. myButton.Background = mySolidColorBrush;
For additional ways to specify color, see the Color reference topic.
Painting an Area with a Gradient
A gradient brush paints an area with multiple colors that blend into each other along an axis. You can use them to create impressions of light and shadow, giving your controls a three-dimensional feel. You can also use them to simulate glass, chrome, water, and other smooth surfaces. WPF provides two types of gradient brushes: LinearGradientBrush and RadialGradientBrush.
Linear Gradients
A LinearGradientBrush paints an area with a gradient defined along a line, the gradient axis. You specify the gradient's colors and their location along the gradient axis using GradientStop objects. You may also modify the gradient axis, which enables you to create horizontal and vertical gradients and to reverse the gradient direction. The gradient axis is described in the next section. By default, a diagonal gradient is created.
The following example shows the code that creates a linear gradient with four colors.
<!-- This rectangle is painted with a diagonal linear gradient. --> <Rectangle Width="200" Height="100"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
Rectangle diagonalFillRectangle = new Rectangle(); diagonalFillRectangle.Width = 200; diagonalFillRectangle.Height = 100; // Create a diagonal linear gradient with four stops. LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(); myLinearGradientBrush.StartPoint = new Point(0,0); myLinearGradientBrush.EndPoint = new Point(1,1); myLinearGradientBrush.GradientStops.Add( new GradientStop(Colors.Yellow, 0.0)); myLinearGradientBrush.GradientStops.Add( new GradientStop(Colors.Red, 0.25)); myLinearGradientBrush.GradientStops.Add( new GradientStop(Colors.Blue, 0.75)); myLinearGradientBrush.GradientStops.Add( new GradientStop(Colors.LimeGreen, 1.0)); // Use the brush to paint the rectangle. diagonalFillRectangle.Fill = myLinearGradientBrush;
This code produces the following gradient:
Note: The gradient examples in this topic use the default coordinate system for setting start points and end points. The default coordinate system is relative to a bounding box: 0 indicates 0 percent of the bounding box and 1 indicates 100 percent of the bounding box. You can change this coordinate system by setting the MappingMode property to the value Absolute. An absolute coordinate system is not relative to a bounding box. Values are interpreted directly in local space.
The GradientStop is the basic building block of a gradient brush. A gradient stop specifies a Color at an Offset along the gradient axis.
The gradient stop's Color property specifies the color of the gradient stop. You may set the color by using a predefined color (provided by the Colors class) or by specifying ScRGB or ARGB values. In XAML, you may also use hexadecimal notation to describe a color. For more information, see the Color structure.
The gradient stop's Offset property specifies the position of the gradient stop's color on the gradient axis. The offset is a Double that ranges from 0 to 1. The closer a gradient stop's offset value is to 0, the closer the color is to the start of the gradient. The closer the gradient's offset value is to 1, the closer the color is to the end of the gradient.
The color of each point between gradient stops is linearly interpolated as a combination of the color specified by the two bounding gradient stops. The following illustration highlights the gradient stops in the previous example. The circles mark the position of gradient stops and a dashed line shows the gradient axis.
The first gradient stop specifies the color yellow at an offset of 0.0. The second gradient stop specifies the color red at an offset of 0.25. The points between these two stops gradually change from yellow to red as you move from left to right along the gradient axis. The third gradient stop specifies the color blue at an offset of 0.75. The points between the second and third gradient stops gradually change from red to blue. The fourth gradient stop specifies the color lime green at an offset of 1.0. The points between the third and fourth gradient stops gradually change from blue to lime green.
The Gradient Axis
As previously mentioned, a linear gradient brush's gradient stops are positioned along a line, the gradient axis. You may change the orientation and size of the line using the brush's StartPoint and EndPoint properties. By manipulating the brush's StartPoint and EndPoint, you can create horizontal and vertical gradients, reverse the gradient direction, condense the gradient spread, and more.
By default, the linear gradient brush's StartPoint and EndPoint are relative to the area being painted. The point (0,0) represents the upper-left corner of the area being painted, and (1,1) represents the lower-right corner of the area being painted. The default StartPoint of a LinearGradientBrush is (0,0), and its default EndPoint is (1,1), which creates a diagonal gradient starting at the upper-left corner and extending to the lower-right corner of the area being painted. The following illustration shows the gradient axis of a linear gradient brush with default StartPoint and EndPoint.
The following example shows how to create a horizontal gradient by specifying the brush's StartPoint and EndPoint. Notice that the gradient stops are the same as in the previous examples; by simply changing the StartPoint and EndPoint, the gradient has been changed from diagonal to horizontal.
<!-- This rectangle is painted with a horizontal linear gradient. --> <Rectangle Width="200" Height="100"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5"> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
Rectangle horizontalFillRectangle = new Rectangle(); horizontalFillRectangle.Width = 200; horizontalFillRectangle.Height = 100; // Create a horizontal linear gradient with four stops. LinearGradientBrush myHorizontalGradient = new LinearGradientBrush(); myHorizontalGradient.StartPoint = new Point(0,0.5); myHorizontalGradient.EndPoint = new Point(1,0.5); myHorizontalGradient.GradientStops.Add( new GradientStop(Colors.Yellow, 0.0)); myHorizontalGradient.GradientStops.Add( new GradientStop(Colors.Red, 0.25)); myHorizontalGradient.GradientStops.Add( new GradientStop(Colors.Blue, 0.75)); myHorizontalGradient.GradientStops.Add( new GradientStop(Colors.LimeGreen, 1.0)); // Use the brush to paint the rectangle. horizontalFillRectangle.Fill = myHorizontalGradient;
The following illustration shows the gradient that is created. The gradient axis is marked with a dashed line, and the gradient stops are marked with circles.
The next example shows how to create a vertical gradient.
<!-- This rectangle is painted with a vertical gradient. --> <Rectangle Width="200" Height="100"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
Rectangle verticalFillRectangle = new Rectangle(); verticalFillRectangle.Width = 200; verticalFillRectangle.Height = 100; // Create a vertical linear gradient with four stops. LinearGradientBrush myVerticalGradient = new LinearGradientBrush(); myVerticalGradient.StartPoint = new Point(0.5,0); myVerticalGradient.EndPoint = new Point(0.5,1); myVerticalGradient.GradientStops.Add( new GradientStop(Colors.Yellow, 0.0)); myVerticalGradient.GradientStops.Add( new GradientStop(Colors.Red, 0.25)); myVerticalGradient.GradientStops.Add( new GradientStop(Colors.Blue, 0.75)); myVerticalGradient.GradientStops.Add( new GradientStop(Colors.LimeGreen, 1.0)); // Use the brush to paint the rectangle. verticalFillRectangle.Fill = myVerticalGradient;
The following illustration shows the gradient that is created. The gradient axis is marked with a dashed line, and the gradient stops are marked with circles.
Radial Gradients
Like a LinearGradientBrush, a RadialGradientBrush paints an area with colors that blend together along an axis. The previous examples showed how a linear gradient brush's axis is a straight line. A radial gradient brush's axis is defined by a circle; its colors "radiate" outward from its origin.
In the following example, a radial gradient brush is used to paint the interior of a rectangle.
<!-- This rectangle is painted with a diagonal linear gradient. --> <Rectangle Width="200" Height="100"> <Rectangle.Fill> <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5"> <GradientStop Color="Yellow" Offset="0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1" /> </RadialGradientBrush> </Rectangle.Fill> </Rectangle>
RadialGradientBrush myRadialGradientBrush = new RadialGradientBrush(); myRadialGradientBrush.GradientOrigin = new Point(0.5,0.5); myRadialGradientBrush.Center = new Point(0.5,0.5); myRadialGradientBrush.RadiusX = 0.5; myRadialGradientBrush.RadiusY = 0.5; myRadialGradientBrush.GradientStops.Add( new GradientStop(Colors.Yellow, 0.0)); myRadialGradientBrush.GradientStops.Add( new GradientStop(Colors.Red, 0.25)); myRadialGradientBrush.GradientStops.Add( new GradientStop(Colors.Blue, 0.75)); myRadialGradientBrush.GradientStops.Add( new GradientStop(Colors.LimeGreen, 1.0)); Rectangle myRectangle = new Rectangle(); myRectangle.Width = 200; myRectangle.Height = 100; myRectangle.Fill = myRadialGradientBrush;
The following illustration shows the gradient created in the previous example. The brush's gradient stops have been highlighted. Notice that, even though the results are different, the gradient stops in this example are identical to the gradient stops in the previous linear gradient brush examples.
The GradientOrigin specifies the start point of a radial gradient brush's gradient axis. The gradient axis radiates from the gradient origin to the gradient circle. A brush's gradient circle is defined by its Center, RadiusX, and RadiusY properties.
The following illustration shows several radial gradients with different GradientOrigin, Center, RadiusX, and RadiusY settings.
Specifying Transparent or Partially-Transparent Gradient Stops
Because gradient stops do not provide an opacity property, you must specify the alpha channel of colors using ARGB hexadecimal notation in markup or use the Color.FromScRgb method to create gradient stops that are transparent or partially transparent. The following sections explain how to create partially transparent gradient stops in XAML and code. For information about setting the opacity of the entire brush, see the Specifying the Opacity of a Brush section.
Specifying Color Opacity in "XAML"
In XAML, you use ARGB hexadecimal notation to specify the opacity of individual colors. ARGB hexadecimal notation uses the following syntax:
#aarrggbb
The aa in the previous line represents a two-digit hexadecimal value used to specify the opacity of the color. The rr, gg, and bb each represent a two digit hexadecimal value used to specify the amount of red, green, and blue in the color. Each hexadecimal digit may have a value from 0-9 or A-F. 0 is the smallest value, and F is the greatest. An alpha value of 00 specifies a color that is completely transparent, while an alpha value of FF creates a color that is fully opaque. In the following example, hexadecimal ARGB notation is used to specify two colors. The first is partially transparent (it has an alpha value of x20), while the second is completely opaque.
<Rectangle Width="100" Height="100"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0,0"> <!-- This gradient stop is partially transparent. --> <GradientStop Color="#200000FF" Offset="0.0" /> <!-- This gradient stop is fully opaque. --> <GradientStop Color="#FF0000FF" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
Specifying Color Opacity in Code
When using code, the static FromArgb method enables you to specify an alpha value when you create a color. The method takes four parameters of type Byte. The first parameter specifies the alpha channel of the color; the other three parameters specify the red, green, and blue values of the color. Each value should be between 0 to 255, inclusive. An alpha value of 0 specifies that the color is completely transparent, while an alpha value of 255 specifies that the color is completely opaque. In the following example, the FromArgb method is used to produce two colors. The first color is partially transparent (it has an alpha value of 32), while the second is fully opaque.
LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(); // This gradient stop is partially transparent. myLinearGradientBrush.GradientStops.Add( new GradientStop(Color.FromArgb(32, 0, 0, 255), 0.0)); // This gradient stop is fully opaque. myLinearGradientBrush.GradientStops.Add( new GradientStop(Color.FromArgb(255, 0, 0, 255), 1.0)); Rectangle myRectangle = new Rectangle(); myRectangle.Width = 100; myRectangle.Height = 100; myRectangle.Fill = myLinearGradientBrush;
Alternatively, you may use the FromScRgb method, which enables you to use ScRGB values to create a color.
Painting with Images, Drawings, Visuals, and Patterns
ImageBrush, DrawingBrush, and VisualBrush classes enable you to paint an area with images, drawings, or visuals. For information about painting with images, drawings, and patterns, see Painting with Images, Drawings, and Visuals.
Painting with Images, Drawings, and Visuals
This topic describes how to use ImageBrush, DrawingBrush, and VisualBrush objects to paint an area with an image, a Drawing, or a Visual.
Prerequisites
To understand this topic, you should be familiar with the different types of brushes Windows Presentation Foundation (WPF) provides and their basic features. For an introduction, see the WPF Brushes Overview.
Paint an Area with an Image
An ImageBrush paints an area with an ImageSource. The most common type of ImageSource to use with an ImageBrush is a BitmapImage, which describes a bitmap graphic. You can use a DrawingImage to paint using a Drawing object, but it is simpler to use a DrawingBrush instead. For more information about ImageSource objects, see the Imaging Overview.
To paint with an ImageBrush, create a BitmapImage and use it to load the bitmap content. Then, use the BitmapImage to set the ImageSource property of the ImageBrush. Finally, apply the ImageBrush to the object you want to paint. In Extensible Application Markup Language (XAML), you can also just set the ImageSource property of the ImageBrush with the path of the image to load.
Like all Brush objects, an ImageBrush can be used to paint objects such as shapes, panels, controls, and text. The following illustration shows some effects that can be achieved with an ImageBrush.
By default, an ImageBrush stretches its image to completely fill the area being painted, possibly distorting the image if the painted area has a different aspect ratio than the image. You can change this behavior by changing the Stretch property from its default value of Fill to None, Uniform, or UniformToFill. Because ImageBrush is a type of TileBrush, you can specify exactly how an image brush fills the output area and even create patterns. For more information about advanced TileBrush features, see the TileBrush Overview.
Example: Paint an Object with a Bitmap Image
The following example uses an ImageBrush to paint the Background of a Canvas.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Microsoft.Samples.BrushExamples.ImageBrushExample" WindowTitle="ImageBrush Example" Background="White"> <StackPanel> <Canvas Height="200" Width="300"> <Canvas.Background> <ImageBrush ImageSource="sampleImages\Waterlilies.jpg" /> </Canvas.Background> </Canvas> </StackPanel> </Page>
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; namespace Microsoft.Samples.BrushExamples { public class ImageBrushExample : Page { public ImageBrushExample() { StackPanel mainPanel = new StackPanel(); canvasBackgroundExample(mainPanel); this.Content = mainPanel; } private void canvasBackgroundExample(Panel mainPanel) { BitmapImage theImage = new BitmapImage (new Uri("sampleImages\\Waterlilies.jpg", UriKind.Relative)); ImageBrush myImageBrush = new ImageBrush(theImage); Canvas myCanvas = new Canvas(); myCanvas.Width = 300; myCanvas.Height = 200; myCanvas.Background = myImageBrush; mainPanel.Children.Add(myCanvas); } } }
Paint an Area with a Drawing
A DrawingBrush enables you to paint an area with shapes, text, images, and video. Shapes inside a drawing brush may themselves be painted with a solid color, gradient, image, or even another DrawingBrush. The following illustration demonstrates some uses of a DrawingBrush.
A DrawingBrush paints an area with a Drawing object. A Drawing object describes visible content, such as a shape, bitmap, video, or a line of text. Different types of drawings describe different types of content. The following is a list of the different types of drawing objects.
GeometryDrawing – Draws a shape.
ImageDrawing – Draws an image.
GlyphRunDrawing – Draws text.
VideoDrawing – Plays an audio or video file.
DrawingGroup – Draws other drawings. Use a drawing group to combine other drawings into a single composite drawing.
For more information about Drawing objects, see the Drawing Objects Overview.
Like an ImageBrush, a DrawingBrush stretches its Drawing to fill its output area. You can override this behavior by changing the Stretch property from its default setting of Fill. For more information, see the Stretch property.
Example: Paint an Object with a Drawing
The following example shows how to paint an object with a drawing of three ellipses. A GeometryDrawing is used to describe the ellipses.
<Button Content="A Button"> <Button.Background> <DrawingBrush> <DrawingBrush.Drawing> <GeometryDrawing Brush="LightBlue"> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry RadiusX="12.5" RadiusY="25" Center="25,50" /> <EllipseGeometry RadiusX="12.5" RadiusY="25" Center="50,50" /> <EllipseGeometry RadiusX="12.5" RadiusY="25" Center="75,50" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Thickness="1" Brush="Gray" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Button.Background> </Button>
// Create a DrawingBrush. DrawingBrush myDrawingBrush = new DrawingBrush(); // Create a drawing. GeometryDrawing myGeometryDrawing = new GeometryDrawing(); myGeometryDrawing.Brush = Brushes.LightBlue; myGeometryDrawing.Pen = new Pen(Brushes.Gray, 1); GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add(new EllipseGeometry(new Point(25,50), 12.5, 25)); ellipses.Children.Add(new EllipseGeometry(new Point(50,50), 12.5, 25)); ellipses.Children.Add(new EllipseGeometry(new Point(75,50), 12.5, 25)); myGeometryDrawing.Geometry = ellipses; myDrawingBrush.Drawing = myGeometryDrawing; Button myButton = new Button(); myButton.Content = "A Button"; // Use the DrawingBrush to paint the button's background. myButton.Background = myDrawingBrush;
Paint an Area with a Visual
The most versatile and powerful of all the brushes, the VisualBrush paints an area with a Visual. A Visual is a low-level graphical type that serves as the ancestor of many useful graphical components. For example, the Window, FrameworkElement, and Control classes are all types of Visual objects. Using a VisualBrush, you can paint areas with almost any Windows Presentation Foundation (WPF) graphical object.
Note |
---|
Although VisualBrush is a type of Freezable object, it cannot be frozen (made read-only) when its Visual property is set to a value other than null. |
There are two ways to specify the Visual content of a VisualBrush.
Create a new Visual and use it to set the Visual property of the VisualBrush. For an example, see the Example: Paint an Object with a Visual section that follows.
Use an existing Visual, which creates a duplicate image of the target Visual. You can then use the VisualBrush to create interesting effects, such as reflection and magnification. For an example, see the Example: Create a Reflection section.
When you define a new Visual for a VisualBrush and that Visual is a UIElement (such as a panel or control), the layout system runs on the UIElement and its child elements when the AutoLayoutContent property is set to true. However, the root UIElement is essentially isolated from the rest of the system: styles, and external layout can't permeate this boundary. Therefore, you should explicitly specify the size of the root UIElement, because its only parent is the VisualBrush and therefore it cannot automatically size itself to the area being painted. For more information about layout in Windows Presentation Foundation (WPF), see the Layout.
Like ImageBrush and DrawingBrush, a VisualBrush stretches its content to fill its output area. You can override this behavior by changing the Stretch property from its default setting of Fill. For more information, see the Stretch property.
Example: Paint an Object with a Visual
In the following example, several controls and a panel are used to paint a rectangle.
<Rectangle Width="150" Height="150" Stroke="Black" Margin="5,0,5,0"> <Rectangle.Fill> <VisualBrush> <VisualBrush.Visual> <StackPanel Background="White"> <Rectangle Width="25" Height="25" Fill="Red" Margin="2" /> <TextBlock FontSize="10pt" Margin="2">Hello, World!</TextBlock> <Button Margin="2">A Button</Button> </StackPanel> </VisualBrush.Visual> </VisualBrush> </Rectangle.Fill> </Rectangle>
VisualBrush myVisualBrush = new VisualBrush(); // Create the visual brush's contents. StackPanel myStackPanel = new StackPanel(); myStackPanel.Background = Brushes.White; Rectangle redRectangle = new Rectangle(); redRectangle.Width = 25; redRectangle.Height =25; redRectangle.Fill = Brushes.Red; redRectangle.Margin = new Thickness(2); myStackPanel.Children.Add(redRectangle); TextBlock someText = new TextBlock(); FontSizeConverter myFontSizeConverter = new FontSizeConverter(); someText.FontSize = (double)myFontSizeConverter.ConvertFrom("10pt"); someText.Text = "Hello, World!"; someText.Margin = new Thickness(2); myStackPanel.Children.Add(someText); Button aButton = new Button(); aButton.Content = "A Button"; aButton.Margin = new Thickness(2); myStackPanel.Children.Add(aButton); // Use myStackPanel as myVisualBrush's content. myVisualBrush.Visual = myStackPanel; // Create a rectangle to paint. Rectangle myRectangle = new Rectangle(); myRectangle.Width = 150; myRectangle.Height = 150; myRectangle.Stroke = Brushes.Black; myRectangle.Margin = new Thickness(5,0,5,0); // Use myVisualBrush to paint myRectangle. myRectangle.Fill = myVisualBrush;
Example: Create a Reflection
The preceding example showed how to create a new Visual for use as a background. You can also use a VisualBrush to display an existing visual; this capability enables you to produce interesting visual effects, such as reflections and magnification. The following example uses a VisualBrush to create a reflection of a Border that contains several elements. The following illustration shows the output that this example produces.
using System; using System.Windows; using System.Windows.Data; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Effects; using System.Windows.Media.Imaging; using System.IO; using System.Collections.ObjectModel; using System.Windows.Shapes; namespace SDKSample { public partial class ReflectionExample : Page { public ReflectionExample() { // Create a name scope for the page. NameScope.SetNameScope(this, new NameScope()); this.Background = Brushes.Black; StackPanel myStackPanel = new StackPanel(); myStackPanel.Margin = new Thickness(50); Border myReflectedBorder = new Border(); this.RegisterName("ReflectedVisual", myReflectedBorder); // Create a gradient background for the border. GradientStop firstStop = new GradientStop(); firstStop.Offset = 0.0; Color firstStopColor = new Color(); firstStopColor.R = 204; firstStopColor.G = 204; firstStopColor.B = 255; firstStopColor.A = 255; firstStop.Color = firstStopColor; GradientStop secondStop = new GradientStop(); secondStop.Offset = 1.0; secondStop.Color = Colors.White; GradientStopCollection myGradientStopCollection = new GradientStopCollection(); myGradientStopCollection.Add(firstStop); myGradientStopCollection.Add(secondStop); LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(); myLinearGradientBrush.StartPoint = new Point(0, 0.5); myLinearGradientBrush.EndPoint = new Point(1, 0.5); myLinearGradientBrush.GradientStops = myGradientStopCollection; myReflectedBorder.Background = myLinearGradientBrush; // Add contents to the border. StackPanel borderStackPanel = new StackPanel(); borderStackPanel.Orientation = Orientation.Horizontal; borderStackPanel.Margin = new Thickness(10); TextBlock myTextBlock = new TextBlock(); myTextBlock.TextWrapping = TextWrapping.Wrap; myTextBlock.Width = 200; myTextBlock.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." + " Suspendisse vel ante. Donec luctus tortor sit amet est." + " Nullam pulvinar odio et wisi." + " Pellentesque quis magna. Sed pellentesque." + " Nulla euismod." + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."; borderStackPanel.Children.Add(myTextBlock); StackPanel ellipseStackPanel = new StackPanel(); Ellipse ellipse1 = new Ellipse(); ellipse1.Margin = new Thickness(10); ellipse1.Height = 50; ellipse1.Width = 50; ellipse1.Fill = Brushes.Black; ellipseStackPanel.Children.Add(ellipse1); Ellipse ellipse2 = new Ellipse(); ellipse2.Margin = new Thickness(10); ellipse2.Height = 50; ellipse2.Width = 50; ellipse2.Fill = Brushes.Black; ellipseStackPanel.Children.Add(ellipse2); Ellipse ellipse3 = new Ellipse(); ellipse3.Margin = new Thickness(10); ellipse3.Height = 50; ellipse3.Width = 50; ellipse3.Fill = Brushes.Black; ellipseStackPanel.Children.Add(ellipse3); borderStackPanel.Children.Add(ellipseStackPanel); myReflectedBorder.Child = borderStackPanel; // Create divider rectangle Rectangle dividerRectangle = new Rectangle(); dividerRectangle.Height = 1; dividerRectangle.Fill = Brushes.Gray; dividerRectangle.HorizontalAlignment = HorizontalAlignment.Stretch; // Create the object to contain the reflection. Rectangle reflectionRectangle = new Rectangle(); // Bind the height of the rectangle to the border height. Binding heightBinding = new Binding(); heightBinding.ElementName = "ReflectedVisual"; heightBinding.Path = new PropertyPath(Rectangle.HeightProperty); BindingOperations.SetBinding(reflectionRectangle, Rectangle.HeightProperty, heightBinding); // Bind the width of the rectangle to the border width. Binding widthBinding = new Binding(); widthBinding.ElementName = "ReflectedVisual"; widthBinding.Path = new PropertyPath(Rectangle.WidthProperty); BindingOperations.SetBinding(reflectionRectangle, Rectangle.WidthProperty, widthBinding); // Creates the reflection. VisualBrush myVisualBrush = new VisualBrush(); myVisualBrush.Opacity = 0.75; myVisualBrush.Stretch = Stretch.None; Binding reflectionBinding = new Binding(); reflectionBinding.ElementName = "ReflectedVisual"; BindingOperations.SetBinding(myVisualBrush, VisualBrush.VisualProperty, reflectionBinding); ScaleTransform myScaleTransform = new ScaleTransform(); myScaleTransform.ScaleX = 1; myScaleTransform.ScaleY = -1; TranslateTransform myTranslateTransform = new TranslateTransform(); myTranslateTransform.Y = 1; TransformGroup myTransformGroup = new TransformGroup(); myTransformGroup.Children.Add(myScaleTransform); myTransformGroup.Children.Add(myTranslateTransform); myVisualBrush.RelativeTransform = myTransformGroup; reflectionRectangle.Fill = myVisualBrush; // Create a gradient background for the border. GradientStop firstStop2 = new GradientStop(); firstStop2.Offset = 0.0; Color c1 = new Color(); c1.R = 0; c1.G = 0; c1.B = 0; c1.A = 255; firstStop2.Color = c1; GradientStop secondStop2 = new GradientStop(); secondStop2.Offset = 0.5; Color c2 = new Color(); c2.R = 0; c2.G = 0; c2.B = 0; c2.A = 51; firstStop2.Color = c2; GradientStop thirdStop = new GradientStop(); thirdStop.Offset = 0.75; Color c3 = new Color(); c3.R = 0; c3.G = 0; c3.B = 0; c3.A = 0; thirdStop.Color = c3; GradientStopCollection myGradientStopCollection2 = new GradientStopCollection(); myGradientStopCollection2.Add(firstStop2); myGradientStopCollection2.Add(secondStop2); myGradientStopCollection2.Add(thirdStop); LinearGradientBrush myLinearGradientBrush2 = new LinearGradientBrush(); myLinearGradientBrush2.StartPoint = new Point(0.5, 0); myLinearGradientBrush2.EndPoint = new Point(0.5, 1); myLinearGradientBrush2.GradientStops = myGradientStopCollection2; reflectionRectangle.OpacityMask = myLinearGradientBrush2; BlurBitmapEffect myBlurBitmapEffect = new BlurBitmapEffect(); myBlurBitmapEffect.Radius = 1.5; reflectionRectangle.BitmapEffect = myBlurBitmapEffect; myStackPanel.Children.Add(myReflectedBorder); myStackPanel.Children.Add(dividerRectangle); myStackPanel.Children.Add(reflectionRectangle); this.Content = myStackPanel; } /* <Rectangle Height="{Binding Path=ActualHeight, ElementName=ReflectedVisual}" Width="{Binding Path=ActualWidth, ElementName=ReflectedVisual}"> <Rectangle.OpacityMask> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Color="#FF000000" Offset="0.0" /> <GradientStop Color="#33000000" Offset="0.5" /> <GradientStop Color="#00000000" Offset="0.75" /> </LinearGradientBrush> </Rectangle.OpacityMask> <Rectangle.BitmapEffect> <BlurBitmapEffect Radius="1.5" /> </Rectangle.BitmapEffect> </Rectangle> </StackPanel> </Page> */ } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="Black"> <StackPanel Margin="50"> <!-- The object to reflect. --> <Border Name="ReflectedVisual" Width="400"> <Border.Background> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5"> <GradientStop Offset="0.0" Color="#CCCCFF" /> <GradientStop Offset="1.0" Color="White" /> </LinearGradientBrush> </Border.Background> <StackPanel Orientation="Horizontal" Margin="10"> <TextBlock TextWrapping="Wrap" Width="200" Margin="10"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Suspendisse vel ante. Donec luctus tortor sit amet est. Nullam pulvinar odio et wisi. Pellentesque quis magna. Sed pellentesque. Nulla euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. </TextBlock> <StackPanel> <Ellipse Margin="10" Height="50" Width="50" Fill="Black" /> <Ellipse Margin="10" Height="50" Width="50" Fill="Black" /> <Ellipse Margin="10" Height="50" Width="50" Fill="Black" /> </StackPanel> </StackPanel> </Border> <Rectangle Height="1" Fill="Gray" HorizontalAlignment="Stretch" /> <!-- The object to contain the reflection.--> <Rectangle Height="{Binding Path=ActualHeight, ElementName=ReflectedVisual}" Width="{Binding Path=ActualWidth, ElementName=ReflectedVisual}"> <Rectangle.Fill> <!-- Creates the reflection. --> <VisualBrush Opacity="0.75" Stretch="None" Visual="{Binding ElementName=ReflectedVisual}"> <VisualBrush.RelativeTransform> <!-- Flip the reflection. --> <TransformGroup> <ScaleTransform ScaleX="1" ScaleY="-1" /> <TranslateTransform Y="1" /> </TransformGroup> </VisualBrush.RelativeTransform> </VisualBrush> </Rectangle.Fill> <Rectangle.OpacityMask> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Color="#FF000000" Offset="0.0" /> <GradientStop Color="#33000000" Offset="0.5" /> <GradientStop Color="#00000000" Offset="0.75" /> </LinearGradientBrush> </Rectangle.OpacityMask> <Rectangle.BitmapEffect> <BlurBitmapEffect Radius="1.5" /> </Rectangle.BitmapEffect> </Rectangle> </StackPanel> </Page>
For additional examples that show how to magnify portions of the screen and how to create reflections, see the VisualBrush Sample.
TileBrush Features
ImageBrush, DrawingBrush, and VisualBrush are types of TileBrush objects. TileBrush objects provide you with a great deal of control over how an area is painted with an image, drawing, or visual. For example, instead of just painting an area with a single stretched image, you can paint an area with a series of image tiles that create a pattern.
A TileBrush has three primary components: content, tiles, and the output area.
For more information about the tiling features of TileBrush objects, see the TileBrush Overview.
TileBrush Overview
TileBrush objects provide you with a great deal of control over how an area is painted with an image, Drawing, or Visual. This topic describes how to useTileBrush features to gain more control over how an ImageBrush, DrawingBrush, or VisualBrush paints an area.
Prerequisites
To understand this topic, it's helpful to understand how to use the basic features of the ImageBrush, DrawingBrush, or VisualBrush class. For an introduction to these types, see the Painting with Images, Drawings, and Visuals.
Painting an Area with Tiles
ImageBrush, DrawingBrush, are VisualBrush are types of TileBrush objects. Tile brushes provide you with a great deal of control over how an area is painted with an image, drawing, or visual. For example, instead of just painting an area with a single stretched image, you can paint an area with a series of image tiles that create a pattern.
Painting an area with a tile brush involves three components: content, the base tile, and the output area.
The output area is the area being painted, such as the Fill of an Ellipse or the Background of a Button. The next sections describe the other two components of a TileBrush.
Brush Content
There are three different types of TileBrush and each paints with a different type of content.
If the brush is an ImageBrush, this content is an image The ImageSource property specifies the contents of the ImageBrush.
If the brush is a DrawingBrush, this content is a drawing. The Drawing property specifies the contents of the DrawingBrush.
If the brush is a VisualBrush, this content is a visual. The Visual property specifies the content of the VisualBrush.
You can specify the position and dimensions of TileBrush content by using the Viewbox property, although it is common to leave the Viewbox set to its default value. By default, the Viewbox is configured to completely contain the brush's contents. For more information about configuring theViewbox, see the Viewbox property page.
The Base Tile
A TileBrush projects its content onto a base tile. The Stretch property controls how TileBrush content is stretched to fill the base tile. The Stretchproperty accepts the following values, defined by the Stretch enumeration:
None: The brush's content is not stretched to fill the tile.
Fill: The brush's content is scaled to fit the tile. Because the content's height and width are scaled independently, the original aspect ratio of the content might not be preserved. That is, the brush's content might be warped in order to completely fill the output tile.
Uniform: The brush's content is scaled so that it fits completely within the tile. The content's aspect ratio is preserved.
UniformToFill: The brush's content is scaled so that it completely fills the output area while preserving the content's original aspect ratio.
The following image illustrates the different Stretch settings.
In the following example, the content of an ImageBrush is set so that it does not stretch to fill the output area.
<Rectangle Width="125" Height="175" Stroke="Black" StrokeThickness="1" Margin="0,0,5,0"> <Rectangle.Fill> <ImageBrush Stretch="None" ImageSource="sampleImages\testImage.gif"/> </Rectangle.Fill> </Rectangle>
// Create a rectangle. Rectangle myRectangle = new Rectangle(); myRectangle.Width = 125; myRectangle.Height = 175; myRectangle.Stroke = Brushes.Black; myRectangle.StrokeThickness = 1; myRectangle.Margin = new Thickness(0,5,0,0); // Load the image. BitmapImage theImage = new BitmapImage( new Uri("sampleImages\\testImage.gif", UriKind.Relative)); ImageBrush myImageBrush = new ImageBrush(theImage); // Configure the brush so that it // doesn't stretch its image to fill // the rectangle. myImageBrush.Stretch = Stretch.None; // Use the ImageBrush to paint the rectangle's background. myRectangle.Fill = myImageBrush;
By default, a TileBrush generates a single tile (the base tile) and stretches that tile to completely fill the output area. You can change the size and position of the base tile by setting the Viewport and ViewportUnits properties.
Base Tile Size
The Viewport property determines the size and position of the base tile, and the ViewportUnits property determines whether the Viewport is specified using absolute or relative coordinates. If the coordinates are relative, they are relative to the size of the output area. The point (0,0) represents the top left corner of the output area, and (1,1) represents the bottom right corner of the output area. To specify that the Viewportproperty uses absolute coordinates, set the ViewportUnits property to Absolute.
The following illustration shows the difference in output between a TileBrush with relative versus absolute ViewportUnits. Notice that the illustrations each show a tiled pattern; the next section describes how to specify tile pattern.
In the following example, an image is used to create a tile that has a width and height of 50%. The base tile is located at (0,0) of the output area.
<Rectangle Width="50" Height="100"> <Rectangle.Fill> <!-- Paints an area with 4 tiles. --> <ImageBrush ImageSource="sampleImages\cherries_larger.jpg" Viewport="0,0,0.5,0.5" ViewportUnits="RelativeToBoundingBox" TileMode="Tile" /> </Rectangle.Fill> </Rectangle>
// Create a rectangle. Rectangle myRectangle = new Rectangle(); myRectangle.Width = 50; myRectangle.Height = 100; // Load the image. BitmapImage theImage = new BitmapImage( new Uri("sampleImages\\cherries_larger.jpg", UriKind.Relative)); ImageBrush myImageBrush = new ImageBrush(theImage); // Create tiles that are 1/4 the size of // the output area. myImageBrush.Viewport = new Rect(0,0,0.25,0.25); myImageBrush.ViewportUnits = BrushMappingMode.RelativeToBoundingBox; // Set the tile mode to Tile. myImageBrush.TileMode = TileMode.Tile; // Use the ImageBrush to paint the rectangle's background. myRectangle.Fill = myImageBrush;
The next example sets the tiles of an ImageBrush to 25 by 25 device independent pixels. Because the ViewportUnits are absolute, the ImageBrush tiles are always 25 by 25 pixels, regardless of the size of the area being painted.
<Rectangle Width="50" Height="100"> <Rectangle.Fill> <!-- Paints an area with 25 x 25 tiles. --> <ImageBrush ImageSource="sampleImages\cherries_larger.jpg" Viewport="0,0,25,25" ViewportUnits="Absolute" TileMode="Tile" /> </Rectangle.Fill> </Rectangle>
// Create a rectangle. Rectangle myRectangle = new Rectangle(); myRectangle.Width = 50; myRectangle.Height = 100; // Load the image. BitmapImage theImage = new BitmapImage( new Uri("sampleImages\\cherries_larger.jpg", UriKind.Relative)); ImageBrush myImageBrush = new ImageBrush(theImage); // Create tiles that are 25 x 25, regardless of the size // of the output area. myImageBrush.Viewport = new Rect(0, 0, 25, 25); myImageBrush.ViewportUnits = BrushMappingMode.Absolute; // Set the tile mode to Tile. myImageBrush.TileMode = TileMode.Tile; // Use the ImageBrush to paint the rectangle's background. myRectangle.Fill = myImageBrush;
Tiling Behavior
A TileBrush produces a tiled pattern when its base tile does not completely fill the output area and a tiling mode other then None is specified. When a tile brush's tile does not completely fill the output area, its TileMode property specifies whether the base tile should be duplicated to fill the output area and, if so, how the base tile should be duplicated. The TileMode property accepts the following values, defined by the TileMode enumeration:
None: Only the base tile is drawn.
Tile: The base tile is drawn and the remaining area is filled by repeating the base tile such that the right edge of one tile is adjacent to the left edge of the next, and similarly for bottom and top.
FlipX: The same as Tile, but alternate columns of tiles are flipped horizontally.
FlipY: The same as Tile, but alternate rows of tiles are flipped vertically.
The following image illustrates the different tiling modes.
In the following example, an image is used to paint a rectangle that is 100 pixels wide and 100 pixels tall. By setting the brush's Viewport has been set to 0,0,0.25,0.25, the brush's base tile is made to be 1/4 of the output area. The brush's TileMode is set to FlipXY. so that it fills the rectangle with rows of tiles.
<Rectangle Width="100" Height="100" > <Rectangle.Fill> <ImageBrush ImageSource="sampleImages\triangle.jpg" Viewport="0,0,0.25,0.25" TileMode="FlipXY" /> </Rectangle.Fill> </Rectangle>
// Create a rectangle. Rectangle myRectangle = new Rectangle(); myRectangle.Width = 100; myRectangle.Height = 100; // Load the image. BitmapImage theImage = new BitmapImage( new Uri("sampleImages\\triangle.jpg", UriKind.Relative)); ImageBrush myImageBrush = new ImageBrush(theImage); // Create tiles that are 1/4 the size of // the output area. myImageBrush.Viewport = new Rect(0,0,0.25,0.25); // Set the tile mode to FlipXY. myImageBrush.TileMode = TileMode.FlipXY; // Use the ImageBrush to paint the rectangle's background. myRectangle.Fill = myImageBrush;
How-to Topics
Animate the Color or Opacity of a SolidColorBrush
This example shows how to animate the Color and Opacity of a SolidColorBrush.
Example
The following example uses three animations to animate the Color and Opacity of a SolidColorBrush.
The first animation, a ColorAnimation, changes the brush's color to Gray when the mouse enters the rectangle.
The next animation, another ColorAnimation, changes the brush's color to Orange when the mouse leaves the rectangle.
The final animation, a DoubleAnimation, changes the brush's opacity to 0.0 when the left mouse button is pressed.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Input; namespace Microsoft.Samples.Animation { /// <summary> /// This example shows how to animate the Opacity and Color /// properties of a SolidColorBrush. /// </summary> public class SolidColorBrushExample : Page { public SolidColorBrushExample() { Title = "SolidColorBrush Animation Example"; Background = Brushes.White; // Create a NameScope for the page so // that Storyboards can be used. NameScope.SetNameScope(this, new NameScope()); // Create a Rectangle. Rectangle aRectangle = new Rectangle(); aRectangle.Width = 100; aRectangle.Height = 100; // Create a SolidColorBrush to paint // the rectangle's fill. The Opacity // and Color properties of the brush // will be animated. SolidColorBrush myAnimatedBrush = new SolidColorBrush(); myAnimatedBrush.Color = Colors.Orange; aRectangle.Fill = myAnimatedBrush; // Register the brush's name with the page // so that it can be targeted by storyboards. this.RegisterName("MyAnimatedBrush", myAnimatedBrush); // // Animate the brush's color to gray when // the mouse enters the rectangle. // ColorAnimation mouseEnterColorAnimation = new ColorAnimation(); mouseEnterColorAnimation.To = Colors.Gray; mouseEnterColorAnimation.Duration = TimeSpan.FromSeconds(1); Storyboard.SetTargetName(mouseEnterColorAnimation, "MyAnimatedBrush"); Storyboard.SetTargetProperty( mouseEnterColorAnimation, new PropertyPath(SolidColorBrush.ColorProperty)); Storyboard mouseEnterStoryboard = new Storyboard(); mouseEnterStoryboard.Children.Add(mouseEnterColorAnimation); aRectangle.MouseEnter += delegate(object sender, MouseEventArgs e) { mouseEnterStoryboard.Begin(this); }; // // Animate the brush's color to orange when // the mouse leaves the rectangle. // ColorAnimation mouseLeaveColorAnimation = new ColorAnimation(); mouseLeaveColorAnimation.To = Colors.Orange; mouseLeaveColorAnimation.Duration = TimeSpan.FromSeconds(1); Storyboard.SetTargetName(mouseLeaveColorAnimation, "MyAnimatedBrush"); Storyboard.SetTargetProperty( mouseLeaveColorAnimation, new PropertyPath(SolidColorBrush.ColorProperty)); Storyboard mouseLeaveStoryboard = new Storyboard(); mouseLeaveStoryboard.Children.Add(mouseLeaveColorAnimation); aRectangle.MouseLeave += delegate(object sender, MouseEventArgs e) { mouseLeaveStoryboard.Begin(this); }; // // Animate the brush's opacity to 0 and back when // the left mouse button is pressed over the rectangle. // DoubleAnimation opacityAnimation = new DoubleAnimation(); opacityAnimation.To = 0.0; opacityAnimation.Duration = TimeSpan.FromSeconds(0.5); opacityAnimation.AutoReverse = true; Storyboard.SetTargetName(opacityAnimation, "MyAnimatedBrush"); Storyboard.SetTargetProperty( opacityAnimation, new PropertyPath(SolidColorBrush.OpacityProperty)); Storyboard mouseLeftButtonDownStoryboard = new Storyboard(); mouseLeftButtonDownStoryboard.Children.Add(opacityAnimation); aRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e) { mouseLeftButtonDownStoryboard.Begin(this); }; StackPanel mainPanel = new StackPanel(); mainPanel.Margin = new Thickness(20); mainPanel.Children.Add(aRectangle); Content = mainPanel; } } }
For a more complete sample, which shows how to animate different types of brushes, see the Brushes Sample. For more information about animation, see the Animation Overview.
For consistency with other animation examples, the code versions of this example use a Storyboard object to apply their animations. However, when applying a single animation in code, it's simpler to use the BeginAnimation method instead of using a Storyboard. For an example, see How to: Animate a Property Without Using a Storyboard.
Animate the Position or Color of a Gradient Stop
This example shows how to animate the Color and Offset of GradientStop objects.
Example
The following example animates three gradient stops inside a LinearGradientBrush. The example uses three animations, each of which animates a different gradient stop:
The first animation, a DoubleAnimation, animates the first gradient stop's Offset from 0.0 to 1.0 and then back to 0.0. As a result, the first color in the gradient shifts from the left side to the right side of the rectangle and then back to the left side.
The second animation, a ColorAnimation, animates the second gradient stop's Color from Purple to Yellow and then back to Purple. As a result, the middle color in the gradient changes from purple to yellow and back to purple.
The third animation, another ColorAnimation, animates the opacity of the third gradient stop's Color by -1 and then back. As a result, the third color in the gradient fades away and then becomes opaque again.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace BrushesIntroduction { public class GradientStopAnimationExample : Page { public GradientStopAnimationExample() { Title = "GradientStop Animation Example"; Background = Brushes.White; // Create a NameScope for the page so that // Storyboards can be used. NameScope.SetNameScope(this, new NameScope()); // Create a rectangle. This rectangle will // be painted with a gradient. Rectangle aRectangle = new Rectangle(); aRectangle.Width = 200; aRectangle.Height = 100; aRectangle.Stroke = Brushes.Black; aRectangle.StrokeThickness = 1; // Create a LinearGradientBrush to paint // the rectangle's fill. LinearGradientBrush gradientBrush = new LinearGradientBrush(); // Create gradient stops for the brush. GradientStop stop1 = new GradientStop(Colors.MediumBlue, 0.0); GradientStop stop2 = new GradientStop(Colors.Purple, 0.5); GradientStop stop3 = new GradientStop(Colors.Red, 1.0); // Register a name for each gradient stop with the // page so that they can be animated by a storyboard. this.RegisterName("GradientStop1", stop1); this.RegisterName("GradientStop2", stop2); this.RegisterName("GradientStop3", stop3); // Add the stops to the brush. gradientBrush.GradientStops.Add(stop1); gradientBrush.GradientStops.Add(stop2); gradientBrush.GradientStops.Add(stop3); // Apply the brush to the rectangle. aRectangle.Fill = gradientBrush; // // Animate the first gradient stop's offset from // 0.0 to 1.0 and then back to 0.0. // DoubleAnimation offsetAnimation = new DoubleAnimation(); offsetAnimation.From = 0.0; offsetAnimation.To = 1.0; offsetAnimation.Duration = TimeSpan.FromSeconds(1.5); offsetAnimation.AutoReverse = true; Storyboard.SetTargetName(offsetAnimation, "GradientStop1"); Storyboard.SetTargetProperty(offsetAnimation, new PropertyPath(GradientStop.OffsetProperty)); // // Animate the second gradient stop's color from // Purple to Yellow and then back to Purple. // ColorAnimation gradientStopColorAnimation = new ColorAnimation(); gradientStopColorAnimation.From = Colors.Purple; gradientStopColorAnimation.To = Colors.Yellow; gradientStopColorAnimation.Duration = TimeSpan.FromSeconds(1.5); gradientStopColorAnimation.AutoReverse = true; Storyboard.SetTargetName(gradientStopColorAnimation, "GradientStop2"); Storyboard.SetTargetProperty(gradientStopColorAnimation, new PropertyPath(GradientStop.ColorProperty)); // Set the animation to begin after the first animation // ends. gradientStopColorAnimation.BeginTime = TimeSpan.FromSeconds(3); // // Animate the third gradient stop's color so // that it becomes transparent. // ColorAnimation opacityAnimation = new ColorAnimation(); // Reduces the target color's alpha value by 1, // making the color transparent. opacityAnimation.By = Color.FromScRgb(-1.0F, 0F, 0F, 0F); opacityAnimation.Duration = TimeSpan.FromSeconds(1.5); opacityAnimation.AutoReverse = true; Storyboard.SetTargetName(opacityAnimation, "GradientStop3"); Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(GradientStop.ColorProperty)); // Set the animation to begin after the first two // animations have ended. opacityAnimation.BeginTime = TimeSpan.FromSeconds(6); // Create a Storyboard to apply the animations. Storyboard gradientStopAnimationStoryboard = new Storyboard(); gradientStopAnimationStoryboard.Children.Add(offsetAnimation); gradientStopAnimationStoryboard.Children.Add(gradientStopColorAnimation); gradientStopAnimationStoryboard.Children.Add(opacityAnimation); // Begin the storyboard when the left mouse button is // pressed over the rectangle. aRectangle.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e) { gradientStopAnimationStoryboard.Begin(this); }; StackPanel mainPanel = new StackPanel(); mainPanel.Margin = new Thickness(10); mainPanel.Children.Add(aRectangle); Content = mainPanel; } } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="GradientStop Animation Example" Background="White"> <StackPanel Margin="10"> <Rectangle Width="200" Height="100" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <LinearGradientBrush> <GradientStop x:Name="GradientStop1" Color="MediumBlue" Offset="0.0" /> <GradientStop x:Name="GradientStop2" Color="Purple" Offset="0.5" /> <GradientStop x:Name="GradientStop3" Color="Red" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> <Rectangle.Triggers> <EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="GradientStop1" Storyboard.TargetProperty="Offset" From="0.0" To="1.0" Duration="0:0:1.5" AutoReverse="True" /> <ColorAnimation Storyboard.TargetName="GradientStop2" Storyboard.TargetProperty="Color" From="Purple" To="Yellow" Duration="0:0:1.5" AutoReverse="True" BeginTime="0:0:3" /> <ColorAnimation Storyboard.TargetName="GradientStop3" Storyboard.TargetProperty="Color" Duration="0:0:1.5" AutoReverse="True" BeginTime="0:0:6"> <ColorAnimation.By> <Color ScA="-1" ScR="0" ScB="0" ScG="0" /> </ColorAnimation.By> </ColorAnimation> </Storyboard> </BeginStoryboard> </EventTrigger> </Rectangle.Triggers> </Rectangle> </StackPanel> </Page>
Create a Reflection
This example shows how to use a VisualBrush to create a reflection. Because a VisualBrush can display an existing visual, you can use this capability to produce interesting visual effects, such as reflections and magnification.
Example
The following example uses a VisualBrush to create a reflection of a Border that contains several elements. The following illustration shows the output that this example produces.
using System; using System.Windows; using System.Windows.Data; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Effects; using System.Windows.Media.Imaging; using System.IO; using System.Collections.ObjectModel; using System.Windows.Shapes; namespace SDKSample { public partial class ReflectionExample : Page { public ReflectionExample() { // Create a name scope for the page. NameScope.SetNameScope(this, new NameScope()); this.Background = Brushes.Black; StackPanel myStackPanel = new StackPanel(); myStackPanel.Margin = new Thickness(50); Border myReflectedBorder = new Border(); this.RegisterName("ReflectedVisual", myReflectedBorder); // Create a gradient background for the border. GradientStop firstStop = new GradientStop(); firstStop.Offset = 0.0; Color firstStopColor = new Color(); firstStopColor.R = 204; firstStopColor.G = 204; firstStopColor.B = 255; firstStopColor.A = 255; firstStop.Color = firstStopColor; GradientStop secondStop = new GradientStop(); secondStop.Offset = 1.0; secondStop.Color = Colors.White; GradientStopCollection myGradientStopCollection = new GradientStopCollection(); myGradientStopCollection.Add(firstStop); myGradientStopCollection.Add(secondStop); LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(); myLinearGradientBrush.StartPoint = new Point(0, 0.5); myLinearGradientBrush.EndPoint = new Point(1, 0.5); myLinearGradientBrush.GradientStops = myGradientStopCollection; myReflectedBorder.Background = myLinearGradientBrush; // Add contents to the border. StackPanel borderStackPanel = new StackPanel(); borderStackPanel.Orientation = Orientation.Horizontal; borderStackPanel.Margin = new Thickness(10); TextBlock myTextBlock = new TextBlock(); myTextBlock.TextWrapping = TextWrapping.Wrap; myTextBlock.Width = 200; myTextBlock.Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit." + " Suspendisse vel ante. Donec luctus tortor sit amet est." + " Nullam pulvinar odio et wisi." + " Pellentesque quis magna. Sed pellentesque." + " Nulla euismod." + "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."; borderStackPanel.Children.Add(myTextBlock); StackPanel ellipseStackPanel = new StackPanel(); Ellipse ellipse1 = new Ellipse(); ellipse1.Margin = new Thickness(10); ellipse1.Height = 50; ellipse1.Width = 50; ellipse1.Fill = Brushes.Black; ellipseStackPanel.Children.Add(ellipse1); Ellipse ellipse2 = new Ellipse(); ellipse2.Margin = new Thickness(10); ellipse2.Height = 50; ellipse2.Width = 50; ellipse2.Fill = Brushes.Black; ellipseStackPanel.Children.Add(ellipse2); Ellipse ellipse3 = new Ellipse(); ellipse3.Margin = new Thickness(10); ellipse3.Height = 50; ellipse3.Width = 50; ellipse3.Fill = Brushes.Black; ellipseStackPanel.Children.Add(ellipse3); borderStackPanel.Children.Add(ellipseStackPanel); myReflectedBorder.Child = borderStackPanel; // Create divider rectangle Rectangle dividerRectangle = new Rectangle(); dividerRectangle.Height = 1; dividerRectangle.Fill = Brushes.Gray; dividerRectangle.HorizontalAlignment = HorizontalAlignment.Stretch; // Create the object to contain the reflection. Rectangle reflectionRectangle = new Rectangle(); // Bind the height of the rectangle to the border height. Binding heightBinding = new Binding(); heightBinding.ElementName = "ReflectedVisual"; heightBinding.Path = new PropertyPath(Rectangle.HeightProperty); BindingOperations.SetBinding(reflectionRectangle, Rectangle.HeightProperty, heightBinding); // Bind the width of the rectangle to the border width. Binding widthBinding = new Binding(); widthBinding.ElementName = "ReflectedVisual"; widthBinding.Path = new PropertyPath(Rectangle.WidthProperty); BindingOperations.SetBinding(reflectionRectangle, Rectangle.WidthProperty, widthBinding); // Creates the reflection. VisualBrush myVisualBrush = new VisualBrush(); myVisualBrush.Opacity = 0.75; myVisualBrush.Stretch = Stretch.None; Binding reflectionBinding = new Binding(); reflectionBinding.ElementName = "ReflectedVisual"; BindingOperations.SetBinding(myVisualBrush, VisualBrush.VisualProperty, reflectionBinding); ScaleTransform myScaleTransform = new ScaleTransform(); myScaleTransform.ScaleX = 1; myScaleTransform.ScaleY = -1; TranslateTransform myTranslateTransform = new TranslateTransform(); myTranslateTransform.Y = 1; TransformGroup myTransformGroup = new TransformGroup(); myTransformGroup.Children.Add(myScaleTransform); myTransformGroup.Children.Add(myTranslateTransform); myVisualBrush.RelativeTransform = myTransformGroup; reflectionRectangle.Fill = myVisualBrush; // Create a gradient background for the border. GradientStop firstStop2 = new GradientStop(); firstStop2.Offset = 0.0; Color c1 = new Color(); c1.R = 0; c1.G = 0; c1.B = 0; c1.A = 255; firstStop2.Color = c1; GradientStop secondStop2 = new GradientStop(); secondStop2.Offset = 0.5; Color c2 = new Color(); c2.R = 0; c2.G = 0; c2.B = 0; c2.A = 51; firstStop2.Color = c2; GradientStop thirdStop = new GradientStop(); thirdStop.Offset = 0.75; Color c3 = new Color(); c3.R = 0; c3.G = 0; c3.B = 0; c3.A = 0; thirdStop.Color = c3; GradientStopCollection myGradientStopCollection2 = new GradientStopCollection(); myGradientStopCollection2.Add(firstStop2); myGradientStopCollection2.Add(secondStop2); myGradientStopCollection2.Add(thirdStop); LinearGradientBrush myLinearGradientBrush2 = new LinearGradientBrush(); myLinearGradientBrush2.StartPoint = new Point(0.5, 0); myLinearGradientBrush2.EndPoint = new Point(0.5, 1); myLinearGradientBrush2.GradientStops = myGradientStopCollection2; reflectionRectangle.OpacityMask = myLinearGradientBrush2; BlurBitmapEffect myBlurBitmapEffect = new BlurBitmapEffect(); myBlurBitmapEffect.Radius = 1.5; reflectionRectangle.BitmapEffect = myBlurBitmapEffect; myStackPanel.Children.Add(myReflectedBorder); myStackPanel.Children.Add(dividerRectangle); myStackPanel.Children.Add(reflectionRectangle); this.Content = myStackPanel; } /* <Rectangle Height="{Binding Path=ActualHeight, ElementName=ReflectedVisual}" Width="{Binding Path=ActualWidth, ElementName=ReflectedVisual}"> <Rectangle.OpacityMask> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Color="#FF000000" Offset="0.0" /> <GradientStop Color="#33000000" Offset="0.5" /> <GradientStop Color="#00000000" Offset="0.75" /> </LinearGradientBrush> </Rectangle.OpacityMask> <Rectangle.BitmapEffect> <BlurBitmapEffect Radius="1.5" /> </Rectangle.BitmapEffect> </Rectangle> </StackPanel> </Page> */ } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="Black"> <StackPanel Margin="50"> <!-- The object to reflect. --> <Border Name="ReflectedVisual" Width="400"> <Border.Background> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5"> <GradientStop Offset="0.0" Color="#CCCCFF" /> <GradientStop Offset="1.0" Color="White" /> </LinearGradientBrush> </Border.Background> <StackPanel Orientation="Horizontal" Margin="10"> <TextBlock TextWrapping="Wrap" Width="200" Margin="10"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Suspendisse vel ante. Donec luctus tortor sit amet est. Nullam pulvinar odio et wisi. Pellentesque quis magna. Sed pellentesque. Nulla euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. </TextBlock> <StackPanel> <Ellipse Margin="10" Height="50" Width="50" Fill="Black" /> <Ellipse Margin="10" Height="50" Width="50" Fill="Black" /> <Ellipse Margin="10" Height="50" Width="50" Fill="Black" /> </StackPanel> </StackPanel> </Border> <Rectangle Height="1" Fill="Gray" HorizontalAlignment="Stretch" /> <!-- The object to contain the reflection.--> <Rectangle Height="{Binding Path=ActualHeight, ElementName=ReflectedVisual}" Width="{Binding Path=ActualWidth, ElementName=ReflectedVisual}"> <Rectangle.Fill> <!-- Creates the reflection. --> <VisualBrush Opacity="0.75" Stretch="None" Visual="{Binding ElementName=ReflectedVisual}"> <VisualBrush.RelativeTransform> <!-- Flip the reflection. --> <TransformGroup> <ScaleTransform ScaleX="1" ScaleY="-1" /> <TranslateTransform Y="1" /> </TransformGroup> </VisualBrush.RelativeTransform> </VisualBrush> </Rectangle.Fill> <Rectangle.OpacityMask> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Color="#FF000000" Offset="0.0" /> <GradientStop Color="#33000000" Offset="0.5" /> <GradientStop Color="#00000000" Offset="0.75" /> </LinearGradientBrush> </Rectangle.OpacityMask> <Rectangle.BitmapEffect> <BlurBitmapEffect Radius="1.5" /> </Rectangle.BitmapEffect> </Rectangle> </StackPanel> </Page>
For the complete sample, which includes examples that show how to magnify parts of the screen and how to create reflections, see VisualBrush Sample.
Create Different Tile Patterns with a TileBrush
This example shows how to use the TileMode property of a TileBrush to create a pattern.
The TileMode property enables you to specify how the content of a TileBrush is repeated, that is, tiled to fill an output area. To create a pattern, you set the TileMode to Tile, FlipX, FlipY, or FlipXY. You must also set the Viewport of the TileBrush so that it is smaller than the area that you are painting; otherwise, only a single tile is produced, regardless which TileMode setting you use.
Example
The following example creates five DrawingBrush objects, gives them each a different TileMode setting, and uses them to paint five rectangles. Although this example uses the DrawingBrush class to demonstrate TileMode behavior, the TileMode property works identically for all the TileBrush objects, that is, for ImageBrush, VisualBrush, and DrawingBrush.
The following illustration shows the output that this example produces.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace BrushesIntroduction { public class TileModeExample : Page { public TileModeExample() { Background = Brushes.White; Margin = new Thickness(20); StackPanel mainPanel = new StackPanel(); mainPanel.HorizontalAlignment = HorizontalAlignment.Left; // // Create a Drawing. This will be the DrawingBrushes' content. // PolyLineSegment triangleLinesSegment = new PolyLineSegment(); triangleLinesSegment.Points.Add(new Point(50, 0)); triangleLinesSegment.Points.Add(new Point(0, 50)); PathFigure triangleFigure = new PathFigure(); triangleFigure.IsClosed = true; triangleFigure.StartPoint = new Point(0, 0); triangleFigure.Segments.Add(triangleLinesSegment); PathGeometry triangleGeometry = new PathGeometry(); triangleGeometry.Figures.Add(triangleFigure); GeometryDrawing triangleDrawing = new GeometryDrawing(); triangleDrawing.Geometry = triangleGeometry; triangleDrawing.Brush = new SolidColorBrush(Color.FromArgb(255, 204, 204, 255)); Pen trianglePen = new Pen(Brushes.Black, 2); triangleDrawing.Pen = trianglePen; trianglePen.MiterLimit = 0; triangleDrawing.Freeze(); // // Create the first TileBrush. Its content is not tiled. // DrawingBrush tileBrushWithoutTiling = new DrawingBrush(); tileBrushWithoutTiling.Drawing = triangleDrawing; tileBrushWithoutTiling.TileMode = TileMode.None; // Create a rectangle and paint it with the DrawingBrush. Rectangle noTileExampleRectangle = createExampleRectangle(); noTileExampleRectangle.Fill = tileBrushWithoutTiling; // Add a header and the rectangle to the main panel. mainPanel.Children.Add(createExampleHeader("None")); mainPanel.Children.Add(noTileExampleRectangle); // // Create another TileBrush, this time with tiling. // DrawingBrush tileBrushWithTiling = new DrawingBrush(); tileBrushWithTiling.Drawing = triangleDrawing; tileBrushWithTiling.TileMode = TileMode.Tile; // Specify the brush's Viewport. Otherwise, // a single tile will be produced that fills // the entire output area and its TileMode will // have no effect. // This setting uses realtive values to // creates four tiles. tileBrushWithTiling.Viewport = new Rect(0, 0, 0.5, 0.5); // Create a rectangle and paint it with the DrawingBrush. Rectangle tilingExampleRectangle = createExampleRectangle(); tilingExampleRectangle.Fill = tileBrushWithTiling; mainPanel.Children.Add(createExampleHeader("Tile")); mainPanel.Children.Add(tilingExampleRectangle); // // Create a TileBrush with FlipX tiling. // The brush's content is flipped horizontally as it is // tiled in this example // DrawingBrush tileBrushWithFlipXTiling = new DrawingBrush(); tileBrushWithFlipXTiling.Drawing = triangleDrawing; tileBrushWithFlipXTiling.TileMode = TileMode.FlipX; // Specify the brush's Viewport. tileBrushWithFlipXTiling.Viewport = new Rect(0, 0, 0.5, 0.5); // Create a rectangle and paint it with the DrawingBrush. Rectangle flipXTilingExampleRectangle = createExampleRectangle(); flipXTilingExampleRectangle.Fill = tileBrushWithFlipXTiling; mainPanel.Children.Add(createExampleHeader("FlipX")); mainPanel.Children.Add(flipXTilingExampleRectangle); // // Create a TileBrush with FlipY tiling. // The brush's content is flipped vertically as it is // tiled in this example // DrawingBrush tileBrushWithFlipYTiling = new DrawingBrush(); tileBrushWithFlipYTiling.Drawing = triangleDrawing; tileBrushWithFlipYTiling.TileMode = TileMode.FlipX; // Specify the brush's Viewport. tileBrushWithFlipYTiling.Viewport = new Rect(0, 0, 0.5, 0.5); // Create a rectangle and paint it with the DrawingBrush. Rectangle flipYTilingExampleRectangle = createExampleRectangle(); flipYTilingExampleRectangle.Fill = tileBrushWithFlipYTiling; mainPanel.Children.Add(createExampleHeader("FlipY")); mainPanel.Children.Add(flipYTilingExampleRectangle); // // Create a TileBrush with FlipXY tiling. // The brush's content is flipped vertically as it is // tiled in this example // DrawingBrush tileBrushWithFlipXYTiling = new DrawingBrush(); tileBrushWithFlipXYTiling.Drawing = triangleDrawing; tileBrushWithFlipXYTiling.TileMode = TileMode.FlipXY; // Specify the brush's Viewport. tileBrushWithFlipXYTiling.Viewport = new Rect(0, 0, 0.5, 0.5); // Create a rectangle and paint it with the DrawingBrush. Rectangle flipXYTilingExampleRectangle = createExampleRectangle(); flipXYTilingExampleRectangle.Fill = tileBrushWithFlipXYTiling; mainPanel.Children.Add(createExampleHeader("FlipXY")); mainPanel.Children.Add(flipXYTilingExampleRectangle); Content = mainPanel; } // // Helper method that creates rectangle elements. // private static Rectangle createExampleRectangle() { Rectangle exampleRectangle = new Rectangle(); exampleRectangle.Width = 50; exampleRectangle.Height = 50; exampleRectangle.Stroke = Brushes.Black; exampleRectangle.StrokeThickness = 1; return exampleRectangle; } // // Helper method that creates headers for the examples. // private static TextBlock createExampleHeader(String text) { TextBlock header = new TextBlock(); header.Margin = new Thickness(0, 10, 0, 0); header.Text = text; return header; } } }
<!-- Demonstrates TileMode values. --> <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" Background="White" Margin="20"> <Page.Resources> <!-- Define a Drawing as a resource that it can be easily used as content for all the DrawingBrush objects in this example. --> <GeometryDrawing x:Key="TriangleDrawing" Geometry="M0,0 L50,0 0,50Z" Brush="#CCCCFF" PresentationOptions:Freeze="True" > <GeometryDrawing.Pen> <Pen Thickness="2" Brush="Black" MiterLimit="0" /> </GeometryDrawing.Pen> </GeometryDrawing> </Page.Resources> <StackPanel HorizontalAlignment="Left"> <TextBlock Margin="0,10,0,0">None</TextBlock> <Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <!-- The DrawingBrush's content is not tiled in this example. --> <DrawingBrush TileMode="None" Drawing="{StaticResource TriangleDrawing}" /> </Rectangle.Fill> </Rectangle> <TextBlock Margin="0,10,0,0">Tile</TextBlock> <Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <!-- The DrawingBrush's content is tiled in this example. The Viewport property is set to create four tiles. --> <DrawingBrush TileMode="Tile" Viewport="0,0,0.5,0.5" Drawing="{StaticResource TriangleDrawing}"/> </Rectangle.Fill> </Rectangle> <TextBlock Margin="0,10,0,0">FlipX</TextBlock> <Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <!-- The DrawingBrush's content is flipped horizontally as it is tiled in this example. --> <DrawingBrush TileMode="FlipX" Viewport="0,0,0.5,0.5" Drawing="{StaticResource TriangleDrawing}" /> </Rectangle.Fill> </Rectangle> <TextBlock Margin="0,10,0,0">FlipY</TextBlock> <Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <!-- The DrawingBrush's content is flipped vertically as it is tiled in this example. --> <DrawingBrush TileMode="FlipY" Viewport="0,0,0.5,0.5" Drawing="{StaticResource TriangleDrawing}" /> </Rectangle.Fill> </Rectangle> <TextBlock Margin="0,10,0,0">FlipXY</TextBlock> <Rectangle Width="50" Height="50" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <!-- The DrawingBrush's content is flipped horizontally and vertically as it is tiled in this example. --> <DrawingBrush TileMode="FlipXY" Viewport="0,0,0.5,0.5" Drawing="{StaticResource TriangleDrawing}" /> </Rectangle.Fill> </Rectangle> </StackPanel> </Page>
Define a Pen
This example shows how use a Pen to outline a shape. To create a simple Pen, you need only specify its Thickness and Brush. You can create more complex pen's by specifying a DashStyle, DashCap, LineJoin, StartLineCap, and EndLineCap.
Example
The following example uses a Pen to outline a shape defined by a GeometryDrawing.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace SDKSample { public partial class PenExample : Page { public PenExample() { // Create several geometries. RectangleGeometry myRectangleGeometry = new RectangleGeometry(); myRectangleGeometry.Rect = new Rect(0, 0, 50, 50); EllipseGeometry myEllipseGeometry = new EllipseGeometry(); myEllipseGeometry.Center = new Point(75, 75); myEllipseGeometry.RadiusX = 50; myEllipseGeometry.RadiusY = 50; LineGeometry myLineGeometry = new LineGeometry(); myLineGeometry.StartPoint = new Point(75, 75); myLineGeometry.EndPoint = new Point(75, 0); // Create a GeometryGroup and add the geometries to it. GeometryGroup myGeometryGroup = new GeometryGroup(); myGeometryGroup.Children.Add(myRectangleGeometry); myGeometryGroup.Children.Add(myEllipseGeometry); myGeometryGroup.Children.Add(myLineGeometry); // Create a GeometryDrawing and use the GeometryGroup to specify // its geometry. GeometryDrawing myGeometryDrawing = new GeometryDrawing(); myGeometryDrawing.Geometry = myGeometryGroup; // Add the GeometryDrawing to a DrawingGroup. DrawingGroup myDrawingGroup = new DrawingGroup(); myDrawingGroup.Children.Add(myGeometryDrawing); // Create a Pen to add to the GeometryDrawing created above. Pen myPen = new Pen(); myPen.Thickness = 10; myPen.LineJoin = PenLineJoin.Round; myPen.EndLineCap = PenLineCap.Round; // Create a gradient to use as a value for the Pen's Brush property. GradientStop firstStop = new GradientStop(); firstStop.Offset = 0.0; Color c1 = new Color(); c1.A = 255; c1.R = 204; c1.G = 204; c1.B = 255; firstStop.Color = c1; GradientStop secondStop = new GradientStop(); secondStop.Offset = 1.0; secondStop.Color = Colors.Purple; LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(); myLinearGradientBrush.GradientStops.Add(firstStop); myLinearGradientBrush.GradientStops.Add(secondStop); myPen.Brush = myLinearGradientBrush; myGeometryDrawing.Pen = myPen; // Create an Image and set its DrawingImage to the Geometry created above. Image myImage = new Image(); myImage.Stretch = Stretch.None; myImage.Margin = new Thickness(10); DrawingImage myDrawingImage = new DrawingImage(); myDrawingImage.Drawing = myDrawingGroup; myImage.Source = myDrawingImage; this.Content = myImage; } } }
Paint an Area with a Drawing
This example shows how to paint an area with a drawing. To paint an area with a drawing, you use a DrawingBrush and one or more Drawing objects. The following example uses a DrawingBrush to paint an object with a drawing of two ellipses.
Example
<!-- Demonstrates the use of DrawingBrush. --> <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="White"> <StackPanel Margin="20"> <Rectangle Width="150" Height="150" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <DrawingBrush> <DrawingBrush.Drawing> <GeometryDrawing Brush="MediumBlue"> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" /> <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Thickness="10"> <Pen.Brush> <LinearGradientBrush> <GradientStop Offset="0.0" Color="Black" /> <GradientStop Offset="1.0" Color="Gray" /> </LinearGradientBrush> </Pen.Brush> </Pen> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Rectangle.Fill> </Rectangle> </StackPanel> </Page>
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace Microsoft.Samples.DrawingBrushExamples { /// <summary> /// Paints a Rectangle element with a DrawingBrush. /// </summary> public class DrawingBrushExample : Page { public DrawingBrushExample() { Background = Brushes.White; StackPanel mainPanel = new StackPanel(); // Create a drawing of two ellipses. GeometryDrawing aDrawing = new GeometryDrawing(); // Use geometries to describe two overlapping ellipses. EllipseGeometry ellipse1 = new EllipseGeometry(); ellipse1.RadiusX = 20; ellipse1.RadiusY = 45; ellipse1.Center = new Point(50, 50); EllipseGeometry ellipse2 = new EllipseGeometry(); ellipse2.RadiusX = 45; ellipse2.RadiusY = 20; ellipse2.Center = new Point(50, 50); GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add(ellipse1); ellipses.Children.Add(ellipse2); // Add the geometry to the drawing. aDrawing.Geometry = ellipses; // Specify the drawing's fill. aDrawing.Brush = Brushes.Blue; // Specify the drawing's stroke. Pen stroke = new Pen(); stroke.Thickness = 10.0; stroke.Brush = new LinearGradientBrush( Colors.Black, Colors.Gray, new Point(0, 0), new Point(1, 1)); aDrawing.Pen = stroke; // Create a DrawingBrush DrawingBrush myDrawingBrush = new DrawingBrush(); myDrawingBrush.Drawing = aDrawing; // Create a Rectangle element. Rectangle aRectangle = new Rectangle(); aRectangle.Width = 150; aRectangle.Height = 150; aRectangle.Stroke = Brushes.Black; aRectangle.StrokeThickness = 1.0; // Use the DrawingBrush to paint the rectangle's // background. aRectangle.Fill = myDrawingBrush; mainPanel.Children.Add(aRectangle); this.Content = mainPanel; } } }
The following illustration shows the example's output.
(The center of the shape is white for reasons described in How to: Control the Fill of a Composite Shape.)
By setting a DrawingBrush object's Viewport and TileMode properties, you can create a repeating pattern. The following example paints an object with a pattern created from a drawing of two ellipses.
<!-- Demonstrates the use of DrawingBrush. --> <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="White"> <StackPanel Margin="20"> <Rectangle Width="150" Height="150" Stroke="Black" StrokeThickness="1"> <Rectangle.Fill> <DrawingBrush Viewport="0,0,0.25,0.25" TileMode="Tile"> <DrawingBrush.Drawing> <GeometryDrawing Brush="MediumBlue"> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" /> <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Thickness="10"> <Pen.Brush> <LinearGradientBrush> <GradientStop Offset="0.0" Color="Black" /> <GradientStop Offset="1.0" Color="Gray" /> </LinearGradientBrush> </Pen.Brush> </Pen> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Rectangle.Fill> </Rectangle> </StackPanel> </Page>
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace Microsoft.Samples.DrawingBrushExamples { /// <summary> /// Paints a Rectangle element with a tiled DrawingBrush. /// </summary> public class TiledDrawingBrushExample : Page { public TiledDrawingBrushExample() { Background = Brushes.White; StackPanel mainPanel = new StackPanel(); // Create a drawing of two ellipses. GeometryDrawing aDrawing = new GeometryDrawing(); // Use geometries to describe two overlapping ellipses. EllipseGeometry ellipse1 = new EllipseGeometry(); ellipse1.RadiusX = 20; ellipse1.RadiusY = 45; ellipse1.Center = new Point(50, 50); EllipseGeometry ellipse2 = new EllipseGeometry(); ellipse2.RadiusX = 45; ellipse2.RadiusY = 20; ellipse2.Center = new Point(50, 50); GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add(ellipse1); ellipses.Children.Add(ellipse2); // Add the geometry to the drawing. aDrawing.Geometry = ellipses; // Specify the drawing's fill. aDrawing.Brush = Brushes.Blue; // Specify the drawing's stroke. Pen stroke = new Pen(); stroke.Thickness = 10.0; stroke.Brush = new LinearGradientBrush( Colors.Black, Colors.Gray, new Point(0, 0), new Point(1, 1)); aDrawing.Pen = stroke; // Create a DrawingBrush DrawingBrush myDrawingBrush = new DrawingBrush(); myDrawingBrush.Drawing = aDrawing; // Set the DrawingBrush's Viewport and TileMode // properties so that it generates a pattern. myDrawingBrush.Viewport = new Rect(0, 0, 0.25, 0.25); myDrawingBrush.TileMode = TileMode.Tile; // Create a Rectangle element. Rectangle aRectangle = new Rectangle(); aRectangle.Width = 150; aRectangle.Height = 150; aRectangle.Stroke = Brushes.Black; aRectangle.StrokeThickness = 1.0; // Use the DrawingBrush to paint the rectangle's // background. aRectangle.Fill = myDrawingBrush; mainPanel.Children.Add(aRectangle); this.Content = mainPanel; } } }
The following illustration shows the tiled DrawingBrush output.
For more information about drawing brushes, see Painting with Images, Drawings, and Visuals. For more information about Drawing objects, see theDrawing Objects Overview.
Paint an Area with an Image
This example shows how to use the ImageBrush class to paint an area with an image. An ImageBrush displays a single image, which is specified by itsImageSource property.
Example
The following example paints the Background of a button by using an ImageBrush.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using System.Windows.Media; namespace Microsoft.Samples.Graphics.UsingImageBrush { public class PaintingWithImagesExample : Page { public PaintingWithImagesExample() { Background = Brushes.White; StackPanel mainPanel = new StackPanel(); mainPanel.Margin = new Thickness(20.0); // Create a button. Button berriesButton = new Button(); berriesButton.Foreground = Brushes.White; berriesButton.FontWeight = FontWeights.Bold; FontSizeConverter sizeConverter = new FontSizeConverter(); berriesButton.FontSize = (Double)sizeConverter.ConvertFromString("16pt"); berriesButton.FontFamily = new FontFamily("Verdana"); berriesButton.Content = "Berries"; berriesButton.Padding = new Thickness(20.0); berriesButton.HorizontalAlignment = HorizontalAlignment.Left; // Create an ImageBrush. ImageBrush berriesBrush = new ImageBrush(); berriesBrush.ImageSource = new BitmapImage( new Uri(@"sampleImages\berries.jpg", UriKind.Relative) ); // Use the brush to paint the button's background. berriesButton.Background = berriesBrush; mainPanel.Children.Add(berriesButton); this.Content = mainPanel; } } }
By default, an ImageBrush stretches its image to completely fill the area that you are painting. In the preceding example, the image is stretched to fill the button, possibly distorting the image. You can control this behavior by setting the Stretch property of TileBrush to Uniform or UniformToFill, which causes the brush to preserve the aspect ratio of the image.
If you set the Viewport and TileMode properties of an ImageBrush, you can create a repeating pattern. The following example paints a button by using a pattern that is created from an image.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using System.Windows.Media; namespace Microsoft.Samples.Graphics.UsingImageBrush { public class TiledImageBrushExample : Page { public TiledImageBrushExample() { Background = Brushes.White; StackPanel mainPanel = new StackPanel(); mainPanel.Margin = new Thickness(20.0); // Create a button. Button berriesButton = new Button(); berriesButton.Foreground = Brushes.White; berriesButton.FontWeight = FontWeights.Bold; FontSizeConverter sizeConverter = new FontSizeConverter(); berriesButton.FontSize = (Double)sizeConverter.ConvertFromString("16pt"); berriesButton.FontFamily = new FontFamily("Verdana"); berriesButton.Content = "Berries"; berriesButton.Padding = new Thickness(20.0); berriesButton.HorizontalAlignment = HorizontalAlignment.Left; // Create an ImageBrush. ImageBrush berriesBrush = new ImageBrush(); berriesBrush.ImageSource = new BitmapImage( new Uri(@"sampleImages\berries.jpg", UriKind.Relative) ); // Set the ImageBrush's Viewport and TileMode // so that it produces a pattern from // the image. berriesBrush.Viewport = new Rect(0,0,0.5,0.5); berriesBrush.TileMode = TileMode.FlipXY; // Use the brush to paint the button's background. berriesButton.Background = berriesBrush; mainPanel.Children.Add(berriesButton); this.Content = mainPanel; } } }
For more information about the ImageBrush class, see Painting with Images, Drawings, and Visuals.
This code example is part of a larger example that is provided for the ImageBrush class. For the complete sample, see ImageBrush Sample.
Paint an Area with a Linear Gradient
This example shows how to use the LinearGradientBrush class to paint an area with a linear gradient. In the following example, the Fill of a Rectangle is painted with a diagonal linear gradient that transitions from yellow to red to blue to lime green.
Example
<!-- This rectangle is painted with a diagonal linear gradient. --> <Rectangle Width="200" Height="100"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
Rectangle diagonalFillRectangle = new Rectangle(); diagonalFillRectangle.Width = 200; diagonalFillRectangle.Height = 100; // Create a diagonal linear gradient with four stops. LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(); myLinearGradientBrush.StartPoint = new Point(0,0); myLinearGradientBrush.EndPoint = new Point(1,1); myLinearGradientBrush.GradientStops.Add( new GradientStop(Colors.Yellow, 0.0)); myLinearGradientBrush.GradientStops.Add( new GradientStop(Colors.Red, 0.25)); myLinearGradientBrush.GradientStops.Add( new GradientStop(Colors.Blue, 0.75)); myLinearGradientBrush.GradientStops.Add( new GradientStop(Colors.LimeGreen, 1.0)); // Use the brush to paint the rectangle. diagonalFillRectangle.Fill = myLinearGradientBrush;
The following illustration shows the gradient created by the previous example.
To create a horizontal linear gradient, change the StartPoint and EndPoint of the LinearGradientBrush to (0,0.5) and (1,0.5). In the following example, a Rectangle is painted with a horizontal linear gradient.
<!-- This rectangle is painted with a horizontal linear gradient. --> <Rectangle Width="200" Height="100"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5"> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
Rectangle horizontalFillRectangle = new Rectangle(); horizontalFillRectangle.Width = 200; horizontalFillRectangle.Height = 100; // Create a horizontal linear gradient with four stops. LinearGradientBrush myHorizontalGradient = new LinearGradientBrush(); myHorizontalGradient.StartPoint = new Point(0,0.5); myHorizontalGradient.EndPoint = new Point(1,0.5); myHorizontalGradient.GradientStops.Add( new GradientStop(Colors.Yellow, 0.0)); myHorizontalGradient.GradientStops.Add( new GradientStop(Colors.Red, 0.25)); myHorizontalGradient.GradientStops.Add( new GradientStop(Colors.Blue, 0.75)); myHorizontalGradient.GradientStops.Add( new GradientStop(Colors.LimeGreen, 1.0)); // Use the brush to paint the rectangle. horizontalFillRectangle.Fill = myHorizontalGradient;
The following illustration shows the gradient created by the previous example.
To create a vertical linear gradient, change the StartPoint and EndPoint of the LinearGradientBrush to (0.5,0) and (0.5,1). In the following example, a Rectangle is painted with a vertical linear gradient.
<!-- This rectangle is painted with a vertical gradient. --> <Rectangle Width="200" Height="100"> <Rectangle.Fill> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Color="Yellow" Offset="0.0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1.0" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle>
Rectangle verticalFillRectangle = new Rectangle(); verticalFillRectangle.Width = 200; verticalFillRectangle.Height = 100; // Create a vertical linear gradient with four stops. LinearGradientBrush myVerticalGradient = new LinearGradientBrush(); myVerticalGradient.StartPoint = new Point(0.5,0); myVerticalGradient.EndPoint = new Point(0.5,1); myVerticalGradient.GradientStops.Add( new GradientStop(Colors.Yellow, 0.0)); myVerticalGradient.GradientStops.Add( new GradientStop(Colors.Red, 0.25)); myVerticalGradient.GradientStops.Add( new GradientStop(Colors.Blue, 0.75)); myVerticalGradient.GradientStops.Add( new GradientStop(Colors.LimeGreen, 1.0)); // Use the brush to paint the rectangle. verticalFillRectangle.Fill = myVerticalGradient;
The following illustration shows the gradient created by the previous example.
Note |
---|
The examples in this topic use the default coordinate system for setting start points and end points. The default coordinate system is relative to a bounding box: 0 indicates 0 percent of the bounding box, and 1 indicates 100 percent of the bounding box. You can change this coordinate system by setting the MappingMode property to the value BrushMappingMode.Absolute. An absolute coordinate system is not relative to a bounding box. Values are interpreted directly in local space. |
For additional examples, see Brushes Sample. For more information about gradients and other types of brushes, see Painting with Solid Colors and Gradients Overview.
Paint an Area with a Radial Gradient
This example shows how to use the RadialGradientBrush class to paint an area with a radial gradient.
Example
The following example uses a RadialGradientBrush to paint a rectangle with a radial gradient that transitions from yellow to red to blue to lime green.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace BrushesIntroduction { public class RadialGradientBrushSnippet : Page { public RadialGradientBrushSnippet() { Title = "RadialGradientBrush Example"; Background = Brushes.White; Margin = new Thickness(20); // // Create a RadialGradientBrush with four gradient stops. // RadialGradientBrush radialGradient = new RadialGradientBrush(); // Set the GradientOrigin to the center of the area being painted. radialGradient.GradientOrigin = new Point(0.5, 0.5); // Set the gradient center to the center of the area being painted. radialGradient.Center = new Point(0.5, 0.5); // Set the radius of the gradient circle so that it extends to // the edges of the area being painted. radialGradient.RadiusX = 0.5; radialGradient.RadiusY = 0.5; // Create four gradient stops. radialGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0)); radialGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25)); radialGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75)); radialGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0)); // Freeze the brush (make it unmodifiable) for performance benefits. radialGradient.Freeze(); // Create a rectangle and paint it with the // RadialGradientBrush. Rectangle aRectangle = new Rectangle(); aRectangle.Width = 200; aRectangle.Height = 100; aRectangle.Fill = radialGradient; StackPanel mainPanel = new StackPanel(); mainPanel.Children.Add(aRectangle); Content = mainPanel; } } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="RadialGradientBrush Example" Background="White" Margin="20"> <StackPanel> <!-- This rectangle is painted with a radial gradient. --> <Rectangle Width="200" Height="100"> <Rectangle.Fill> <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5"> <RadialGradientBrush.GradientStops> <GradientStop Color="Yellow" Offset="0" /> <GradientStop Color="Red" Offset="0.25" /> <GradientStop Color="Blue" Offset="0.75" /> <GradientStop Color="LimeGreen" Offset="1" /> </RadialGradientBrush.GradientStops> </RadialGradientBrush> </Rectangle.Fill> </Rectangle> </StackPanel> </Page>
The following illustration shows the gradient from the preceding example. The gradient's stops have been highlighted.
Note |
---|
The examples in this topic use the default coordinate system for setting control points. The default coordinate system is relative to a bounding box: 0 indicates 0 percent of the bounding box, and 1 indicates 100 percent of the bounding box. You can change this coordinate system by setting the MappingMode property to the value Absolute. An absolute coordinate system is not relative to a bounding box. Values are interpreted directly in local space. |
For additional RadialGradientBrush examples, see the Brushes Sample. For more information about gradients and other types of brushes, see Painting with Solid Colors and Gradients Overview.
Paint an Area with a Solid Color
To paint an area with a solid color, you can use a predefined system brush, such as Red or Blue, or you can create a new SolidColorBrush and describe its Color using alpha, red, green, and blue values. In XAML, you may also paint an area with a solid color by using hexidecimal notation.
The following examples uses each of these techniques to paint a Rectangle blue.
Example
Using a Predefined Brush
In the following example uses the predefined brush Blue to paint a rectangle blue.
<Rectangle Width="50" Height="50" Fill="Blue" />
// Create a rectangle and paint it with // a predefined brush. Rectangle myPredefinedBrushRectangle = new Rectangle(); myPredefinedBrushRectangle.Width = 50; myPredefinedBrushRectangle.Height = 50; myPredefinedBrushRectangle.Fill = Brushes.Blue;
Using Hexadecimal Notation
The next example uses 8-digit hexadecimal notation to paint a rectangle blue.
<!-- Note that the first two characters "FF" of the 8-digit value is the alpha which controls the transparency of the color. Therefore, to make a completely transparent color (invisible), use "00" for those digits (e.g. #000000FF). --> <Rectangle Width="50" Height="50" Fill="#FF0000FF" />
Using ARGB Values
The next example creates a SolidColorBrush and describes its Color using the ARGB values for the color blue.
<Rectangle Width="50" Height="50"> <Rectangle.Fill> <SolidColorBrush> <SolidColorBrush.Color> <!-- Describes the brush's color using RGB values. Each value has a range of 0-255. R is for red, G is for green, and B is for blue. A is for alpha which controls transparency of the color. Therefore, to make a completely transparent color (invisible), use a value of 0 for Alpha. --> <Color A="255" R="0" G="0" B="255" /> </SolidColorBrush.Color> </SolidColorBrush> </Rectangle.Fill> </Rectangle>
Rectangle myRgbRectangle = new Rectangle(); myRgbRectangle.Width = 50; myRgbRectangle.Height = 50; SolidColorBrush mySolidColorBrush = new SolidColorBrush(); // Describes the brush's color using RGB values. // Each value has a range of 0-255. mySolidColorBrush.Color = Color.FromArgb(255, 0, 0, 255); myRgbRectangle.Fill = mySolidColorBrush;
For other ways of describing color, see the Color structure.
Related Topics
For more information about SolidColorBrush and additional examples, see the Painting with Solid Colors and Gradients Overview overview.
This code example is part of a larger example provided for the SolidColorBrush class. For the complete sample, see the Brushes Sample.
Paint an Area with a System Brush
The SystemColors class provides access to system brushes and colors, such as ControlBrush, ControlBrushKey, and DesktopBrush. A system brush is aSolidColorBrush object that paints an area with the specified system color. A system brush always produces a solid fill; it can't be used to create a gradient.
You can use system brushes as either a static or a dynamic resource. Use a dynamic resource if you want the brush to update automatically if the user changes the system brush as the application is running; otherwise, use a static resource. The SystemColors class contains a variety of static properties that follow a strict naming convention:
<SystemColor>Brush
Gets a static reference to a SolidColorBrush of the specified system color.
<SystemColor>BrushKey
Gets a dynamic reference to a SolidColorBrush of the specified system color.
<SystemColor>Color
Gets a static reference to a Color structure of the specified system color.
<SystemColor>ColorKey
Gets a dynamic reference to the Color structure of the specified system color.
A system color is a Color structure that can be used to configure a brush. For example, you can create a gradient using system colors by setting theColor properties of a LinearGradientBrush object's gradient stops with system colors. For an example, see How to: Use System Colors in a Gradient.
Example
The following example uses a dynamic system brush reference to set the Background of a button.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowTitle="SystemColors Example" Background="White"> <StackPanel Margin="20"> <!-- Uses a dynamic resource to set the background of a button. If the desktop brush changes while this application is running, this button will be updated. --> <Button Background="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}" Content="Hello, World!" /> </StackPanel> </Page>
The next example uses a static system brush reference to set the Background of a button.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowTitle="SystemColors Example" Background="White"> <StackPanel Margin="20"> <!-- Uses a static brush to set the background of a button. If the desktop brush changes while this application is running, this button will not be updated until the page is loaded again. --> <Button Background="{x:Static SystemColors.DesktopBrush}" Content="Hello, World!" /> </StackPanel> </Page>
For an example showing how to use a system color in a gradient, see How to: Use System Colors in a Gradient.
Paint an Area with a Video
This example shows how to paint an area with media. One way to paint an area with media is to use a MediaElement together with a VisualBrush. Use the MediaElement to load and play the media, and then use it to set the Visual property of the VisualBrush. You can then use the VisualBrush to paint an area with the loaded media.
Example
The following example uses a MediaElement and a VisualBrush to paint the Foreground of a TextBlock control with video. This example sets the IsMuted property of the MediaElement to true so that it produces no sound.
MediaElement myMediaElement = new MediaElement(); myMediaElement.Source = new Uri("sampleMedia\\xbox.wmv", UriKind.Relative); myMediaElement.IsMuted = true; VisualBrush myVisualBrush = new VisualBrush(); myVisualBrush.Visual = myMediaElement; TextBlock myTextBlock = new TextBlock(); myTextBlock.FontSize = 150; myTextBlock.Text = "Some Text"; myTextBlock.FontWeight = FontWeights.Bold; myTextBlock.Foreground = myVisualBrush;
<TextBlock FontSize="100pt" Text="Some Text" FontWeight="Bold"> <TextBlock.Foreground> <VisualBrush> <VisualBrush.Visual> <MediaElement Source="sampleMedia\xbox.wmv" IsMuted="True" /> </VisualBrush.Visual> </VisualBrush> </TextBlock.Foreground> </TextBlock>
Example
Because VisualBrush inherits from the TileBrush class, it provides several tiling modes. By setting the TileMode property of a VisualBrush to Tile and by setting its Viewport property to a value smaller than the area that you are painting, you can create a tiled pattern.
The following example is identical to the previous example, except that the VisualBrush generates a pattern from the video.
MediaElement myMediaElement = new MediaElement(); myMediaElement.Source = new Uri("sampleMedia\\xbox.wmv", UriKind.Relative); myMediaElement.IsMuted = true; VisualBrush myVisualBrush = new VisualBrush(); myVisualBrush.Viewport = new Rect(0, 0, 0.5, 0.5); myVisualBrush.TileMode = TileMode.Tile; myVisualBrush.Visual = myMediaElement; TextBlock myTextBlock = new TextBlock(); myTextBlock.FontSize = 150; myTextBlock.Text = "Some Text"; myTextBlock.FontWeight = FontWeights.Bold; myTextBlock.Foreground = myVisualBrush;
<TextBlock FontSize="100pt" Text="Some Text" FontWeight="Bold"> <TextBlock.Foreground> <VisualBrush Viewport="0,0,0.5,0.5" TileMode="Tile"> <VisualBrush.Visual> <MediaElement Source="sampleMedia\xbox.wmv" IsMuted="True" /> </VisualBrush.Visual> </VisualBrush> </TextBlock.Foreground> </TextBlock>
For information about how to add a content file, such as a media file, to your application, see WPF Application Resource, Content, and Data Files. When you add a media file, you must add it as a content file, not as a resource file.
Paint an Area with a Visual
This example shows how to use the VisualBrush class to paint an area with a Visual.
In the following example, several controls and a panel are used as the background of a rectangle.
Example
<Rectangle Width="150" Height="150" Stroke="Black" Margin="5,0,5,0"> <Rectangle.Fill> <VisualBrush> <VisualBrush.Visual> <StackPanel Background="White"> <Rectangle Width="25" Height="25" Fill="Red" Margin="2" /> <TextBlock FontSize="10pt" Margin="2">Hello, World!</TextBlock> <Button Margin="2">A Button</Button> </StackPanel> </VisualBrush.Visual> </VisualBrush> </Rectangle.Fill> </Rectangle>
VisualBrush myVisualBrush = new VisualBrush(); // Create the visual brush's contents. StackPanel myStackPanel = new StackPanel(); myStackPanel.Background = Brushes.White; Rectangle redRectangle = new Rectangle(); redRectangle.Width = 25; redRectangle.Height =25; redRectangle.Fill = Brushes.Red; redRectangle.Margin = new Thickness(2); myStackPanel.Children.Add(redRectangle); TextBlock someText = new TextBlock(); FontSizeConverter myFontSizeConverter = new FontSizeConverter(); someText.FontSize = (double)myFontSizeConverter.ConvertFrom("10pt"); someText.Text = "Hello, World!"; someText.Margin = new Thickness(2); myStackPanel.Children.Add(someText); Button aButton = new Button(); aButton.Content = "A Button"; aButton.Margin = new Thickness(2); myStackPanel.Children.Add(aButton); // Use myStackPanel as myVisualBrush's content. myVisualBrush.Visual = myStackPanel; // Create a rectangle to paint. Rectangle myRectangle = new Rectangle(); myRectangle.Width = 150; myRectangle.Height = 150; myRectangle.Stroke = Brushes.Black; myRectangle.Margin = new Thickness(5,0,5,0); // Use myVisualBrush to paint myRectangle. myRectangle.Fill = myVisualBrush;
For more information about VisualBrush and additional examples, see the Painting with Images, Drawings, and Visuals overview.
This code example is part of a larger example provided for the VisualBrush class. For the complete sample, see the VisualBrush Sample.
Preserve the Aspect Ratio of an Image Used as a Background
This example shows how to use the Stretch property of an ImageBrush in order to preserve the aspect ratio of the image.
By default, when you use an ImageBrush to paint an area, its content stretches to completely fill the output area. When the output area and the image have different aspect ratios, the image is distorted by this stretching.
To make an ImageBrush preserve the aspect ratio of its image, set the Stretch property to Uniform or UniformToFill.
Example
The following example uses two ImageBrush objects to paint two rectangles. Each rectangle is 300 by 150 pixels and each contains a 300 by 300 pixel image. The Stretch property of the first brush is set to Uniform, and the Stretch property of the second brush is set to UniformToFill.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using System.Windows.Media; using System.Windows.Shapes; namespace Microsoft.Samples.Graphics.UsingImageBrush { /// <summary> /// Demonstrates different ImageBrush Stretch settings. /// </summary> public class StretchModes : Page { public StretchModes() { // Create an ImageBrush with its Stretch // property set to Uniform. The image it // contains will be expanded as much as possible // to fill the output area while still // preserving its aspect ratio. ImageBrush uniformBrush = new ImageBrush(); uniformBrush.ImageSource = new BitmapImage(new Uri("sampleImages\\square.jpg", UriKind.Relative)); uniformBrush.Stretch = Stretch.Uniform; // Freeze the brush (make it unmodifiable) for performance benefits. uniformBrush.Freeze(); // Create a rectangle and paint it with the ImageBrush. Rectangle rectangle1 = new Rectangle(); rectangle1.Width = 300; rectangle1.Height = 150; rectangle1.Stroke = Brushes.MediumBlue; rectangle1.StrokeThickness = 1.0; rectangle1.Fill = uniformBrush; // Create an ImageBrush with its Stretch // property set to UniformToFill. The image it // contains will be expanded to completely fill // the rectangle, but its aspect ratio is preserved. ImageBrush uniformToFillBrush = new ImageBrush(); uniformToFillBrush.ImageSource = new BitmapImage(new Uri("sampleImages\\square.jpg", UriKind.Relative)); uniformToFillBrush.Stretch = Stretch.UniformToFill; // Freeze the brush (make it unmodifiable) for performance benefits. uniformToFillBrush.Freeze(); // Create a rectangle and paint it with the ImageBrush. Rectangle rectangle2 = new Rectangle(); rectangle2.Width = 300; rectangle2.Height = 150; rectangle2.Stroke = Brushes.MediumBlue; rectangle2.StrokeThickness = 1.0; rectangle2.Margin = new Thickness(0, 10, 0, 0); rectangle2.Fill = uniformToFillBrush; StackPanel mainPanel = new StackPanel(); mainPanel.Children.Add(rectangle1); mainPanel.Children.Add(rectangle2); Content = mainPanel; Background = Brushes.White; Margin = new Thickness(20); Title = "ImageBrush Stretch Modes"; } } }
The following illustration shows the output of the first brush, which has a Stretch setting of Uniform.
The next illustration shows the output of the second brush, which has a Stretch setting of UniformToFill.
Note that the Stretch property behaves identically for the other TileBrush objects, that is, for DrawingBrush and VisualBrush. For more information about ImageBrush and the other TileBrush objects, see Painting with Images, Drawings, and Visuals.
Note also that, although the Stretch property appears to specify how the TileBrush content stretches to fit its output area, it actually specifies how theTileBrush content stretches to fill its base tile. For more information, see TileBrush.
This code example is part of a larger example that is provided for the ImageBrush class. For the complete sample, see ImageBrush Sample.
Set the Horizontal and Vertical Alignment of a TileBrush
This example shows how to control the horizontal and vertical alignment of content in a tile. To control the horizontal and vertical alignment of a TileBrush, use its AlignmentX and AlignmentY properties.
The AlignmentX and AlignmentY properties of a TileBrush are used when either of the following conditions is true:
The Stretch property is Uniform or UniformToFill and the Viewbox and Viewport have different aspect ratios.
The Stretch property is None and the Viewbox and Viewport are different sizes.
Example
The following example aligns the content of a DrawingBrush, which is a type of TileBrush, to the upper-left corner of its tile. To align the content, the example sets the AlignmentX property of the DrawingBrush to Left and the AlignmentY property to Top. This example produces the following output.
// // Create a TileBrush and align its // content to the top-left of its tile. // DrawingBrush topLeftAlignedTileBrush = new DrawingBrush(); topLeftAlignedTileBrush.AlignmentX = AlignmentX.Left; topLeftAlignedTileBrush.AlignmentY = AlignmentY.Top; // Set Stretch to None so that the brush's // content doesn't automatically expand to // fill the entire tile. topLeftAlignedTileBrush.Stretch = Stretch.None; // Define the brush's content. GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 20, 45)); ellipses.Children.Add(new EllipseGeometry(new Point(50, 50), 45, 20)); Pen drawingPen = new Pen(Brushes.Gray, 10); GeometryDrawing ellipseDrawing = new GeometryDrawing(Brushes.Blue, drawingPen, ellipses); topLeftAlignedTileBrush.Drawing = ellipseDrawing; // Use the brush to paint a rectangle. Rectangle rectangle1 = new Rectangle(); rectangle1.Width = 150; rectangle1.Height = 150; rectangle1.Stroke = Brushes.Red; rectangle1.StrokeThickness = 2; rectangle1.Margin = new Thickness(20); rectangle1.Fill = topLeftAlignedTileBrush;
<Rectangle Width="150" Height="150" Stroke="Red" StrokeThickness="2" Margin="20"> <Rectangle.Fill> <!-- This brush's content is aligned to the top-left of its tile. --> <DrawingBrush Stretch="None" AlignmentX="Left" AlignmentY="Top"> <DrawingBrush.Drawing> <GeometryDrawing Brush="MediumBlue"> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" /> <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Gray" Thickness="10" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Rectangle.Fill> </Rectangle>
Example
The next example aligns the content of a DrawingBrush to the lower-right corner of its tile by setting the AlignmentX property to Right and the AlignmentY property to Bottom. The example produces the following output.
// // Create a TileBrush and align its // content to the bottom-right of its tile. // DrawingBrush bottomRightAlignedTileBrush = new DrawingBrush(); bottomRightAlignedTileBrush.AlignmentX = AlignmentX.Right; bottomRightAlignedTileBrush.AlignmentY = AlignmentY.Bottom; bottomRightAlignedTileBrush.Stretch = Stretch.None; // Define the brush's content. bottomRightAlignedTileBrush.Drawing = ellipseDrawing; // Use the brush to paint a rectangle. Rectangle rectangle2 = new Rectangle(); rectangle2.Width = 150; rectangle2.Height = 150; rectangle2.Stroke = Brushes.Red; rectangle2.StrokeThickness = 2; rectangle2.Margin = new Thickness(20); rectangle2.Fill = bottomRightAlignedTileBrush;
<Rectangle Width="150" Height="150" Stroke="Red" StrokeThickness="2" Margin="20"> <Rectangle.Fill> <!-- This brush's content is aligned to the bottom right of its tile. --> <DrawingBrush Stretch="None" AlignmentX="Right" AlignmentY="Bottom"> <DrawingBrush.Drawing> <GeometryDrawing Brush="MediumBlue"> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" /> <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Gray" Thickness="10" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Rectangle.Fill> </Rectangle>
Example
The next example aligns the content of a DrawingBrush to the upper-left corner of its tile by setting the AlignmentX property to Left and the AlignmentY property to Top. It also sets the Viewport and TileMode of the DrawingBrush to produce a tile pattern. The example produces the following output.
The illustration highlights a base tile so that you can see how its content is aligned. Notice that the AlignmentX setting has no effect because the content of the DrawingBrush completely fills the base tile horizontally.
// // Create a TileBrush that generates a // tiled pattern and align its // content to the top-left of its tile. // DrawingBrush tiledTopLeftAlignedTileBrush = new DrawingBrush(); tiledTopLeftAlignedTileBrush.AlignmentX = AlignmentX.Left; tiledTopLeftAlignedTileBrush.AlignmentY = AlignmentY.Top; tiledTopLeftAlignedTileBrush.Stretch = Stretch.Uniform; // Set the brush's Viewport and TileMode to produce a // tiled pattern. tiledTopLeftAlignedTileBrush.Viewport = new Rect(0, 0, 0.25, 0.5); tiledTopLeftAlignedTileBrush.TileMode = TileMode.Tile; // Define the brush's content. tiledTopLeftAlignedTileBrush.Drawing = ellipseDrawing; // Use the brush to paint a rectangle. Rectangle rectangle3 = new Rectangle(); rectangle3.Width = 150; rectangle3.Height = 150; rectangle3.Stroke = Brushes.Black; rectangle3.StrokeThickness = 2; rectangle3.Margin = new Thickness(20); rectangle3.Fill = tiledTopLeftAlignedTileBrush;
<Rectangle Width="150" Height="150" Stroke="Black" StrokeThickness="2" Margin="20"> <Rectangle.Fill> <!-- This brush's content is aligned to the top left of its tile. --> <DrawingBrush Stretch="Uniform" Viewport="0,0,0.25,0.5" TileMode="Tile" AlignmentX="Left" AlignmentY="Top"> <DrawingBrush.Drawing> <GeometryDrawing Brush="MediumBlue"> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" /> <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Gray" Thickness="10" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Rectangle.Fill> </Rectangle>
Example
The final example aligns the content of a tiled DrawingBrush to the lower-right of its base tile by setting the AlignmentX property to Right and the AlignmentY property to Bottom. The example produces the following output.
Again, the AlignmentX setting has no effect because the content of the DrawingBrush completely fills the base tile horizontally.
// // Create a TileBrush and align its // content to the bottom-right of its tile. // DrawingBrush bottomRightAlignedTileBrush = new DrawingBrush(); bottomRightAlignedTileBrush.AlignmentX = AlignmentX.Right; bottomRightAlignedTileBrush.AlignmentY = AlignmentY.Bottom; bottomRightAlignedTileBrush.Stretch = Stretch.None; // Define the brush's content. bottomRightAlignedTileBrush.Drawing = ellipseDrawing; // Use the brush to paint a rectangle. Rectangle rectangle2 = new Rectangle(); rectangle2.Width = 150; rectangle2.Height = 150; rectangle2.Stroke = Brushes.Red; rectangle2.StrokeThickness = 2; rectangle2.Margin = new Thickness(20); rectangle2.Fill = bottomRightAlignedTileBrush;
<Rectangle Width="150" Height="150" Stroke="Red" StrokeThickness="2" Margin="20"> <Rectangle.Fill> <!-- This brush's content is aligned to the bottom right of its tile. --> <DrawingBrush Stretch="None" AlignmentX="Right" AlignmentY="Bottom"> <DrawingBrush.Drawing> <GeometryDrawing Brush="MediumBlue"> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry RadiusX="20" RadiusY="45" Center="50,50" /> <EllipseGeometry RadiusX="45" RadiusY="20" Center="50,50" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Gray" Thickness="10" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Rectangle.Fill> </Rectangle>
The examples use DrawingBrush objects to demonstrate how the AlignmentX and AlignmentY properties are used. These properties behave identically for all the tile brushes: DrawingBrush, ImageBrush, and VisualBrush. For more information about tile brushes, see Painting with Images, Drawings, and Visuals.
Set the Tile Size for a TileBrush
This example shows how to set the tile size for a TileBrush. By default, a TileBrush produces a single tile that completely fills the area that you are painting. You can override this behavior by setting the Viewport and ViewportUnits properties.
The Viewport property specifies the tile size for a TileBrush. By default, the value of the Viewport property is relative to the size of the area being painted. To make the Viewport property specify an absolute tile size, set the ViewportUnits property to Absolute.
Example
The following example uses an ImageBrush, a type of TileBrush, to paint a rectangle with tiles. The example sets each tile to 50 percent by 50 percent of the output area (the rectangle). As a result, the rectangle is painted with four projections of the image.
The following illustration shows the output that the example produces .
// // Create an ImageBrush and set the size of each // tile to 50% by 50% of the area being painted. // ImageBrush relativeTileSizeImageBrush = new ImageBrush(); relativeTileSizeImageBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\cherries_larger.jpg", UriKind.Relative)); relativeTileSizeImageBrush.TileMode = TileMode.Tile; // Specify the size of the base tile. // By default, the size of the Viewport is // relative to the area being painted, // so a value of 0.5 indicates 50% of the output // area. relativeTileSizeImageBrush.Viewport = new Rect(0, 0, 0.5, 0.5); // Create a rectangle and paint it with the ImageBrush. Rectangle relativeTileSizeExampleRectangle = new Rectangle(); relativeTileSizeExampleRectangle.Width = 200; relativeTileSizeExampleRectangle.Height = 150; relativeTileSizeExampleRectangle.Stroke = Brushes.LimeGreen; relativeTileSizeExampleRectangle.StrokeThickness = 1; relativeTileSizeExampleRectangle.Fill = relativeTileSizeImageBrush;
The next example creates an ImageBrush, sets its Viewport to 0,0,25,25 and its ViewportUnits to Absolute, and uses it to paint another rectangle. As a result, the brush produces tiles that have a width of 25 pixels and a height of 25 pixels .
The following illustration shows the output that the example produces.
// // Create an ImageBrush and set the size of each // tile to 25 by 25 pixels. // ImageBrush absoluteTileSizeImageBrush = new ImageBrush(); absoluteTileSizeImageBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\cherries_larger.jpg", UriKind.Relative)); absoluteTileSizeImageBrush.TileMode = TileMode.Tile; // Specify that the Viewport is to be interpreted as // an absolute value. absoluteTileSizeImageBrush.ViewportUnits = BrushMappingMode.Absolute; // Set the size of the base tile. Had we left ViewportUnits set // to RelativeToBoundingBox (the default value), // each tile would be 25 times the size of the area being // painted. Because ViewportUnits is set to Absolute, // the following line creates tiles that are 25 by 25 pixels. absoluteTileSizeImageBrush.Viewport = new Rect(0, 0, 25, 25); // Create a rectangle and paint it with the ImageBrush. Rectangle absoluteTileSizeExampleRectangle = new Rectangle(); absoluteTileSizeExampleRectangle.Width = 200; absoluteTileSizeExampleRectangle.Height = 150; absoluteTileSizeExampleRectangle.Stroke = Brushes.LimeGreen; absoluteTileSizeExampleRectangle.StrokeThickness = 1; absoluteTileSizeExampleRectangle.Fill = absoluteTileSizeImageBrush;
The preceding examples are part of a larger sample. For the complete sample, see ImageBrush Sample.
Although this example uses the ImageBrush class, the Viewport and ViewportUnits properties behave identically for the other TileBrush objects, that is, for DrawingBrush and VisualBrush. For more information about ImageBrush and the other TileBrush objects, see Painting with Images, Drawings, and Visuals.
Transform a Brush
This example shows how to transform Brush objects by using their two transformation properties: RelativeTransform and Transform.
The following examples use a RotateTransform to rotate the content of an ImageBrush by 45 degrees.
The following illustration shows the ImageBrush without a RotateTransform, with the RotateTransform applied to the RelativeTransform property, and with the RotateTransform applied to the Transform property.
Example
The first example applies a RotateTransform to the RelativeTransform property of an ImageBrush. The CenterX and CenterY properties of a RotateTransform object are both set to 0.5, which is the relative coordinate of the center point of this content. As a result, the ImageBrush content rotates about its center.
// // Create an ImageBrush with a relative transform and // use it to paint a rectangle. // ImageBrush relativeTransformImageBrush = new ImageBrush(); relativeTransformImageBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative)); // Create a 45 rotate transform about the brush's center // and apply it to the brush's RelativeTransform property. RotateTransform aRotateTransform = new RotateTransform(); aRotateTransform.CenterX = 0.5; aRotateTransform.CenterY = 0.5; aRotateTransform.Angle = 45; relativeTransformImageBrush.RelativeTransform = aRotateTransform; // Use the brush to paint a rectangle. Rectangle relativeTransformImageBrushRectangle = new Rectangle(); relativeTransformImageBrushRectangle.Width = 175; relativeTransformImageBrushRectangle.Height = 90; relativeTransformImageBrushRectangle.Stroke = Brushes.Black; relativeTransformImageBrushRectangle.Fill = relativeTransformImageBrush;
<Rectangle Width="175" Height="90" Stroke="Black"> <Rectangle.Fill> <ImageBrush ImageSource="sampleImages\pinkcherries.jpg"> <ImageBrush.RelativeTransform> <RotateTransform CenterX="0.5" CenterY="0.5" Angle="45" /> </ImageBrush.RelativeTransform> </ImageBrush> </Rectangle.Fill> </Rectangle>
The second example also applies a RotateTransform to an ImageBrush; however, this example uses the Transform property instead of the RelativeTransform property.
To rotate the brush about its center, the example sets the CenterX and CenterY properties of the RotateTransform object to absolute coordinates. Because the brush paints a rectangle that is 175 by 90 pixels, the center point of the rectangle is (87.5, 45).
// // Create an ImageBrush with a transform and // use it to paint a rectangle. // ImageBrush transformImageBrush = new ImageBrush(); transformImageBrush.ImageSource = new BitmapImage(new Uri(@"sampleImages\pinkcherries.jpg", UriKind.Relative)); // Create a 45 rotate transform about the brush's center // and apply it to the brush's Transform property. RotateTransform anotherRotateTransform = new RotateTransform(); anotherRotateTransform.CenterX = 87.5; anotherRotateTransform.CenterY = 45; anotherRotateTransform.Angle = 45; transformImageBrush.Transform = anotherRotateTransform; // Use the brush to paint a rectangle. Rectangle transformImageBrushRectangle = new Rectangle(); transformImageBrushRectangle.Width = 175; transformImageBrushRectangle.Height = 90; transformImageBrushRectangle.Stroke = Brushes.Black; transformImageBrushRectangle.Fill = transformImageBrush;
<Rectangle Width="175" Height="90" Stroke="Black"> <Rectangle.Fill> <ImageBrush ImageSource="sampleImages\pinkcherries.jpg"> <ImageBrush.Transform> <RotateTransform CenterX="87.5" CenterY="45" Angle="45" /> </ImageBrush.Transform> </ImageBrush> </Rectangle.Fill> </Rectangle>
For a description of how the RelativeTransform and Transform properties work, see the Brush Transformation Overview.
For the complete sample, see Brushes Sample. For more information about brushes, see Painting with Solid Colors and Gradients Overview.
Use System Colors in a Gradient
To use a system color in a gradient, you use the <SystemColor>Color and <SystemColor>ColorKey static properties of the SystemColors class to obtain a reference to the color, where <SystemColor> is the name of the desired system color. Use the <SystemColor>ColorKey properties when you want to create a dynamic reference that updates automatically as the system theme changes. Otherwise, use the <SystemColor>Color properties.
Example
The following example uses dynamic system color resources to create a gradient.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowTitle="Dynamic System Colors Example" Background="White"> <StackPanel Margin="20"> <!-- Uses dynamic references to system colors to set the colors of gradient stops. If these system colors change while this application is running, the gradient will be updated automatically. --> <Button Content="Hello, World!"> <Button.Background> <LinearGradientBrush> <LinearGradientBrush.GradientStops> <GradientStop Offset="0.0" Color="{DynamicResource {x:Static SystemColors.DesktopColorKey}}" /> <GradientStop Offset="1.0" Color="{DynamicResource {x:Static SystemColors.ControlLightLightColorKey}}" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Button.Background> </Button> </StackPanel> </Page>
The next example uses static system color resources to create a gradient.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowTitle="Static System Colors Example" Background="White"> <StackPanel Margin="20"> <!-- Uses static references to system colors to set the colors of gradient stops. If these system colors change while this application is running, this button will not be updated until the page is loaded again. --> <Button Content="Hello, World!"> <Button.Background> <LinearGradientBrush> <LinearGradientBrush.GradientStops> <GradientStop Offset="0.0" Color="{x:Static SystemColors.DesktopColor}" /> <GradientStop Offset="1.0" Color="{x:Static SystemColors.ControlLightLightColor}" /> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Button.Background> </Button> </StackPanel> </Page>
Drawings
Drawing Objects Overview
This topic introduces Drawing objects and describes how to use them to efficiently draw shapes, bitmaps, text, and media. Use Drawing objects when you create clip art, paint with a DrawingBrush, or use Visual objects.
What Is a Drawing Object?
A Drawing object describes visible content, such as a shape, bitmap, video, or a line of text. Different types of drawings describe different types of content. The following is a list of the different types of drawing objects.
GeometryDrawing – Draws a shape.
ImageDrawing – Draws an image.
GlyphRunDrawing – Draws text.
VideoDrawing – Plays an audio or video file.
DrawingGroup – Draws other drawings. Use a drawing group to combine other drawings into a single composite drawing.
Drawing objects are versatile; there are many ways you can use a Drawing object.
You can display it as an image by using a DrawingImage and an Image control.
You can use it with a DrawingBrush to paint an object, such as the Background of a Page.
You can use it to describe the appearance of a DrawingVisual.
You can use it to enumerate the contents of a Visual.
WPF provides other types of objects that are capable of drawing shapes, bitmaps, text, and media. For example, you can also use Shape objects to draw shapes, and the MediaElement control provides another way to add video to your application. So when should you use Drawing objects? When you can sacrifice framework level features to gain performance benefits or when you need Freezable features. Because Drawing objects lack support for Layout, input, and focus, they provide performance benefits that make them ideal for describing backgrounds, clip art, and for low-level drawing with Visual objects.
Because they are a type Freezable object, Drawing objects gain several special features, which include the following: they can be declared as resources, shared among multiple objects, made read-only to improve performance, cloned, and made thread-safe. For more information about the different features provided by Freezable objects, see the Freezable Objects Overview.
Draw a Shape
To draw a shape, you use a GeometryDrawing. A geometry drawing's Geometry property describes the shape to draw, its Brush property describes how the interior of the shape should be painted, and its Pen property describes how its outline should be drawn.
The following example uses a GeometryDrawing to draw a shape. The shape is described by a GeometryGroup and two EllipseGeometry objects. The shape's interior is painted with a LinearGradientBrush and its outline is drawn with a Black Pen.
This example creates the following GeometryDrawing.
// // Create the Geometry to draw. // GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add( new EllipseGeometry(new Point(50,50), 45, 20) ); ellipses.Children.Add( new EllipseGeometry(new Point(50, 50), 20, 45) ); // // Create a GeometryDrawing. // GeometryDrawing aGeometryDrawing = new GeometryDrawing(); aGeometryDrawing.Geometry = ellipses; // Paint the drawing with a gradient. aGeometryDrawing.Brush = new LinearGradientBrush( Colors.Blue, Color.FromRgb(204,204,255), new Point(0,0), new Point(1,1)); // Outline the drawing with a solid color. aGeometryDrawing.Pen = new Pen(Brushes.Black, 10);
<GeometryDrawing> <GeometryDrawing.Geometry> <!-- Create a composite shape. --> <GeometryGroup> <EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" /> <EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Brush> <!-- Paint the drawing with a gradient. --> <LinearGradientBrush> <GradientStop Offset="0.0" Color="Blue" /> <GradientStop Offset="1.0" Color="#CCCCFF" /> </LinearGradientBrush> </GeometryDrawing.Brush> <GeometryDrawing.Pen> <!-- Outline the drawing with a solid color. --> <Pen Thickness="10" Brush="Black" /> </GeometryDrawing.Pen> </GeometryDrawing>
For the complete example, see How to: Create a GeometryDrawing.
Other Geometry classes, such as PathGeometry enable you to create more complex shapes by creating curves and arcs. For more information about Geometry objects, see the Geometry Overview.
For more information about other ways to draw shapes that don't use Drawing objects, see Shapes and Basic Drawing in WPF Overview.
Draw an Image
To draw an image, you use an ImageDrawing. An ImageDrawing object's ImageSource property describes the image to draw, and its Rect property defines the region where the image is drawn.
The following example draws an image into a rectangle located at (75,75) that is 100 by 100 pixel. The following illustration shows the ImageDrawing created by the example. A gray border was added to show the bounds of the ImageDrawing.
// Create a 100 by 100 image with an upper-left point of (75,75). ImageDrawing bigKiwi = new ImageDrawing(); bigKiwi.Rect = new Rect(75, 75, 100, 100); bigKiwi.ImageSource = new BitmapImage( new Uri(@"sampleImages\kiwi.png", UriKind.Relative));
<!-- The Rect property specifies that the image only fill a 100 by 100 rectangular area. --> <ImageDrawing Rect="75,75,100,100" ImageSource="sampleImages\kiwi.png"/>
For more information about images, see the Imaging Overview.
Play Media (Code Only)
Note |
---|
Although you can declare a VideoDrawing in Extensible Application Markup Language (XAML), you can only load and play its media using code. To play video in Extensible Application Markup Language (XAML), use a MediaElement instead. |
To play an audio or video file, you use a VideoDrawing and a MediaPlayer. There are two ways to load and play media. The first is to use a MediaPlayer and a VideoDrawing by themselves, and the second way is to create your own MediaTimeline to use with the MediaPlayer and VideoDrawing.
Note |
---|
When distributing media with your application, you cannot use a media file as a project resource, like you would an image. In your project file, you must instead set the media type to Content and set CopyToOutputDirectory to PreserveNewest or Always. |
To play media without creating your own MediaTimeline, you perform the following steps.
Create a MediaPlayer object.
MediaPlayer player = new MediaPlayer();
Use the Open method to load the media file.
player.Open(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative));
Create a VideoDrawing.
VideoDrawing aVideoDrawing = new VideoDrawing();
Specify the size and location to draw the media by setting the Rect property of the VideoDrawing.
aVideoDrawing.Rect = new Rect(0, 0, 100, 100);
Set the Player property of the VideoDrawing with the MediaPlayer you created.
aVideoDrawing.Player = player;
Use the Play method of the MediaPlayer to start playing the media.
// Play the video once. player.Play();
The following example uses a VideoDrawing and a MediaPlayer to play a video file once.
// // Create a VideoDrawing. // MediaPlayer player = new MediaPlayer(); player.Open(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative)); VideoDrawing aVideoDrawing = new VideoDrawing(); aVideoDrawing.Rect = new Rect(0, 0, 100, 100); aVideoDrawing.Player = player; // Play the video once. player.Play();
To gain additional timing control over the media, use a MediaTimeline with the MediaPlayer and VideoDrawing objects. The MediaTimeline enables you to specify whether the video should repeat. To use a MediaTimeline with a VideoDrawing, you perform the following steps:
Declare the MediaTimeline and set its timing behaviors.
// Create a MediaTimeline. MediaTimeline mTimeline = new MediaTimeline(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative)); // Set the timeline to repeat. mTimeline.RepeatBehavior = RepeatBehavior.Forever;
Create a MediaClock from the MediaTimeline.
// Create a clock from the MediaTimeline. MediaClock mClock = mTimeline.CreateClock();
Create a MediaPlayer and use the MediaClock to set its Clock property.
MediaPlayer repeatingVideoDrawingPlayer = new MediaPlayer(); repeatingVideoDrawingPlayer.Clock = mClock;
Create a VideoDrawing and assign the MediaPlayer to the Player property of the VideoDrawing.
VideoDrawing repeatingVideoDrawing = new VideoDrawing(); repeatingVideoDrawing.Rect = new Rect(150, 0, 100, 100); repeatingVideoDrawing.Player = repeatingVideoDrawingPlayer;
The following example uses a MediaTimeline with a MediaPlayer and a VideoDrawing to play a video repeatedly.
// // Create a VideoDrawing that repeats. // // Create a MediaTimeline. MediaTimeline mTimeline = new MediaTimeline(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative)); // Set the timeline to repeat. mTimeline.RepeatBehavior = RepeatBehavior.Forever; // Create a clock from the MediaTimeline. MediaClock mClock = mTimeline.CreateClock(); MediaPlayer repeatingVideoDrawingPlayer = new MediaPlayer(); repeatingVideoDrawingPlayer.Clock = mClock; VideoDrawing repeatingVideoDrawing = new VideoDrawing(); repeatingVideoDrawing.Rect = new Rect(150, 0, 100, 100); repeatingVideoDrawing.Player = repeatingVideoDrawingPlayer;
Note that, when you use a MediaTimeline, you use the interactive ClockController returned from the Controller property of the MediaClock to control media playback instead of the interactive methods of MediaPlayer.
Draw Text
To draw text, you use a GlyphRunDrawing and a GlyphRun. The following example uses a GlyphRunDrawing to draw the text "Hello World".
GlyphRun theGlyphRun = new GlyphRun( new GlyphTypeface(new Uri(@"C:\WINDOWS\Fonts\TIMES.TTF")), 0, false, 13.333333333333334, new ushort[]{43, 72, 79, 79, 82, 3, 58, 82, 85, 79, 71}, new Point(0, 12.29), new double[]{ 9.62666666666667, 7.41333333333333, 2.96, 2.96, 7.41333333333333, 3.70666666666667, 12.5866666666667, 7.41333333333333, 4.44, 2.96, 7.41333333333333}, null, null, null, null, null, null ); GlyphRunDrawing gDrawing = new GlyphRunDrawing(Brushes.Black, theGlyphRun);
<GlyphRunDrawing ForegroundBrush="Black"> <GlyphRunDrawing.GlyphRun> <GlyphRun CaretStops="{x:Null}" ClusterMap="{x:Null}" IsSideways="False" GlyphOffsets="{x:Null}" GlyphIndices="43 72 79 79 82 3 58 82 85 79 71" BaselineOrigin="0,12.29" FontRenderingEmSize="13.333333333333334" DeviceFontName="{x:Null}" AdvanceWidths="9.62666666666667 7.41333333333333 2.96 2.96 7.41333333333333 3.70666666666667 12.5866666666667 7.41333333333333 4.44 2.96 7.41333333333333" BidiLevel="0"> <GlyphRun.GlyphTypeface> <GlyphTypeface FontUri="C:\WINDOWS\Fonts\TIMES.TTF" /> </GlyphRun.GlyphTypeface> </GlyphRun> </GlyphRunDrawing.GlyphRun> </GlyphRunDrawing>
A GlyphRun is a low-level object intended for use with fixed-format document presentation and print scenarios. A simpler way to draw text to the screen is to use a Label or a TextBlock. For more information about GlyphRun, see the Introduction to the GlyphRun Object and Glyphs Element overview.
Composite Drawings
A DrawingGroup enables you to combine multiple drawings into a single composite drawing. By using a DrawingGroup, you can combine shapes, images, and text into a single Drawing object.
The following example uses a DrawingGroup to combine two GeometryDrawing objects and an ImageDrawing object. This example produces the following output.
// // Create three drawings. // GeometryDrawing ellipseDrawing = new GeometryDrawing( new SolidColorBrush(Color.FromArgb(102, 181, 243, 20)), new Pen(Brushes.Black, 4), new EllipseGeometry(new Point(50,50), 50, 50) ); ImageDrawing kiwiPictureDrawing = new ImageDrawing( new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative)), new Rect(50,50,100,100)); GeometryDrawing ellipseDrawing2 = new GeometryDrawing( new SolidColorBrush(Color.FromArgb(102,181,243,20)), new Pen(Brushes.Black, 4), new EllipseGeometry(new Point(150, 150), 50, 50) ); // Create a DrawingGroup to contain the drawings. DrawingGroup aDrawingGroup = new DrawingGroup(); aDrawingGroup.Children.Add(ellipseDrawing); aDrawingGroup.Children.Add(kiwiPictureDrawing); aDrawingGroup.Children.Add(ellipseDrawing2);
<DrawingGroup> <GeometryDrawing Brush="#66B5F314"> <GeometryDrawing.Geometry> <EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"/> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Black" Thickness="4" /> </GeometryDrawing.Pen> </GeometryDrawing> <ImageDrawing ImageSource="sampleImages\kiwi.png" Rect="50,50,100,100"/> <GeometryDrawing Brush="#66B5F314"> <GeometryDrawing.Geometry> <EllipseGeometry Center="150,150" RadiusX="50" RadiusY="50"/> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Black" Thickness="4" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingGroup>
A DrawingGroup also enables you to apply opacity masks, transforms, bitmap effects, and other operations to its contents. DrawingGroup operations are applied in the following order: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSet, and then Transform.
The following illustration shows the order in which DrawingGroup operations are applied.
The following table describes the properties you can use to manipulate a DrawingGroup object's contents.
Property | Description | Illustration |
---|---|---|
Alters the opacity of selected portions of the DrawingGroup contents. For an example, see How to: Control the Opacity of a Drawing. | ||
Uniformly changes the opacity of the DrawingGroup contents. Use this property to make a Drawing transparent or partially transparent. For an example, see How to: Apply an Opacity Mask to a Drawing. | ||
Applies a BitmapEffect to the DrawingGroup contents. For an example, see How to: Apply a BitmapEffect to a Drawing. | ||
Clips the DrawingGroup contents to a region you describe using a Geometry. For an example, see How to: Clip a Drawing . | ||
Snaps device independent pixels to device pixels along the specified guidelines. This property is useful for ensuring that finely detailed graphics render sharply on low-DPI displays. For an example, see How to: Apply a GuidelineSet to a Drawing. | ||
Transforms the DrawingGroup contents. For an example, see How to: Apply a Transform to a Drawing. |
Display a Drawing as an Image
To display a Drawing with an Image control, use a DrawingImage as the Image control's Source and set the DrawingImage object's DrawingImage.Drawing property to the drawing you want to display.
The following example uses a DrawingImage and an Image control to display a GeometryDrawing. This example produces the following output.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SDKSample { public class DrawingImageExample : Page { public DrawingImageExample() { // // Create the Geometry to draw. // GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add( new EllipseGeometry(new Point(50,50), 45, 20) ); ellipses.Children.Add( new EllipseGeometry(new Point(50, 50), 20, 45) ); // // Create a GeometryDrawing. // GeometryDrawing aGeometryDrawing = new GeometryDrawing(); aGeometryDrawing.Geometry = ellipses; // Paint the drawing with a gradient. aGeometryDrawing.Brush = new LinearGradientBrush( Colors.Blue, Color.FromRgb(204,204,255), new Point(0,0), new Point(1,1)); // Outline the drawing with a solid color. aGeometryDrawing.Pen = new Pen(Brushes.Black, 10); // // Use a DrawingImage and an Image control // to display the drawing. // DrawingImage geometryImage = new DrawingImage(aGeometryDrawing); // Freeze the DrawingImage for performance benefits. geometryImage.Freeze(); Image anImage = new Image(); anImage.Source = geometryImage; anImage.HorizontalAlignment = HorizontalAlignment.Left; // // Place the image inside a border and // add it to the page. // Border exampleBorder = new Border(); exampleBorder.Child = anImage; exampleBorder.BorderBrush = Brushes.Gray; exampleBorder.BorderThickness = new Thickness(1); exampleBorder.HorizontalAlignment = HorizontalAlignment.Left; exampleBorder.VerticalAlignment = VerticalAlignment.Top; exampleBorder.Margin = new Thickness(10); this.Margin = new Thickness(20); this.Background = Brushes.White; this.Content = exampleBorder; } } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" Background="White" Margin="20"> <Border BorderBrush="Gray" BorderThickness="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10"> <!-- This image uses a Drawing object for its source. --> <Image> <Image.Source> <DrawingImage PresentationOptions:Freeze="True"> <DrawingImage.Drawing> <GeometryDrawing> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" /> <EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Brush> <LinearGradientBrush> <GradientStop Offset="0.0" Color="Blue" /> <GradientStop Offset="1.0" Color="#CCCCFF" /> </LinearGradientBrush> </GeometryDrawing.Brush> <GeometryDrawing.Pen> <Pen Thickness="10" Brush="Black" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingImage.Drawing> </DrawingImage> </Image.Source> </Image> </Border> </Page>
Paint an Object with a Drawing
A DrawingBrush is a type of brush that paints an area with a drawing object. You can use it to paint just about any graphical object with a drawing. The Drawing property of a DrawingBrush describes its Drawing. To render a Drawing with a DrawingBrush, add it to the brush using the brush's Drawing property and use the brush to paint a graphical object, such as a control or panel.
The following examples uses a DrawingBrush to paint the Fill of a Rectangle with a pattern created from a GeometryDrawing. This example produces the following output.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SDKSample { public class DrawingBrushExample : Page { public DrawingBrushExample() { // // Create the Geometry to draw. // GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add( new EllipseGeometry(new Point(50,50), 45, 20) ); ellipses.Children.Add( new EllipseGeometry(new Point(50, 50), 20, 45) ); // // Create a GeometryDrawing. // GeometryDrawing aGeometryDrawing = new GeometryDrawing(); aGeometryDrawing.Geometry = ellipses; // Paint the drawing with a gradient. aGeometryDrawing.Brush = new LinearGradientBrush( Colors.Blue, Color.FromRgb(204,204,255), new Point(0,0), new Point(1,1)); // Outline the drawing with a solid color. aGeometryDrawing.Pen = new Pen(Brushes.Black, 10); DrawingBrush patternBrush = new DrawingBrush(aGeometryDrawing); patternBrush.Viewport = new Rect(0, 0, 0.25, 0.25); patternBrush.TileMode = TileMode.Tile; patternBrush.Freeze(); // // Create an object to paint. // Rectangle paintedRectangle = new Rectangle(); paintedRectangle.Width = 100; paintedRectangle.Height = 100; paintedRectangle.Fill = patternBrush; // // Place the image inside a border and // add it to the page. // Border exampleBorder = new Border(); exampleBorder.Child = paintedRectangle; exampleBorder.BorderBrush = Brushes.Gray; exampleBorder.BorderThickness = new Thickness(1); exampleBorder.HorizontalAlignment = HorizontalAlignment.Left; exampleBorder.VerticalAlignment = VerticalAlignment.Top; exampleBorder.Margin = new Thickness(10); this.Margin = new Thickness(20); this.Background = Brushes.White; this.Content = exampleBorder; } } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" Margin="20" Background="White"> <Border BorderBrush="Gray" BorderThickness="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10"> <Rectangle Width="100" Height="100"> <Rectangle.Fill> <DrawingBrush PresentationOptions:Freeze="True" Viewport="0,0,0.25,0.25" TileMode="Tile"> <DrawingBrush.Drawing> <GeometryDrawing> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" /> <EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Brush> <LinearGradientBrush> <GradientStop Offset="0.0" Color="Blue" /> <GradientStop Offset="1.0" Color="#CCCCFF" /> </LinearGradientBrush> </GeometryDrawing.Brush> <GeometryDrawing.Pen> <Pen Thickness="10" Brush="Black" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingBrush.Drawing> </DrawingBrush> </Rectangle.Fill> </Rectangle> </Border> </Page>
The DrawingBrush class provides a variety of options for stretching and tiling its content. For more information about DrawingBrush, see the Painting with Images, Drawings, and Visuals overview.
Render a Drawing with a Visual
A DrawingVisual is a type of visual object designed to render a drawing. Working directly at the visual layer is an option for developers who want to build a highly customized graphical environment, and is not described in this overview. For more information, see the Using DrawingVisual Objects overview.
DrawingContext Objects
The DrawingContext class enables you to populate a Visual or a Drawing with visual content. Many such lower-level graphics objects use a DrawingContext because it describes graphical content very efficiently.
Although the DrawingContext draw methods appear similar to the draw methods of the System.Drawing.Graphics type, they are actually very different. DrawingContext is used with a retained mode graphics system, while the System.Drawing.Graphics type is used with an immediate mode graphics system. When you use a DrawingContext object's draw commands, you are actually storing a set of rendering instructions (although the exact storage mechanism depends on the type of object that supplies the DrawingContext) that will later be used by the graphics system; you are not drawing to the screen in real-time. For more information about how the Windows Presentation Foundation (WPF) graphics system works, see the WPF Graphics Rendering Overview.
You never directly instantiate a DrawingContext; you can, however, acquire a drawing context from certain methods, such as DrawingGroup.Open and DrawingVisual.RenderOpen.
Enumerate the Contents of a Visual
In addition to their other uses, Drawing objects also provide an object model for enumerating the contents of a Visual.
The following example uses the GetDrawing method to retrieve the DrawingGroup value of a Visual and enumerate it.
public void RetrieveDrawing(Visual v) { DrawingGroup dGroup = VisualTreeHelper.GetDrawing(v); EnumDrawingGroup(dGroup); } // Enumerate the drawings in the DrawingGroup. public void EnumDrawingGroup(DrawingGroup drawingGroup) { DrawingCollection dc = drawingGroup.Children; // Enumerate the drawings in the DrawingCollection. foreach (Drawing drawing in dc) { // If the drawing is a DrawingGroup, call the function recursively. if (drawing.GetType() == typeof(DrawingGroup)) { EnumDrawingGroup((DrawingGroup)drawing); } else if (drawing.GetType() == typeof(GeometryDrawing)) { // Perform action based on drawing type. } else if (drawing.GetType() == typeof(ImageDrawing)) { // Perform action based on drawing type. } else if (drawing.GetType() == typeof(GlyphRunDrawing)) { // Perform action based on drawing type. } else if (drawing.GetType() == typeof(VideoDrawing)) { // Perform action based on drawing type. } } }
How-to Topics
Apply a GuidelineSet to a Drawing
This example shows how to apply a GuidelineSet to a DrawingGroup.
The DrawingGroup class is the only type of Drawing that has a GuidelineSet property. To apply a GuidelineSet to another type of Drawing, add it to a DrawingGroup and then apply the GuidelineSet to your DrawingGroup.
Example
The following example creates two DrawingGroup objects that are almost identical; the only difference is: the second DrawingGroup has a GuidelineSet and the first does not.
The following illustration shows the output from the example. Because the rendering difference between the two DrawingGroup objects is so subtle, portions of the drawings are enlarged.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SDKSample { /// <summary> /// This example shows how to apply a GuidelineSet to /// a drawing. /// </summary> public class DrawingGroupGuidelineSetExample : Page { public DrawingGroupGuidelineSetExample() { // // Create a DrawingGroup // that has no guideline set // GeometryDrawing drawing1 = new GeometryDrawing( Brushes.Black, null, new RectangleGeometry(new Rect(0,20,30,80)) ); GeometryGroup whiteRectangles = new GeometryGroup(); whiteRectangles.Children.Add(new RectangleGeometry(new Rect(5.5, 25, 20, 20))); whiteRectangles.Children.Add(new RectangleGeometry(new Rect(5.5, 50, 20, 20))); whiteRectangles.Children.Add(new RectangleGeometry(new Rect(5.5, 75, 20, 20))); GeometryDrawing drawing2 = new GeometryDrawing( Brushes.White, null, whiteRectangles ); // Create a DrawingGroup DrawingGroup drawingGroupWithoutGuidelines = new DrawingGroup(); drawingGroupWithoutGuidelines.Children.Add(drawing1); drawingGroupWithoutGuidelines.Children.Add(drawing2); // Use an Image control and a DrawingImage to // display the drawing. DrawingImage drawingImage01 = new DrawingImage(drawingGroupWithoutGuidelines); // Freeze the DrawingImage for performance benefits. drawingImage01.Freeze(); Image image01 = new Image(); image01.Source = drawingImage01; image01.Stretch = Stretch.None; image01.HorizontalAlignment = HorizontalAlignment.Left; image01.Margin = new Thickness(10); // // Create another DrawingGroup and apply // a blur effect to it. // // Create a clone of the first DrawingGroup. DrawingGroup drawingGroupWithGuidelines = drawingGroupWithoutGuidelines.Clone(); // Create a guideline set. GuidelineSet guidelines = new GuidelineSet(); guidelines.GuidelinesX.Add(5.5); guidelines.GuidelinesX.Add(25.5); guidelines.GuidelinesY.Add(25); guidelines.GuidelinesY.Add(50); guidelines.GuidelinesY.Add(75); // Apply it to the drawing group. drawingGroupWithGuidelines.GuidelineSet = guidelines; // Use another Image control and DrawingImage // to display the drawing. DrawingImage drawingImage02 = new DrawingImage(drawingGroupWithGuidelines); // Freeze the DrawingImage for performance benefits. drawingImage02.Freeze(); Image image02 = new Image(); image02.Source = drawingImage02; image02.Stretch = Stretch.None; image02.HorizontalAlignment = HorizontalAlignment.Left; image02.Margin = new Thickness(50, 10, 10, 10); StackPanel mainPanel = new StackPanel(); mainPanel.Orientation = Orientation.Horizontal; mainPanel.HorizontalAlignment = HorizontalAlignment.Left; mainPanel.Margin = new Thickness(20); mainPanel.Children.Add(image01); mainPanel.Children.Add(image02); // // Use a DrawingBrush to create a grid background. // GeometryDrawing backgroundRectangleDrawing = new GeometryDrawing( Brushes.White, null, new RectangleGeometry(new Rect(0,0,1,1)) ); PolyLineSegment backgroundLine1 = new PolyLineSegment(); backgroundLine1.Points.Add(new Point(1, 0)); backgroundLine1.Points.Add(new Point(1, 0.1)); backgroundLine1.Points.Add(new Point(0, 0.1)); PathFigure line1Figure = new PathFigure(); line1Figure.Segments.Add(backgroundLine1); PathGeometry backgroundLine1Geometry = new PathGeometry(); backgroundLine1Geometry.Figures.Add(line1Figure); GeometryDrawing backgroundLineDrawing1 = new GeometryDrawing( new SolidColorBrush(Color.FromArgb(255,204,204,255)), null, backgroundLine1Geometry ); PolyLineSegment backgroundLine2 = new PolyLineSegment(); backgroundLine2.Points.Add(new Point(0, 1)); backgroundLine2.Points.Add(new Point(0.1, 1)); backgroundLine2.Points.Add(new Point(0.1, 0)); PathFigure line2Figure = new PathFigure(); line2Figure.Segments.Add(backgroundLine2); PathGeometry backgroundLine2Geometry = new PathGeometry(); backgroundLine2Geometry.Figures.Add(line2Figure); GeometryDrawing backgroundLineDrawing2 = new GeometryDrawing( new SolidColorBrush(Color.FromArgb(255, 204, 204, 255)), null, backgroundLine2Geometry ); DrawingGroup backgroundGroup = new DrawingGroup(); backgroundGroup.Children.Add(backgroundRectangleDrawing); backgroundGroup.Children.Add(backgroundLineDrawing1); backgroundGroup.Children.Add(backgroundLineDrawing2); DrawingBrush gridPatternBrush = new DrawingBrush(backgroundGroup); gridPatternBrush.Viewport = new Rect(0, 0, 10, 10); gridPatternBrush.ViewportUnits = BrushMappingMode.Absolute; gridPatternBrush.TileMode = TileMode.Tile; gridPatternBrush.Freeze(); Border mainBorder = new Border(); mainBorder.Background = gridPatternBrush; mainBorder.BorderThickness = new Thickness(1); mainBorder.BorderBrush = Brushes.Gray; mainBorder.HorizontalAlignment = HorizontalAlignment.Left; mainBorder.VerticalAlignment = VerticalAlignment.Top; mainBorder.Margin = new Thickness(20); mainBorder.Child = mainPanel; // // Add the items to the page. // this.Content = mainBorder; this.Background = Brushes.White; } } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions"> <Border BorderThickness="1" BorderBrush="Gray" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20"> <StackPanel Margin="20" Orientation="Horizontal"> <Image Stretch="None" Margin="10"> <Image.Source> <DrawingImage PresentationOptions:Freeze="True"> <DrawingImage.Drawing> <!-- This DrawingGroup has no GuidelineSet. --> <DrawingGroup> <GeometryDrawing Brush="Black"> <GeometryDrawing.Geometry> <RectangleGeometry Rect="0,20,30,80" /> </GeometryDrawing.Geometry> </GeometryDrawing> <GeometryDrawing Brush="White"> <GeometryDrawing.Geometry> <GeometryGroup> <RectangleGeometry Rect="5.5,25, 20,20" /> <RectangleGeometry Rect="5.5,50, 20,20" /> <RectangleGeometry Rect="5.5,75, 20,20" /> </GeometryGroup> </GeometryDrawing.Geometry> </GeometryDrawing> </DrawingGroup> </DrawingImage.Drawing> </DrawingImage> </Image.Source> </Image> <Image Stretch="None" Margin="50,10,10,10"> <Image.Source> <DrawingImage PresentationOptions:Freeze="True"> <DrawingImage.Drawing> <!-- This DrawingGroup has a GuidelineSet. --> <DrawingGroup> <GeometryDrawing Brush="Black"> <GeometryDrawing.Geometry> <RectangleGeometry Rect="0,20,30,80" /> </GeometryDrawing.Geometry> </GeometryDrawing> <GeometryDrawing Brush="White"> <GeometryDrawing.Geometry> <GeometryGroup> <RectangleGeometry Rect="5.5,25, 20,20" /> <RectangleGeometry Rect="5.5,50, 20,20" /> <RectangleGeometry Rect="5.5,75, 20,20" /> </GeometryGroup> </GeometryDrawing.Geometry> </GeometryDrawing> <DrawingGroup.GuidelineSet> <!-- The GuidelineSet --> <GuidelineSet GuidelinesX="5.5,25.5" GuidelinesY="25,50,75" /> </DrawingGroup.GuidelineSet> </DrawingGroup> </DrawingImage.Drawing> </DrawingImage> </Image.Source> </Image> </StackPanel> <Border.Background> <DrawingBrush Viewport="0,0,10,10" ViewportUnits="Absolute" TileMode="Tile" PresentationOptions:Freeze="True"> <DrawingBrush.Drawing> <DrawingGroup> <GeometryDrawing Brush="White"> <GeometryDrawing.Geometry> <RectangleGeometry Rect="0,0,1,1" /> </GeometryDrawing.Geometry> </GeometryDrawing> <GeometryDrawing Geometry="M0,0 L1,0 1,0.1, 0,0.1Z " Brush="#CCCCFF" /> <GeometryDrawing Geometry="M0,0 L0,1 0.1,1, 0.1,0Z" Brush="#CCCCFF" /> </DrawingGroup> </DrawingBrush.Drawing> </DrawingBrush> </Border.Background> </Border> </Page>
Create a Composite Drawing
This example shows how to use a DrawingGroup to create complex drawings by combining multiple Drawing objects into a single composite drawing.
Example
The following example uses a DrawingGroup to create a composite drawing from the GeometryDrawing and ImageDrawing objects. The following illustration shows the output that this example produces.
Note the gray border, which shows the bounds of the drawing.
// // Create three drawings. // GeometryDrawing ellipseDrawing = new GeometryDrawing( new SolidColorBrush(Color.FromArgb(102, 181, 243, 20)), new Pen(Brushes.Black, 4), new EllipseGeometry(new Point(50,50), 50, 50) ); ImageDrawing kiwiPictureDrawing = new ImageDrawing( new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative)), new Rect(50,50,100,100)); GeometryDrawing ellipseDrawing2 = new GeometryDrawing( new SolidColorBrush(Color.FromArgb(102,181,243,20)), new Pen(Brushes.Black, 4), new EllipseGeometry(new Point(150, 150), 50, 50) ); // Create a DrawingGroup to contain the drawings. DrawingGroup aDrawingGroup = new DrawingGroup(); aDrawingGroup.Children.Add(ellipseDrawing); aDrawingGroup.Children.Add(kiwiPictureDrawing); aDrawingGroup.Children.Add(ellipseDrawing2);
<DrawingGroup> <GeometryDrawing Brush="#66B5F314"> <GeometryDrawing.Geometry> <EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"/> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Black" Thickness="4" /> </GeometryDrawing.Pen> </GeometryDrawing> <ImageDrawing ImageSource="sampleImages\kiwi.png" Rect="50,50,100,100"/> <GeometryDrawing Brush="#66B5F314"> <GeometryDrawing.Geometry> <EllipseGeometry Center="150,150" RadiusX="50" RadiusY="50"/> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Black" Thickness="4" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingGroup>
You can use a DrawingGroup to apply a Transform, Opacity setting, OpacityMask, BitmapEffect, ClipGeometry, or GuidelineSet to the drawings it contains. Because a DrawingGroup is also a Drawing, it can contain other DrawingGroup objects.
The following example is similar to the preceding example, except that it uses additional DrawingGroup objects to apply bitmap effects and an opacity mask to some of its drawings. The following illustration shows the output that this example produces.
Note the gray border, which shows the bounds of the drawing.
// Create a DrawingGroup. DrawingGroup mainGroup = new DrawingGroup(); // // Create a GeometryDrawing // GeometryDrawing ellipseDrawing = new GeometryDrawing( new SolidColorBrush(Color.FromArgb(102, 181, 243, 20)), new Pen(Brushes.Black, 4), new EllipseGeometry(new Point(50, 50), 50, 50) ); // // Use a DrawingGroup to apply a blur // bitmap effect to the drawing. // DrawingGroup blurGroup = new DrawingGroup(); blurGroup.Children.Add(ellipseDrawing); BlurBitmapEffect blurEffect = new BlurBitmapEffect(); blurEffect.Radius = 5; blurGroup.BitmapEffect = blurEffect; // Add the DrawingGroup to the main DrawingGroup. mainGroup.Children.Add(blurGroup); // // Create an ImageDrawing. // ImageDrawing kiwiPictureDrawing = new ImageDrawing( new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative)), new Rect(50, 50, 100, 100)); // // Use a DrawingGroup to apply an opacity mask // and a bevel. // DrawingGroup maskedAndBeveledGroup = new DrawingGroup(); maskedAndBeveledGroup.Children.Add(kiwiPictureDrawing); // Create an opacity mask. RadialGradientBrush rgBrush =new RadialGradientBrush(); rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(0,0,0,0), 0.55)); rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(255,0,0,0), 0.65)); rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(0,0,0,0), 0.75)); rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(255,0,0,0), 0.80)); rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(0,0,0,0), 0.90)); rgBrush.GradientStops.Add(new GradientStop(Color.FromArgb(255,0,0,0), 1.0)); maskedAndBeveledGroup.OpacityMask = rgBrush; // Apply a bevel. maskedAndBeveledGroup.BitmapEffect = new BevelBitmapEffect(); // Add the DrawingGroup to the main group. mainGroup.Children.Add(maskedAndBeveledGroup); // // Create another GeometryDrawing. // GeometryDrawing ellipseDrawing2 = new GeometryDrawing( new SolidColorBrush(Color.FromArgb(102, 181, 243, 20)), new Pen(Brushes.Black, 4), new EllipseGeometry(new Point(150, 150), 50, 50) ); // Add the DrawingGroup to the main group. mainGroup.Children.Add(ellipseDrawing2);
<DrawingGroup> <DrawingGroup> <GeometryDrawing Brush="#66B5F314"> <GeometryDrawing.Geometry> <EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50"/> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Black" Thickness="4" /> </GeometryDrawing.Pen> </GeometryDrawing> <DrawingGroup.BitmapEffect> <BlurBitmapEffect Radius="5" /> </DrawingGroup.BitmapEffect> </DrawingGroup> <DrawingGroup> <ImageDrawing ImageSource="sampleImages\kiwi.png" Rect="50,50,100,100"/> <DrawingGroup.BitmapEffect> <BevelBitmapEffect /> </DrawingGroup.BitmapEffect> <DrawingGroup.OpacityMask> <RadialGradientBrush> <GradientStop Offset="0.55" Color="#00000000" /> <GradientStop Offset="0.65" Color="#FF000000" /> <GradientStop Offset="0.75" Color="#00000000" /> <GradientStop Offset="0.80" Color="#FF000000" /> <GradientStop Offset="0.90" Color="#00000000" /> <GradientStop Offset="1.0" Color="#FF000000" /> </RadialGradientBrush> </DrawingGroup.OpacityMask> </DrawingGroup> <GeometryDrawing Brush="#66B5F314"> <GeometryDrawing.Geometry> <EllipseGeometry Center="150,150" RadiusX="50" RadiusY="50"/> </GeometryDrawing.Geometry> <GeometryDrawing.Pen> <Pen Brush="Black" Thickness="4" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingGroup>
For more information about Drawing objects, see Drawing Objects Overview.
Create a GeometryDrawing
This example shows how to create and display a GeometryDrawing. A GeometryDrawing enables you to create shape with a fill and an outline by associating a Pen and a Brush with a Geometry. The Geometry describes the shape's structure, the Brush describes the shape's fill, and the Pen describes the shape's outline.
Example
The following example uses a GeometryDrawing to render a shape. The shape is described by a GeometryGroup and two EllipseGeometry objects. The shape's interior is painted with a LinearGradientBrush and its outline is drawn with a Black Pen. The GeometryDrawing is displayed using an ImageDrawing and an Image element.
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SDKSample { public class GeometryDrawingExample : Page { public GeometryDrawingExample() { // // Create the Geometry to draw. // GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add( new EllipseGeometry(new Point(50,50), 45, 20) ); ellipses.Children.Add( new EllipseGeometry(new Point(50, 50), 20, 45) ); // // Create a GeometryDrawing. // GeometryDrawing aGeometryDrawing = new GeometryDrawing(); aGeometryDrawing.Geometry = ellipses; // Paint the drawing with a gradient. aGeometryDrawing.Brush = new LinearGradientBrush( Colors.Blue, Color.FromRgb(204,204,255), new Point(0,0), new Point(1,1)); // Outline the drawing with a solid color. aGeometryDrawing.Pen = new Pen(Brushes.Black, 10); // // Use a DrawingImage and an Image control // to display the drawing. // DrawingImage geometryImage = new DrawingImage(aGeometryDrawing); // Freeze the DrawingImage for performance benefits. geometryImage.Freeze(); Image anImage = new Image(); anImage.Source = geometryImage; anImage.Stretch = Stretch.None; anImage.HorizontalAlignment = HorizontalAlignment.Left; // // Place the image inside a border and // add it to the page. // Border exampleBorder = new Border(); exampleBorder.Child = anImage; exampleBorder.BorderBrush = Brushes.Gray; exampleBorder.BorderThickness = new Thickness(1); exampleBorder.HorizontalAlignment = HorizontalAlignment.Left; exampleBorder.VerticalAlignment = VerticalAlignment.Top; exampleBorder.Margin = new Thickness(10); this.Margin = new Thickness(20); this.Background = Brushes.White; this.Content = exampleBorder; } } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" Margin="20" Background="White"> <Border BorderBrush="Gray" BorderThickness="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10"> <Image Stretch="None" HorizontalAlignment="Left"> <Image.Source> <DrawingImage PresentationOptions:Freeze="True"> <DrawingImage.Drawing> <GeometryDrawing> <GeometryDrawing.Geometry> <!-- Create a composite shape. --> <GeometryGroup> <EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" /> <EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Brush> <!-- Paint the drawing with a gradient. --> <LinearGradientBrush> <GradientStop Offset="0.0" Color="Blue" /> <GradientStop Offset="1.0" Color="#CCCCFF" /> </LinearGradientBrush> </GeometryDrawing.Brush> <GeometryDrawing.Pen> <!-- Outline the drawing with a solid color. --> <Pen Thickness="10" Brush="Black" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingImage.Drawing> </DrawingImage> </Image.Source> </Image> </Border> </Page>
The following illustration shows the resulting GeometryDrawing.
To create more complex drawings, you can combine multiple drawing objects into a single composite drawing using a DrawingGroup.
Draw an Image Using ImageDrawing
This example shows how to use an ImageDrawing to draw an image. An ImageDrawing enables you display an ImageSource with a DrawingBrush, DrawingImage, or Visual. To draw an image, you create an ImageDrawing and set its ImageDrawing.ImageSource and ImageDrawing.Rect properties. The ImageDrawing.ImageSource property specifies the image to draw, and the ImageDrawing.Rect property specifies the position and size of each image.
Example
The following example creates a composite drawing using four ImageDrawing objects. This example produces the following image:
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Media.Imaging; namespace SDKSample { public class ImageDrawingExample : Page { public ImageDrawingExample() { // Create a DrawingGroup to combine the ImageDrawing objects. DrawingGroup imageDrawings = new DrawingGroup(); // Create a 100 by 100 image with an upper-left point of (75,75). ImageDrawing bigKiwi = new ImageDrawing(); bigKiwi.Rect = new Rect(75, 75, 100, 100); bigKiwi.ImageSource = new BitmapImage( new Uri(@"sampleImages\kiwi.png", UriKind.Relative)); imageDrawings.Children.Add(bigKiwi); // Create a 25 by 25 image with an upper-left point of (0,150). ImageDrawing smallKiwi1 = new ImageDrawing(); smallKiwi1.Rect = new Rect(0, 150, 25, 25); smallKiwi1.ImageSource = new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative)); imageDrawings.Children.Add(smallKiwi1); // Create a 25 by 25 image with an upper-left point of (150,0). ImageDrawing smallKiwi2 = new ImageDrawing(); smallKiwi2.Rect = new Rect(150, 0, 25, 25); smallKiwi2.ImageSource = new BitmapImage(new Uri(@"sampleImages\kiwi.png", UriKind.Relative)); imageDrawings.Children.Add(smallKiwi2); // Create a 75 by 75 image with an upper-left point of (0,0). ImageDrawing wholeKiwi = new ImageDrawing(); wholeKiwi.Rect = new Rect(0, 0, 75, 75); wholeKiwi.ImageSource = new BitmapImage(new Uri(@"sampleImages\wholekiwi.png", UriKind.Relative)); imageDrawings.Children.Add(wholeKiwi); // // Use a DrawingImage and an Image control to // display the drawings. // DrawingImage drawingImageSource = new DrawingImage(imageDrawings); // Freeze the DrawingImage for performance benefits. drawingImageSource.Freeze(); Image imageControl = new Image(); imageControl.Stretch = Stretch.None; imageControl.Source = drawingImageSource; // Create a border to contain the Image control. Border imageBorder = new Border(); imageBorder.BorderBrush = Brushes.Gray; imageBorder.BorderThickness = new Thickness(1); imageBorder.HorizontalAlignment = HorizontalAlignment.Left; imageBorder.VerticalAlignment = VerticalAlignment.Top; imageBorder.Margin = new Thickness(20); imageBorder.Child = imageControl; this.Background = Brushes.White; this.Margin = new Thickness(20); this.Content = imageBorder; } } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" Background="White" Margin="20"> <Border BorderBrush="Gray" BorderThickness="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20"> <Image Stretch="None"> <Image.Source> <DrawingImage PresentationOptions:Freeze="True"> <DrawingImage.Drawing> <DrawingGroup> <!-- The Rect property specifies that the image only fill a 100 by 100 rectangular area. --> <ImageDrawing Rect="75,75,100,100" ImageSource="sampleImages\kiwi.png"/> <!-- This image is set to fill a 25 by 25 rectangular area. --> <ImageDrawing Rect="0,150,25,25" ImageSource="sampleImages\kiwi.png"/> <!-- This image is set to fill a 25 by 25 rectangular area. --> <ImageDrawing Rect="150,0,25,25" ImageSource="sampleImages\kiwi.png"/> <!-- This image is set to fill a 75 by 75 rectangular area. --> <ImageDrawing Rect="0,0,75,75" ImageSource="sampleImages\wholekiwi.png"/> </DrawingGroup> </DrawingImage.Drawing> </DrawingImage> </Image.Source> </Image> </Border> </Page>
For an example showing a simple way to display an image without using ImageDrawing, see How to: Use the Image Element.
Play Media using a VideoDrawing
To play an audio or video file, you use a VideoDrawing and a MediaPlayer. There are two ways to load and play media. The first is to use a MediaPlayer and a VideoDrawing by themselves, and the second way is to create your own MediaTimeline to use with the MediaPlayer and VideoDrawing.
Note |
---|
When distributing media with your application, you cannot use a media file as a project resource, like you would an image. In your project file, you must instead set the media type to Content and set CopyToOutputDirectory to PreserveNewest or Always. |
Example
The following example uses a VideoDrawing and a MediaPlayer to play a video file once.
// // Create a VideoDrawing. // MediaPlayer player = new MediaPlayer(); player.Open(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative)); VideoDrawing aVideoDrawing = new VideoDrawing(); aVideoDrawing.Rect = new Rect(0, 0, 100, 100); aVideoDrawing.Player = player; // Play the video once. player.Play();
To gain additional timing control over the media, use a MediaTimeline with the MediaPlayer and VideoDrawing objects. The MediaTimeline enables you to specify whether the video should repeat.
Example
The following example uses a MediaTimeline with the MediaPlayer and VideoDrawing objects to play a video repeatedly.
// // Create a VideoDrawing that repeats. // // Create a MediaTimeline. MediaTimeline mTimeline = new MediaTimeline(new Uri(@"sampleMedia\xbox.wmv", UriKind.Relative)); // Set the timeline to repeat. mTimeline.RepeatBehavior = RepeatBehavior.Forever; // Create a clock from the MediaTimeline. MediaClock mClock = mTimeline.CreateClock(); MediaPlayer repeatingVideoDrawingPlayer = new MediaPlayer(); repeatingVideoDrawingPlayer.Clock = mClock; VideoDrawing repeatingVideoDrawing = new VideoDrawing(); repeatingVideoDrawing.Rect = new Rect(150, 0, 100, 100); repeatingVideoDrawing.Player = repeatingVideoDrawingPlayer;
Note that, when you use a MediaTimeline, you use the interactive ClockController returned from the Controller property of the MediaClock to control media playback instead of the interactive methods of MediaPlayer.
Use a Drawing as an Image Source
This example shows how to use a Drawing as the Source for an Image control. To display a Drawing with an Image control, use a DrawingImage as the Image control's Source and set the DrawingImage object's DrawingImage.Drawing property to the drawing you want to display.
Example
The following example uses a DrawingImage and an Image control to display a GeometryDrawing. This example produces the following output:
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SDKSample { public class DrawingImageExample : Page { public DrawingImageExample() { // // Create the Geometry to draw. // GeometryGroup ellipses = new GeometryGroup(); ellipses.Children.Add( new EllipseGeometry(new Point(50,50), 45, 20) ); ellipses.Children.Add( new EllipseGeometry(new Point(50, 50), 20, 45) ); // // Create a GeometryDrawing. // GeometryDrawing aGeometryDrawing = new GeometryDrawing(); aGeometryDrawing.Geometry = ellipses; // Paint the drawing with a gradient. aGeometryDrawing.Brush = new LinearGradientBrush( Colors.Blue, Color.FromRgb(204,204,255), new Point(0,0), new Point(1,1)); // Outline the drawing with a solid color. aGeometryDrawing.Pen = new Pen(Brushes.Black, 10); // // Use a DrawingImage and an Image control // to display the drawing. // DrawingImage geometryImage = new DrawingImage(aGeometryDrawing); // Freeze the DrawingImage for performance benefits. geometryImage.Freeze(); Image anImage = new Image(); anImage.Source = geometryImage; anImage.HorizontalAlignment = HorizontalAlignment.Left; // // Place the image inside a border and // add it to the page. // Border exampleBorder = new Border(); exampleBorder.Child = anImage; exampleBorder.BorderBrush = Brushes.Gray; exampleBorder.BorderThickness = new Thickness(1); exampleBorder.HorizontalAlignment = HorizontalAlignment.Left; exampleBorder.VerticalAlignment = VerticalAlignment.Top; exampleBorder.Margin = new Thickness(10); this.Margin = new Thickness(20); this.Background = Brushes.White; this.Content = exampleBorder; } } }
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="PresentationOptions" Background="White" Margin="20"> <Border BorderBrush="Gray" BorderThickness="1" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10"> <!-- This image uses a Drawing object for its source. --> <Image> <Image.Source> <DrawingImage PresentationOptions:Freeze="True"> <DrawingImage.Drawing> <GeometryDrawing> <GeometryDrawing.Geometry> <GeometryGroup> <EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" /> <EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" /> </GeometryGroup> </GeometryDrawing.Geometry> <GeometryDrawing.Brush> <LinearGradientBrush> <GradientStop Offset="0.0" Color="Blue" /> <GradientStop Offset="1.0" Color="#CCCCFF" /> </LinearGradientBrush> </GeometryDrawing.Brush> <GeometryDrawing.Pen> <Pen Thickness="10" Brush="Black" /> </GeometryDrawing.Pen> </GeometryDrawing> </DrawingImage.Drawing> </DrawingImage> </Image.Source> </Image> </Border> </Page>
'프로그래밍 > WPF' 카테고리의 다른 글
Data Binding (0) | 2017.01.10 |
---|---|
Graphics and Multimedia - Animation Overview (0) | 2017.01.07 |
Documents (0) | 2016.11.19 |
Control Library 3 (0) | 2016.11.18 |
Control Library 2 (0) | 2016.11.13 |
Although this example uses a LinearGradientBrush, the process is the same for animating GradientStop objects inside a RadialGradientBrush.
For additional examples, see the Brushes Sample.