I have to draw some custom shapes in wpf, like Square, Ellipse, Spade etc etc as shown in the image.
Now I need to apply some simple borders to those shapes like shown in the image,
How should I achieve it. Shape size id variable, it could be small, medium, large and extra large.
what I have done till now is draw all the images using this
Ellipse
<Ellipse Width='4' Height='4' Stroke='Green' Fill='Red'>
Triangle
<Polygon Points='2 0, 4 4,0 4' Stroke='Green' Fill='Red'>
Spade
<Polygon Points='2 0, 4 2,2 4,0 2' Stroke='Green' Fill='Red'> and so on.
The first border with simple line is not a problem. I could use a simple border or just change the size of stroke so they show they have a border, problem lies in dashed lines and double lines border
Check a set of Stroke... properties of Shape class
StrokeThickness - to set thickness,
StrokeDashArray - to setup dashed pattern
Regarding last two items in second drop down - I do not see an easy way of implementing such border for any generic shape.
[Update] Check this question it contains some ideas applicable to your situation
Related
I'm creating a speech bubble control for my application, and the way I'm looking to do it is to use a rectangle with rounded corners, then place a shape on top that forms the "origin" of the speech bubble. These are arranged in a Grid so that the bubble resizes to its content whilst keeping the origin shape constant (i.e. it won't stretch). Now, here's my question; is it possible to create a Path in WPF with one of the sides omitted (i.e. so the stroke is omitted from that edge, but the fill is still present)?
I know I could do it by placing 2 shapes on top of each other, but I'm looking for a solution that's as simple as possible!
Thanks, Lee.
Yes, it's possible. You just omit one of the edges. The Fill will still be applied inside the shape:
<Path Fill="Beige" Stroke="Black" Data="M 0,0 L 20,0 L 0,20"></Path>
Above is the image i am using. What i am trying to achieve is removing the red portion of the border from the image. How can I achieve this programmatically in windows phone? I found WriteableBitmapExtensions.Crop() method, but I am confused with the arguments (how i can find the x,y position of the image, as well as the size and the width?)
Also another issue I am facing is: I will get the images with differently sized borders, so I can't hardcode the x or y values.
Can anyone suggest a solution, or guide me to solve the issue?
This is not such a trivial thing and you haven't shared any code with us, so I can give you a few suggestions. Every WriteableBitmap has width and height defined. You should be able to access it via
wb.PixelWidth;
wb.PixelHeight;
where wb is your WriteableBitmap (the picture)
Having said that, it's trivial to crop a WriteableBitmap using WriteableBitmapEx library
var croppedBmp = wb.Crop(10, 10, 300, 220);
If your wb was 320x240 and the border was of width 10, then the above Crop call will do the trick - you will take the inner rectangle starting from point (10,10) and ending at (310, 230)
Now to your second issue - not knowing the width of the border. It would help if you know that
Border is of the same thickness on every side of the picture
Border is always in one color only
Assuming that's true, you could think of a simple algorithm (that may not be correct every time, but you can test it and adjust) which would take a few random points, for example
(0,randNumber < wb.PixelHeight), (randNumber < wb.PixelWidth, 0), (wb.PixelWidth, randNumber < wb.PixelHeight), (randNumber < wb.PixelWidth, wb.PixelHeight)
and then move towards the inner part of the picture as long as the neighbour pixel is the same color as the starting pixel. The more points you take randomly, the better chances you have of getting it right. The obvious problem with this is that it may happen that something on the picture is the same color as the border (exactly the same) which will make it seem like the border is wider than it really is. That's why you should take more points.
If you showed some code, I'd be happy to expand the answer.
I have an image frame:
1 http://i48.tinypic.com/wugmc2.png
The image resolution is: 533x300
Using GDI+ I Re-size the image to 300x533:
Now as you can see it distorted the width/height of the border and shrunken Santa Claus...
Is there a way using GDI+ c# to prevent this distortion of the image frame?
Scaling the image will always result into a skewed santa. If that is not what you are looking for, try creating separate images of your santa and the border.
If the border will stay that simple as a red line, I am almost sure that there is a simple control for just drawing red borders in GDI. If you are going to create some christmas border with branches and trees, you need a bit more smaller images to separate this problem.
Create a separate santa to use as an overlay
Create separate images for the corners
Create separate tillable images for vertical and horizontal borders
Then place the images by yourself and tile the images in the centers like so:
I have never worked with GDI, but this is a general solution for scaling borders.
I have had the problem described in the question Tiling rectangles seamlessly in WPF, but am not really happy with the answers given there.
I am painting a bar chart by painting lots of rectangles right next to each other. Depending on the scale of the canvas containing them, there are small gaps visible between some of them as a result from sub-pixel rendering.
I learned from the above question how to make my rectangles fit with the screen pixels, removing that effect.
Unfortunately, my chart may display way more bars than there are pixels. Apart from the tiny gaps (which manifest as a periodic change in color saturation), this works well. If I snap each bar with the screen pixels, most of the bars vanish, though, so I am looking for another solution.
Thanks in advance!
Cause of the problem
Subpixel shapes use alpha blending within the pixel. Unfortunately there is no alpha blending algorithm that results in the rectangles blending seamlessly when abutted.
For example, if:
The background color is white
The foreground color is black, and
You have two rectangles, each covering half of a single pixel
Each rectangle will be painted as black with 50% opacity. The first converts the white pixel to gray. The second converts it to a darker gray, but not black. If these rectangles continue black in adjacent pixels you see a dark gray pixel among the black.
Two types of solutions
There are two general ways to solve this problem:
Use a single Geometry to define all your rectangles, or
Force the initial rendering to be at a high enough resolution your user won't see the problem.
How to use a single Geometry
If you just have a set of Rectangles, you can create a simple control that paints over the whole set of rectangles with a single PathGeometry containing the combined shape. To illustrate the idea, if you had two rectangles beside each other of different heights, like this:
<Rectangle Canvas.Left="0" Canvas.Top="0" Width="1.5" Height="2" Fill="Red" />
<Rectangle Canvas.Left="1.5" Canvas.Top="0" Width="1.5" Height="4" Fill="Red" />
You could render it with a single PathGeometry like this:
<Path Data="M0,0 L0,2 L1.5,2 L1.5,4 L3,4 L3,0 Z" Fill="Red" />
A practical way to implement this is to:
Paint your rectangles with a Transparent brush so they will be clickable but not visable
Add a Path control underneath the rectangles in Z order
Data binding the Data property of your Path control to your data source with a converter that constructs the geometry.
If you are using the layout system to position your rectangles, you may instead want to use an AdornerLayer by creating an Adorner for each rectangles, then when rendering the adorners compute the combined path for the first one and make the rest invisible.
The above assumes it is easy to generate the PathGeometry from the source data. For more complex scenarios, the Path control can be subclassed to search the visual tree of its parent for specified shapes and use general geometricl algorithms to compute a PathGeometry that represents the union of them with no extra edges.
If your rectangles will have multiple colors, you can use multiple Path controls one per color, or you can construct a Drawing object and show that.
Here is the structure of the code to construct a PathGeometry:
var geo = new PathGeometry();
var figure = new PathFigure();
var segment = new PolyLineSegment();
segment.Points.Add(...);
segment.Points.Add(...);
segment.Points.Add(...);
segment.Points.Add(...);
segment.Points.Add(...);
figure.Segments.Add(segment);
geo.Figures.Add(figure);
How to force the initial rendering to be at high resolution
To force rendering at higher resolution:
Internally construct your chart several times larger than you want to display it, for example by wrapping it in a ViewBox.
Use a VisualBrush or RenderTargetBitmap to force your chart to be rendered separately
Add a Rectangle painted with that VisualBrush to your UI
Note that normally WPF is clever about rendering at the actual resolution required when you use a ViewBrush, but it can be tricked by having the actual chart actually display on the screen at the larger size, but then be clipped by a parent control so you don't actually see the too-big version.
This problem doesn't exist with RenderTargetBitmap, of course, since you specify the resolution you want, but it can be tricky knowing when to re-render the bitmap. If you only re-render on data changes you can use an event, but if you want any visual change to trigger a re-render it is more difficult.
I have polygons of various shapes and sizes. They have a solid fill and currently a solid border.
I would like to give the polygons a gradient on their edge to soften them.
So far I've tried using a Pen with a LinearGradientBrush and whilst the effect it produces is very interesting it's most definitely not what I want ;)
I've looked through the System.Drawing.Drawing2D namespace but there didn't seem to be any other classes that would be applicable for this purpose.
I've had a search around and the articles that I can find are mostly about creating borders for rectangles, which are mush easier, or are irrelevant.
So to summarize, does anyone have a way of drawing a gradient border in on a polygon using GDI+?
Perhaps a screen shot of what your previous attempt produced and a mock up of what you would like would help?
Though I suspect the issue you're running into is that the direction and offset of the gradient is consistent throughout the entire shape and does not change with the orientation of the lines of the polygon.
Have you taken a look instead at the PathGradientBrush? (Examples) If you can't achieve the effect using it with a Pen for the stroke of the shape, perhaps you could do it with two "fills" with the first (the border) being slightly larger than the second (the interior).
I think I have done exactly what you're asking for, but in my case I have used it for creating soft shadows on text.
I do the following:
Draw the text (in your case:
polygon) to a Bitmap
Apply a
softening filter on the alpha
channel only
Iterate step 2 as
many times needed to get the desired
gradient width
Finally draw the
result onto the resulting
bitmap/screen