Given a canvas with black background and some white children on it:
How can I make all children transparent also through canvas background? Behind the canvas may be an image or other content. All solutions that I found are not satisfying:
Render the canvas to PNG image and turn all white color to transparency. In this case I would loose all benefits of a vector graphic when using the canvas in a viewbox.
Create one invers child of all children and render it in black on a transparent canvas. But I'm not shure if that's possible.
Note: The children of the canvas may be changed so I'm not searching for a static solution (e.g. a fixed path around all children).
Any ideas how to create such a mask?
Create a geometry with holes and use it with a Path element, e.g. like this:
<Grid Background="White">
<Path Fill="Black"
Data="M0,0 L1000,0 1000,1000 0,1000Z M100,100 L200,100 200,200 100,200Z"/>
</Grid>
Related
Using WPF, I need something like Canvas, but with the option that elements are sized in relation to the canvas. I'm displaying an Image and multiple Rectangle elements and would like to have the image as well as the rectangles sized when the container is resized. Using a Canvas, the elements always retain the original size.
The answer is to use a ViewBox around your Canvas. Try this:
<ViewBox>
<Canvas>
<!-- Your elements -->
</Canvas>
</ViewBox>
You should set the Stretch and StretchDirection properties according to your needs. The ViewBox will scale all UI elements inside equally. Please see the first linked page on MSDN for further help with this class.
You are looking for ViewBox. And yes, it's a short, but an answer =P.
I got a Canvas inside ScrollViewer.
<ScrollViewer x:Name="svWorkSpace" Visibility="Collapsed" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
Tapped="svWorkSpace_Tapped"
PointerPressed="svWorkSpace_PointerPressed"
PointerMoved="svWorkSpace_PointerMoved"
PointerReleased="svWorkSpace_PointerReleased">
<Grid>
<Image x:Name="cvWorkImage"/>
<Canvas x:Name="cvWorkSpace"/>
</Grid>
</ScrollViewer>
In PointerPressed code, I capture the starting point and in PointerMoved code, I draw a rectangle as pointer moves (also remove trailing rectangle a I move, maintaining only a single rectangle in the canvas. I achieve rectangle sizing effect using this method). PointerReleased will accept the last rectangle.
Everything works fine using a mouse in touch enabled device but not using finger. The image just scroll when I move my finger.
Tried to move the code into Canvas, like below. Failed to draw rectangle using both mouse and touch.
<ScrollViewer x:Name="svWorkSpace" Visibility="Collapsed" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid>
<Image x:Name="cvWorkImage"/>
<Canvas x:Name="cvWorkSpace"
Tapped="svWorkSpace_Tapped"
PointerPressed="svWorkSpace_PointerPressed"
PointerMoved="svWorkSpace_PointerMoved"
PointerReleased="svWorkSpace_PointerReleased"/>
</Grid>
</ScrollViewer>
Point me in the right direction pls.
When the ScrollViewer receives the touch based PointerPressed it turns to Direct Manipulation to responsively handle panning and zooming. Direct Manipulation captures the pointer input so the Canvas' PointerMoved and PointerReleased events don't fire. No events -> no drawing.
The ScrollViewer pan or zoom with the mouse, so mouse events make it through to the Canvas.
Assuming you always want the Canvas to handle the pointer events rather than scrolling (perhaps there are other controls in the Grid that make use of the ScrollViewer), you can set the Canvas' ManipulationMone to all to let touches on the Canvas block touches on the ScrollViewer
<Canvas x:Name="cvWorkSpace"
Background={ThemeResource WorkSpaceBackgroundBrush}
Tapped="svWorkSpace_Tapped"
ManipulationMode="All"
PointerPressed="svWorkSpace_PointerPressed"
PointerMoved="svWorkSpace_PointerMoved"
PointerReleased="svWorkSpace_PointerReleased"/>
If you only sometimes want the Canvas to handle the pointer events then you can switch the ManipulationMode back to System to let the ScrollViewer handle it. If you want to draw on the Canvas with single-touch and pan/zoom with multi-touch then you can handle Manipulation events on the Canvas to pan and zoom.
Also make sure the Canvas isn't transparent and lets the pointer events pass through to whatever is behind it. If you want to draw on top of an image you can set an ImageBrush with the image as the Canvas' background rather than using a separate Image control.
I have a WPF image, and I'm trying to draw something on it (Lets say a smiley, 2 blue circles for eyes and and a red ellipse for the mouth).
I've made a small Rectangle over the image, and made it stretched.
<Grid Name="mGrid">
<Rectangle Height="0" HorizontalAlignment="Stretch" Stretch="Fill" Name="mImageFrame" VerticalAlignment="Stretch" Width="0" />
</Grid >
I used a DrawingBrush to draw the circles in the rectangle.
Obviously this is wrong, because I have 2 problems:
1. The DrawingBrush seems to have a different scale. It will scale according to the largest item it's drawing.
2. I can only use one brush color.
So, how can I somehow draw over an image so it keeps the same proportions ?
And how can I use a different color for each shape ?
You can put Shapes on a Canvas that overlays the Image, and put the whole thing in a Viewbox. This requires that you define absolute coordinates by either setting the Image's Stretch property to None (and thus force the Image size to that of its Source bitmap) or explicitly set is Width or Height.
<Viewbox>
<Grid>
<Image Source="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"
Stretch="None"/>
<Canvas>
<Ellipse Canvas.Left="420" Canvas.Top="480"
Fill="Red" Width="100" Height="100"/>
... more shapes here ...
</Canvas>
</Grid>
</Viewbox>
One solution would be to put both the drawing and the Image into a ViewBox control. You can find out more about the Viewbox from the Viewbox Class page at MSDN. Basically, it provides the same stretching capabilities as the Image control.
You may also like to view the Shapes and Basic Drawing in WPF Overview page at MSDN.
Hey, I'm having an issue with adorners. I created resize adorners which have four Thumb controls, one for each of the corners of the control being decorated. The control is being drawn on a Canvas, and the user may select it and resize it.
The canvas is hosted on a ZoomBoxPanel control, which basically applies a ScaleTransform and TranslateTransform to the whole thing to provide zoom and pan support.
Problem is that when an item is outside the bounds of the zoom panel, and the item is cropped as you'd expect (like when you set ClipToBounds = true), you can still see the adorners! Could anyone please tell me a way to prevent this?
Evidence. The black square is the one selected, two resize thumbs are visible (right), the others should not be visible (left)
Thanks!!
Fixed it, solution was to put an AdornerDecorator object immediately above the Canvas :)
<AdornerDecorator>
<Canvas>
</AdornerDecorator>
I'm working on a Microsoft Surface and attaching a round image object to a ScatterViewItem. I'm having an issue hiding the background of the square ScatterViewItem. If I go in and set the background to transparent, it's not transparent, it's more like gray translucent. So what I end up with is a round image in the middle sitting on a square with gray translucent edges. How do I hide this? I'm doing this programmatically through C#.
What you're seeing isn't really the svi background, but the shadow that is part of the default template. If you want to get rid of the shadow, you need to redefine the control template.
So like this:
<s:ScatterView>
<s:ScatterViewItem Background="Transparent">
<s:ScatterViewItem.Template>
<ControlTemplate>
<TextBlock>Hello World</TextBlock>
</ControlTemplate>
</s:ScatterViewItem.Template>
</s:ScatterViewItem>
</s:ScatterView>
Be aware that if you replace it like that, you lose all the other little visual flare like the 'pick up' effect and the shimmer. If you want to keep those, just use blend to edit a copy of the existing template and remove the shadow.