How to correctly save UIControl with opacity to WriteableBitmap? - c#

I make group of rectangles with different opacity value and add these rectangles to Grid in WindowsPhone:
var grid=new Grid();
grid.Width = grid.Height = 200;
var rectanglesCount=55;
var rectangleSizeStep = grid.Height / rectanglesCount;
var opacityStep = 1.0 / rectanglesCount
var rectangleSize = grid.Height;
var opacity = 0.0;
for (int i = 0; i <= rectanglesCount; i++)
{
Rectangle rect = new Rectangle();
rect.Height = rect.Width = rectangleSize;
rect.VerticalAlignment = VerticalAlignment.Center;
rect.HorizontalAlignment = HorizontalAlignment.Center;
rect.Fill = new SolidColorBrush(Colors.Yellow);
rect.Opacity = opacity;
opacity += opacityStep;
rectangleSize -= rectangleSizeStep;
grid.Children.Add(rect);
}
I can see in grid following picture:
After I try to save this group of rectangles to WriteableBitmap and show as Image:
var img=new Image();
var wrBit = new WriteableBitmap(grid, null);
img.Source=wrBit;
And I see picture:
What happend with opacity on top and left edges?
How to correctly save group of Rectangles?

Need to use Canvas instead Grid control for group of rectangles:
var canvas=new Canvas();
canvas.Width = canvas.Height = 200;
var rectanglesCount=55;
var rectangleSizeStep = canvas.Height / rectanglesCount;
var opacityStep = 1.0 / rectanglesCount
var rectangleSize = canvas.Height;
var opacity = 0.0;
var rectMargin = 0.0;
for (int i = 0; i <= rectanglesCount; i++)
{
Rectangle rect = new Rectangle();
rect.Height = rect.Width = rectangleSize;
rect.Margin=new Thickness(rectMargin,rectMargin,0,0);
rectMargin += rectangleSizeStep/2;
rect.Fill = new SolidColorBrush(Colors.Yellow);
rect.Opacity = opacity;
opacity += opacityStep;
rectangleSize -= rectangleSizeStep;
canvas.Children.Add(rect);
}
and save Canvas as WriteableBitmap:
var img=new Image();
var wrBit = new WriteableBitmap(canvas, null);
img.Source=wrBit;
Problem was solved!

Related

Viewing applications in WPF with errors

I have an application that breaks the image when the screen size changes
Below is the screen
Where can the mistake be? What can cause this situation? I do not even know where to look because it is not a permanent error only once and once is gone
This is how I load items with a line and number per view:
<ItemsControl ItemsSource="{Binding ConnectorsGridsHorizontal, Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Function drawing 1 element:
public Grid DrawConnector1(Thickness margin, int nr, bool rotate, bool rightSide)
{
Grid grid = new Grid();
grid.Margin = margin;
grid.HorizontalAlignment = HorizontalAlignment.Left;
grid.Width = S10;
grid.Height = 128;
grid.VerticalAlignment = System.Windows.VerticalAlignment.Center;
Line line = new Line();
line.X1 = S10HALF;
line.X2 = S10HALF;
line.Y1 = 0;
line.Y2 = 128;
line.StrokeDashArray = new System.Windows.Media.DoubleCollection() { 4, 2, 1, 2 };
line.Stroke = System.Windows.Media.Brushes.Green;
line.StrokeThickness = 4;
grid.Children.Add(line);
Grid inGrid = new Grid();
inGrid.Width = S10;
inGrid.Height = HF;
inGrid.Background = System.Windows.Media.Brushes.Black;
grid.Children.Add(inGrid);
Border br = new Border();
br.BorderThickness = new Thickness(0);
br.CornerRadius = new CornerRadius(10);
br.Background = System.Windows.Media.Brushes.White;
br.Margin = new Thickness(-10, -10, -10, -10);
br.Width = 20;
br.Height = 20;
br.VerticalAlignment = rightSide ? VerticalAlignment.Top : VerticalAlignment.Bottom;
br.RenderSize = new System.Windows.Size(br.ActualWidth + 1, br.ActualHeight + 1);
if (SelectedConnector + 1 == nr) br.Background = System.Windows.Media.Brushes.Green;
else br.Background = System.Windows.Media.Brushes.White;
if (DisableGreenMark) br.Background = System.Windows.Media.Brushes.White;
TextBlock txtBlock = new TextBlock();
txtBlock.FontSize = 16;
txtBlock.Text = nr.ToString();
txtBlock.Foreground = new SolidColorBrush(Colors.Black);
txtBlock.VerticalAlignment = VerticalAlignment.Center;
txtBlock.HorizontalAlignment = HorizontalAlignment.Center;
br.Child = txtBlock;
grid.Children.Add(br);
Binding b = new Binding("S60_20");
b.Mode = BindingMode.Default;
grid.SetBinding(Canvas.TopProperty, b);
return grid;
}
GIF:
I'm also using SnapsToDevicePixels="true"
To start with, try doing this:
br.HorizontalAlignment = HorizontalAlignment.Stretch;
br.Margin = new Thickness(0, 0, 0, 0);
Do not use margin with a negative value
Stretch will provide you with an element extension
Side cut is probably caused by too narrow a strip for the element:
You have:
grid.Width = S10;
line.X1 = S10HALF;
line.X2 = S10HALF;
This indicates that you have the width set to probably 10
and Here you have set to 20
br.Width = 20;
br.Height = 20;
I also suggest changing here:
grid.Width = S10 * 2;
line.X1 = S10HALF * 2;
line.X2 = S10HALF * 2;

