How to do picture shaped button in WPF? - c#

I want a picture with transparent background to be a button.
The shape of the picture is custom (not an ellipse or something like that). So, I need it to be lighted and be possible to press (in the shape of 1 itself!).
I've only started working on WPf and don't know how to do this. And I couldn't really figure out how to do it in my case (although there are alike questions on the platform).
Would be very thankful if you give me a detailed answer!

<Button>
<Image Source="num1"/>
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Button.Template>
</Button>
You can set the template of the button something like this:
<Image Source="num1.png"
Width="16"
Height="16"/>
Also this might help
<Button.Background>
<ImageBrush ImageSource="num1.png" Stretch="Fill" TileMode="None" />
</Button.Background>

It sounds like you need to handle a limited number of pictures and if all of them are relatively simple like that "1" the task seems doable. The most challenging part is to construct the geometry element that cuts the button in its specific shape. If you only have the images in raster formats (*.png, *.jpg, *.bmp - a rectangular map of colored pixels), you will first have to them to vector images (presented with a set of mathematical functions instead of pixel data). It is not a trivial task, but if an image has a simple outline, you should be able to get good results. There are different pieces of software that handle this problem. Here is some blog post on this topic, but if does not meet your needs, you can also search for "How to trace a raster image", "Convert a raster image to a vector one" etc. If you are successful at this step, you will get some SVG images. Alas WPF does not support SVG images, as it has its own "language" for translating geometry data. So the svgs should be translated to WPF Geometries. I found some blogs while looking for "SVG to XAML", "SVG to WPF path" etc. Here is one with several approaches to the task.
When you have the WPF Geometries, you will be able to cut the button like this:
<Button>
<Button.Template>
<ControlTemplate>
<Image Source=". . .">
<Image.Clip>
<Geometry . . . />
</Image.Clip>
</Image>
</ControlTemplate>
</Button.Template>
</Button>
Of course, you can make it much more maintainable if you can create a custom control type that has the image data and geometry data exposed as properties, and then bind them in the template.
On the bottom line, this is not an easy task, which can become even more cumbersome if you have to add new geometries in the future. As Clemens mentioned in the comments, sticking with rectangular images that are hit testable in the whole bounding rectangle will make the task immensely easier.

You can draw a graph by yourself,and you can get Path Data via the link below
Get path geometry from image
<Button Width="100" Height="100" >
<Button.Template >
<ControlTemplate>
<Path x:Name="path" Data="xxxxx " Stretch="Fill" Fill="Azure" RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
<Path.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="22" Color="#FF646464"/>
</Path.Effect>
</Path>
</ControlTemplate>
</Button.Template>
</Button>

Related

How to position "Selection Box" with ItemContainerStyle of a ListView?

I've been reading this documentation and I was wondering if it's possible to position the selection check box of the container? Specifically, this thing here:
Ideally, I want it aligned on the right. So far I've tried to use
<ListView.ItemContainerStyle>
<Style TargetType="WHAT DO I WRITE HERE?">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</ListView.ItemContainerStyle>
With various TargetTypes. Is it even possible to position that Selection-box?
To be honest you're looking in the wrong place. The ItemContainerStyle is adjust the margin padding and such properties of the container of the items of a listview.
What You need is a style for a ListViewItem. Lucky for us it's easily available from the ListViewItem styles and templates from the MSDN Documentation.
I won't paste the whole code here since, it's huge and it's cause deviated focus from the actual code that you need to tweak.
From the style from the above link, pick the second style of the two mentioned and refer to the below code:
<Border x:Name="MultiSelectSquare"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
BorderThickness="2"
Width="20"
Height="20"
Margin="12,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Visibility="Collapsed" >
<Border.Clip>
<RectangleGeometry Rect="0,0,20,20">
<RectangleGeometry.Transform>
<TranslateTransform x:Name="MultiSelectClipTransform"/>
</RectangleGeometry.Transform>
</RectangleGeometry>
</Border.Clip>
<Border.RenderTransform>
<TranslateTransform x:Name="MultiSelectCheckBoxTransform"/>
</Border.RenderTransform>
<FontIcon x:Name="MultiSelectCheck"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph=""
FontSize="16"
Foreground="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
Visibility="Collapsed"
Opacity="0"/>
</Border>
The above code handles the checkbox kinda tick mark with border for SelectionMode="Multiple".
All the changes you want to do must be done in this style and the above code section of the style.
Please Note: I would advise not to play around with Visibility and Opacity property as they are modified using VisualStates. Don't worry about them they'll change states at runtime.

How can I make multiple Path elements inside a Canvas scale to fit its parent?