Printing Image from Silverlight

I'm trying to print a Image in Landscape mode in Silverlight.
I found a great example here. Where most of the code comes from. The code worked perfectly as expected. When I changed the Line to an Image it failed.
Code
Canvas OuterCanvas = new Canvas();
/* a container for everything that will print */
Border OuterBorder = new Border()
{
BorderThickness = new Thickness(3),
BorderBrush = new SolidColorBrush(Colors.Red),
Margin = new Thickness(10)
};
double Width = e.PrintableArea.Width - OuterBorder.Margin.Left - OuterBorder.Margin.Right;
double Height = e.PrintableArea.Height - OuterBorder.Margin.Top - OuterBorder.Margin.Bottom;
/* NOTE: We're trying to force landscape, so swop the width and height */
OuterBorder.Width = Height;
OuterBorder.Height = Width;
/* on portrait, this line goes down (leave the printer settings, we're trying to force landscape) */
Line Line = new Line()
{
X1 = OuterBorder.Width / 2,
Y1 = 0,
X2 = OuterBorder.Width / 2,
Y2 = OuterBorder.Height,
Stroke = new SolidColorBrush(Colors.Blue),
StrokeThickness = 3
};
//
// Here is where I changed the Line to an Image
//
OuterBorder.Child = imageElementInXaml; //Line;
OuterCanvas.Children.Add(OuterBorder);
/* rotate 90 degrees, and move into place */
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new RotateTransform() { Angle = 90 });
transformGroup.Children.Add(new TranslateTransform() { X = e.PrintableArea.Width });
OuterBorder.RenderTransform = transformGroup;
e.PageVisual = OuterCanvas;
e.HasMorePages = false;
I know that a Border can only contain 1 element in which I have done so, and when I printed the image on its own without trying to make it landscape this worked too. So why wont it work when I simply replace the Line with the image Element
So since posting this I found some code (cant remember where now) that has helped me get the printing working. Its not as clean as I would have liked but it works.
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Image image = new Image();
image.Source = imgPlayer.Source;
//This is important
image.Stretch = Stretch.Uniform;
// Find the full size of the page
Size pageSize = new Size(e.PrintableArea.Width + e.PageMargins.Left + e.PageMargins.Right, e.PrintableArea.Height + e.PageMargins.Top + e.PageMargins.Bottom);
var MARGIN= 10;
// Get additional margins to bring the total to MARGIN (= 96)
Thickness additionalMargin = new Thickness
{
Left = Math.Max(0, MARGIN - e.PageMargins.Left),
Top = Math.Max(0, MARGIN - e.PageMargins.Top),
Right = Math.Max(0, MARGIN - e.PageMargins.Right),
Bottom = Math.Max(0, MARGIN - e.PageMargins.Bottom)
};
// Find the area for display purposes
Size displayArea = new Size(e.PrintableArea.Width - additionalMargin.Left - additionalMargin.Right, e.PrintableArea.Height - additionalMargin.Top - additionalMargin.Bottom);
bool pageIsLandscape = displayArea.Width > displayArea.Height;
bool imageIsLandscape = image.ActualWidth > image.ActualHeight;
double displayAspectRatio = displayArea.Width / displayArea.Height;
double imageAspectRatio = (double)image.ActualWidth / image.ActualHeight;
double scaleX = Math.Min(1, imageAspectRatio / displayAspectRatio);
double scaleY = Math.Min(1, displayAspectRatio / imageAspectRatio);
// Calculate the transform matrix
MatrixTransform transform = new MatrixTransform();
if (pageIsLandscape == imageIsLandscape)
{
// Pure scaling
transform.Matrix = new Matrix(scaleX, 0, 0, scaleY, 0, 0);
}
else
{
// Scaling with rotation
scaleX *= pageIsLandscape ? displayAspectRatio : 1 / displayAspectRatio;
scaleY *= pageIsLandscape ? displayAspectRatio : 1 / displayAspectRatio;
transform.Matrix = new Matrix(0, scaleX, -scaleY, 0, 0, 0);
}
Image image2 = new Image
{
Source = image.Source,
Stretch = Stretch.Fill,
Width = displayArea.Width,
Height = displayArea.Height,
RenderTransform = transform,
RenderTransformOrigin = new Point(0.5, 0.5),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Margin = additionalMargin,
};
Border border = new Border
{
Child = image,
};
e.PageVisual = border;
}