I have created a series of shapes in Illustrator, and exported them to an .ai file. When I import this file in Blend for Visual Studio, I get something that looks like this:
<Canvas x:Name="ManyPaths" Grid.Row="0">
<Path Data="F1M0,53.135L0.004,102.44 22.03,151.59 55.042,0z" Fill="#FF8B1A34" Height="151.59" Canvas.Left="0.017" Stretch="None" Canvas.Top="182.406" Width="55.042"/>
<Path Data="F1M0.003,34.152L22.027,49.15 0,0z" Fill="#FF991937" Height="49.15" Canvas.Left="0.02" Stretch="None" Canvas.Top="284.846" Width="22.027"/>
</Canvas>
There are numerous Paths, I won't list them all here for brevity. When put together, they make a fixed size rectangle. I would like to use this rectangle at the top of my app as the header image. I can resize the Canvas element in Blend, but I cannot get the collective Paths to fit the Canvas, and be resized along with it. Since I'm designing for various size screens, I would like the header image to scale. I have tried nesting it in a Grid, but that doesn't work.
Looks like the traditional way to do Paths in C# is
<Path Grid.Row="1" Stroke="Black" StrokeThickness="2" Fill="Green">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="100,100">
<QuadraticBezierSegment Point1="165,25" Point2="225,100" />
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
I'm not sure if there is a means to convert the first format to the second, but I would like to reuse my .ai files if possible, instead of recreating them from scratch.
There is no need to convert to the second format. Using the Data attribute is more concise and often clearer.
You can wrap your Canvas in a ViewBox to let it scale to its container. The Stretch attribute can control if it stretches uniformly or distorts (you probably want uniform)
<Viewbox Stretch="Uniform" Grid.Row="0">
<Grid x:Name="ManyPaths" >
<Path Data="F1M0,53.135L0.004,102.44 22.03,151.59 55.042,0z" Fill="#FF8B1A34" Height="151.59" Canvas.Left="0.017" Stretch="None" Canvas.Top="182.406" Width="55.042"/>
<Path Data="F1M0.003,34.152L22.027,49.15 0,0z" Fill="#FF991937" Height="49.15" Canvas.Left="0.02" Stretch="None" Canvas.Top="284.846" Width="22.027"/>
</Grid>
</Viewbox>

Scratching the color off a picture

I'm working on a project with the kinect (I'm adding in case someone has a good way to do using the kinect) but I think this is mostly some programming issue in C# and WPF. I want to make to have 2 pictures, one on top of the other and with a mouse click, be able to scratch the first picture out. I tried using inkcanvas and put the picture in the inkcanvas but I can only draw on top of it.
Can someone give me an idea or some methods he think it would be better way to proceed?
An idea might be using an OpacityMask which is a VisualBrush that contains your InkCanvas.
This is what I did, Thanks #HB for your help. part of the code comes from
http://geekswithblogs.net/tkokke/archive/2009/03/02/scratchcard-in-wpf.aspx if anyone wants to know or need it.
<Border Background="#FF909090" BorderBrush="#FF000000"
BorderThickness="2,2,2,2">
<Grid Width="Auto" Height="Auto">
<Grid.Background>
<ImageBrush ImageSource="birthday_cake_by_protoperahe.jpg"/>
</Grid.Background>
<InkCanvas x:Name="inkCanvas"
Background="{x:Null}">
<InkCanvas.DefaultDrawingAttributes>
<DrawingAttributes Height="25" Width="25"/>
</InkCanvas.DefaultDrawingAttributes>
</InkCanvas>
<Image IsHitTestVisible="False" Source="planet.jpg" Stretch="Fill">
<Image.OpacityMask>
<VisualBrush
Visual="{Binding ElementName=inkCanvas}"/>
</Image.OpacityMask>
</Image>
</Grid>

WPF semi transparent button to control MediaElement

I am making WPF application that plays a video.
I use MediaElement, I wish to add Play/Pause button, I want that image button to be in shape of play, and only the image i put on the button will be shown. the rest to be transparent.
e.g: put a play triangle image on a rectangle button will only show the triangle image.
You're going to have to "make your own", fortunately it's not that hard, here is a working example (doesn't handle mouse hovering though):
<Grid Background="Black">
<Button HorizontalAlignment="Center" VerticalAlignment="Center">
<Button.Template>
<ControlTemplate TargetType="Button">
<StackPanel>
<ContentPresenter Content="{TemplateBinding Content}" />
</StackPanel>
</ControlTemplate>
</Button.Template>
<Path Data="M 0,0 L 15,10 L 0,20" Fill="Green"/>
</Button>
</Grid>
The grid is only here to show that only the arrow is actually drawn, and the Path thing is vectorial data to draw a Play button.
It looks like this:

Advanced Effects in WPF?

I've been trying to recreate this GUI purely in WPF, and I'm having problems:
The shadow. The shadow on the main element doesn't show inside the fill - when using DropShadowEffect in WPF, it does. As of yet I've found no solution to this.
Background images - the main element has a slight pattern in it, a diagonal one. But in WPF, I can't use background images like this. Chances are I'm just missing something.
The slight inset, in the main element (at the top) - not easily replicated.
So anyway, I guess my question is, how can I accomplish these kinds of effects in WPF?
Hopefully this snippet will point you in the right direction:
<Grid>
<Border x:Name="Blur"
BorderThickness="5"
CornerRadius="5"
BorderBrush="#7F000000">
<Border.Effect>
<BlurEffect Radius="8" />
</Border.Effect>
</Border>
<Border x:Name="Outter"
BorderBrush="#CCD3D3D3"
BorderThickness="1"
CornerRadius="5"
Margin="2">
<Border.Background>
<ImageBrush Viewbox="0,0,45,38"
ViewboxUnits="Absolute"
Viewport="0,0,45,38"
ViewportUnits="Absolute"
TileMode="Tile"
ImageSource="<SomeImageThatIsATileOfThePattern>"
Opacity="0.3"
Stretch="Fill" />
</Border.Background>
</Border>
<Border x:Name="Inner"
BorderThickness="0,1,0,0"
CornerRadius="5"
Margin="2,4,2,2"
BorderBrush="#7FD3D3D3" />
<ItemsControl Background="HotPink"
Margin="11"
Height="21" />
</Grid>
The result is:
[I used a generic image, just to show the repetition. The original image is W50xH38 in size - hope the repetition is noticeable]
Play with the values for Viewbox and Viewport to adjust to your image.
Of course, the ItemsControl should not have the pink background and its height should not be a constant, it was done for demo purposes.

Categories

Resources