how to animate rectangle with AnimationPoint(windows phone)?

I want to animate retangle with using AnimationPoint.
How can i do it?
P.S.
I searhed in google, but did not find what i need.
I try this :
private void drawRect()
{
var d = new Grid();
var moveTranc = new TranslateTransform() { X = 1,Y = 1 };
var e2 = new Rectangle()
{
Stroke = new SolidColorBrush(System.Windows.Media.Color.FromArgb(255, 0, 200, 0)),
RenderTransform = moveTranc,
RadiusX = 100,
RadiusY = 100,
RenderTransformOrigin = new Point(0.5f,0.5f),
};
var pointAnimation = new PointAnimation()
{
Duration = new Duration(TimeSpan.FromSeconds(2)),
From = new Point(e2.RadiusX,e2.RadiusY),
To = new Point(450,450)
};
var storyBoard = new Storyboard();
storyBoard.RepeatBehavior = RepeatBehavior.Forever;
storyBoard.Children.Add(pointAnimation);
Storyboard.SetTarget(pointAnimation, e2);
Storyboard.SetTargetProperty(pointAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X).(TranslateTransform.Y)"));
d.Children.Add(e2);
ContentPanel.Children.Add(d);
storyBoard.Begin();
}
I found any variant of animating rectangle with using double animation
Rectangle myRectangle;
Storyboard sb;
//creating rectangle
myRectangle = new Rectangle();
myRectangle.Width = 200;
myRectangle.Height = 200;
Color myColor = Color.FromArgb(255, 255, 0, 0);
SolidColorBrush myBrush = new SolidColorBrush();
myBrush.Color = myColor;
myRectangle.Fill = myBrush;
// Create the transform
TranslateTransform moveTransform = new TranslateTransform();
moveTransform.X = 0;
moveTransform.Y = 0;
myRectangle.RenderTransform = moveTransform;
// Add the rectangle to the tree.
if (!LayoutRoot.Children.Contains(myRectangle)) LayoutRoot.Children.Add(myRectangle);
// Create a duration of 2 seconds.
Duration duration = new Duration(TimeSpan.FromSeconds(1.0));
// Create two DoubleAnimations and set their properties.
DoubleAnimation myDoubleAnimationX = new DoubleAnimation();
sb = new Storyboard();
sb.Duration = duration;
sb.Children.Add(myDoubleAnimationX);
Storyboard.SetTarget(myDoubleAnimationX, moveTransform);
Storyboard.SetTargetProperty(myDoubleAnimationX, new PropertyPath("X"));
DoubleAnimation myDoubleAnimationY = new DoubleAnimation();
sb.Children.Add(myDoubleAnimationY);
Storyboard.SetTarget(myDoubleAnimationY, moveTransform);
Storyboard.SetTargetProperty(myDoubleAnimationY, new PropertyPath("Y"));
myDoubleAnimationX.To = 0;
myDoubleAnimationX.From = 340;
myDoubleAnimationY.To = 0;
myDoubleAnimationY.From = 340;
// Make the Storyboard a resource.
if (!LayoutRoot.Resources.Contains("unique_id")) LayoutRoot.Resources.Add("unique_id", sb);
sb.Begin();

Lines Shapes and Shananagins

So, Basically I'm trying to draw a line between the center of 2 ellipses
And I think this should do it:
Path myPath = new Path();
myPath.Stroke = System.Windows.Media.Brushes.Black;
myPath.StrokeThickness = 4;
myPath.HorizontalAlignment = HorizontalAlignment.Left;
myPath.VerticalAlignment = VerticalAlignment.Center;
EllipseGeometry myEllipseGeometry = new EllipseGeometry();
myEllipseGeometry.Center = new System.Windows.Point((xQuard * 10) + 100, yQuard * 10);
myEllipseGeometry.RadiusX = 2;
myEllipseGeometry.RadiusY = 2;
myPath.Data = myEllipseGeometry;
GraphPanel.Children.Add(myPath);
//if it's not the first point...
if (prevA != 0.0)
{
Path iLine = new Path();
iLine.Stroke = Brushes.Black;
iLine.StrokeThickness = 4;
iLine.HorizontalAlignment = HorizontalAlignment.Left;
myPath.VerticalAlignment = VerticalAlignment.Center;
LineGeometry iLineGeometry = new LineGeometry();
iLineGeometry.StartPoint = myEllipseGeometry.Center;
iLineGeometry.EndPoint = new System.Windows.Point(prevA, prevB);
iLine.Data = iLineGeometry;
GraphPanel.Children.Add(iLine);
}
//Set the previous point(s)
prevA = (xQuard * 10) + 100;
prevB = yQuard * 10;
Now as you can see, I've set the Line's StartPoint = to the first ellipse start point
And Yet....
Why is the Line's start point in the picture not the center of the point on the left?
I think you mean iLine.VerticalAlignment instead of myPath.VerticalAlignment the second time, right?

Rectangle shape won't update left or top positions with canvas

It won't change the position, the position is fixed at runtime even though i change the value 50 below:
System.Windows.Shapes.Rectangle myRectangle = new System.Windows.Shapes.Rectangle();
mainGrid.Children.Add(myRectangle);
Canvas.SetLeft(myRectangle, 50);
Canvas.SetTop(myRectangle, 50);
myRectangle.Height = 100;
myRectangle.Width = 100;
myRectangle.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
here are the 2 solutions for your problem
1) with a canvas
var myRectangle = new System.Windows.Shapes.Rectangle();
var mainCanvas = new Canvas();
mainGrid.Children.Add(mainCanvas);
mainCanvas.Children.Add(myRectangle);
Canvas.SetLeft(myRectangle, 50);
Canvas.SetTop(myRectangle, 50);
myRectangle.Height = 100;
myRectangle.Width = 100;
myRectangle.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
2) only with your grid
var myRectangle = new System.Windows.Shapes.Rectangle();
mainGrid.Children.Add(myRectangle);
myRectangle.Margin = new Thickness(50, 50, 0, 0);
myRectangle.HorizontalAlignment = HorizontalAlignment.Left;
myRectangle.VerticalAlignment = VerticalAlignment.Top;
myRectangle.Height = 100;
myRectangle.Width = 100;
myRectangle.Stroke = System.Windows.Media.Brushes.LightSteelBlue;

Categories