Erase loaded image part by part in Windows Phone 7 - c#

I want to erase image loaded on canvas on mouse move and display the background image in wp7.
in C# MakeTransparent method is available.
But in windows phone no such method is available.
what to do ?

Canvas.Opacity = 0; //This will make the control transparent
Also you can use .Opacity function almost every visual user control (Image, Grid, Lists etc.)

Cleverly, you can use canvas_MouseMove event for an eraser effect.
Just subscribe to canvas mousemove event like in see the example below
//Canvas MouseMove Event
private void Canvas_MouseMove_1(object sender, System.Windows.Input.MouseEventArgs e)
{
currentPoint = e.GetPosition(this.canvas);
//Initialize line according to currentpoint position.
Line line = new Line() { X1 = currentPoint.X, Y1 = currentPoint.Y, X2 = oldPoint.X, Y2 = oldPoint.Y };
line.StrokeDashCap = PenLineCap.Round;
line.StrokeEndLineCap = PenLineCap.Round;
line.StrokeLineJoin = PenLineJoin.Round;
line.StrokeThickness = 10;
line.Stroke = new SolidColorBrush(Colors.White) ;
////////////////////////////////
//Set color & thickness of line.
//Line add in canvas children to draw image & assign oldpoint.
this.canvas.Children.Add(line);
oldPoint = currentPoint;
}
Not too sure with it but still, I hope it helps.

Related

C# WindowForm How can I make line cursor in PictureBox?

You know, we can easily to make line cursor for Chart (ex: Fig). But with PictureBox, how can I do it? Is there anyone has the solution?
You can intercept the MouseMove and the Paint events. Just draw the cross on the paint.
The advantage of using the Paint method, is that the original image is not changed, so no need to restore the overwritten pixels by the crosshair.
Here's an example:
I dropped a picturebox on a winform and linked some events.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MouseCrosshair
{
public partial class Form1 : Form
{
// to store the latest mouse position
private Point? _mousePos;
// the pen to draw the crosshair.
private Pen _pen = new Pen(Brushes.Red);
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
// when the mouse enters the picturebox, we just hide it.
Cursor.Hide();
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
var pictureBox = (PictureBox)sender;
// on a mouse move, save the current location (to be used when drawing the crosshair)
_mousePos = e.Location;
// force an update to the picturebox.
pictureBox.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
// if the mousepos is assigned (meaning we have a mouse pos, draw the crosshair)
if (_mousePos.HasValue)
{
var pictureBox = (PictureBox)sender;
// draw a vertical line
e.Graphics.DrawLine(_pen, new Point(_mousePos.Value.X, 0), new Point(_mousePos.Value.X, pictureBox.Height));
// draw a horizontal line
e.Graphics.DrawLine(_pen, new Point(0, _mousePos.Value.Y), new Point(pictureBox.Width, _mousePos.Value.Y));
}
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
// when the mouse is outside the picturebox, clear the mousepos
_mousePos = null;
// repaint the picturebox
pictureBox1.Invalidate();
// show the mouse cursor again.
Cursor.Show();
}
}
}
Because the events are using the sender, you can link multiple pictureboxes to these events.
It's also possible to inherit from the PictureBox, and write a new CrosshairPictureBox control, which has a crosshair by default.
If you want to draw charts in a PictureBox, use a Bitmap and draw on that using the Graphics.FromImage(bitmap) and put it in the PictureBox.Image. Don't forget to dispose the Graphics object.
You can achieve this by storing the position of the last point received, and then draw a line using the Graphics.DrawLine method between the old position and the new one.
Please also note, that when the mouse is moving, the Control.MouseMove event for every single pixel traveled by the mouse pointer isn't received for every single move. You do receive the Control.MouseMove events at a fairly consistent time interval. That means that the faster the mouse moves, the further apart the points you'll be actually receiving.
Check out this walkthrough for some examples - https://www.c-sharpcorner.com/UploadFile/mahesh/drawing-lines-in-gdi/
If I understand the question correctly, you are interested to draw x-axis and y-axis for a chart, but not using a chat control.
In this case, what you need to do is: Handle the Paint event of the PictureBox and draw the line from top middle to bottom middle and from left middle to right middle.
Here is the code which I write to produce above chart, y = Sin(x)
:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var axisWidth = 3;
var axisColor = Color.Red;
var chartLineWidth = 2;
var chartLineColor = Color.Blue;
var scale = 90;
var gridSize = 45;
var gridLineWidth = 1;
var gridLineColor = Color.LightGray;
var g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
var w = pictureBox1.ClientRectangle.Width / 2;
var h = pictureBox1.ClientRectangle.Height / 2;
g.TranslateTransform(w, h);
g.ScaleTransform(1, -1);
//Draw grid
for (int i = -w / gridSize; i <= w / gridSize; i++)
using (var axisPen = new Pen(gridLineColor, gridLineWidth))
g.DrawLine(axisPen, i * gridSize, -h, i * gridSize, h);
for (int i = -h / gridSize; i <= h / gridSize; i++)
using (var axisPen = new Pen(gridLineColor, gridLineWidth))
g.DrawLine(axisPen, -w, i * gridSize, w, i * gridSize);
//Draw axis
using (var axisPen = new Pen(axisColor, axisWidth))
{
g.DrawLine(axisPen, -w, 0, w, 0); //X-Asxis
g.DrawLine(axisPen, 0, -h, 0, h); //Y-Asxis
}
//Draw y = Sin(x)
var points = new List<PointF>();
for (var x = -w; x < w; x++)
{
var y = System.Math.Sin(x * Math.PI / 180);
points.Add(new PointF(x, scale * (float)y));
}
using (var chartLinePen = new Pen(chartLineColor, chartLineWidth))
{
g.DrawCurve(chartLinePen, points.ToArray());
}
g.ResetTransform();
}
You also need the following piece of code to handle resizing of the picture box:
private void MyForm_Load(object sender, EventArgs e)
{
this.pictureBox1.GetType().GetProperty("ResizeRedraw",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance).SetValue(
this.pictureBox1, true);
}
You can also add a crosshair and rubber-band rectangle to the control, like the following image:

Stripline label

Currently, I have been doing a project on graphs on windows form. Now I have something to ask.
Is there by any chance a way to move the Stripeline label out of my chart and not have it in the chart to something like this What I expect it to be and also make my stripeline tinner because it is too thick
till date what i do
What I expect it to be
This is my stripline code in case you need it
StripLine stripLine1 = new StripLine();
stripLine1.StripWidth = 0.01;
stripLine1.BorderColor = System.Drawing.Color.Blue;
stripLine1.BorderWidth = 0;
stripLine1.BorderDashStyle = ChartDashStyle.Solid;
stripLine1.IntervalOffset = Convert.ToDouble(textBox7.Text);
stripLine1.BackColor = System.Drawing.Color.Blue;
stripLine1.Text = "x̅";
chart1.ChartAreas[0].AxisY.StripLines.Add(stripLine1);
No, StripLines are drawn inside their ChartArea only.
There are at least two options:
You can display their Text outside of it by coding a PaintXXX event, maybe like this:
private void chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
ChartArea ca = chart1.ChartAreas[0];
Axis ax = ca.AxisX;
Axis ay = ca.AxisY;
Graphics g = e.ChartGraphics.Graphics;
foreach (StripLine sl in ay.StripLines)
{
double v = (sl.Interval != double.NaN ? sl.Interval : 0) + sl.IntervalOffset;
TextRenderer.DrawText(g, sl.Text, sl.Font, new Point(
(int)ax.ValueToPixelPosition(ax.Maximum),
(int)ay.ValueToPixelPosition(v)),Color.Black);
}
}
Fine-tuning the position, maybe by honoring the TextAlignment properties is up to you..
Note that this will now display the text twice; a simple solution it to make the original label transparent:
YourStripLine.ForeColor = Color.Transparent;
Also note that drawn graphics will not get exported if you serialize the chart.
An alternative would be to set the secondary y-axis and add the labels as CustomLabels. On second thought, I think this is preferrable, at least if you don't need the secondary y-axis.
Here I do it for one stripline:
Axis ay2 = chart1.ChartAreas[0].AxisY2;
ay2.Enabled = AxisEnabled.True;
ay2.LineColor = Color.Transparent;
CustomLabel cl = new CustomLabel();
cl.Text = stripLine.Text;
double v = (stripLine.Interval != double.NaN ? stripLine.Interval : 0)
+ stripLine.IntervalOffset;
cl.FromPosition = v - 0.001;
cl.ToPosition = v + 0.001;
ay2.CustomLabels.Add(cl);
You here also will want to make the original text transparent.

Draw a connector between shapes in wpf

I am creating some shapes from code behind dynamically and adding them to a Grid and further add the Grid to Canvas.
So when I double click on a shape I should be able to add some text which works fine. Now lets say I have two shapes on the Canvas and when I try to draw a line between these shapes for some reason the first shape gets pulled away to the bottom and the line starts from the middle of first shape.
I want the shape not to change the position and the line should start from the bottom of first shape. Please see the image for my problem.
Please help with your thoughts. Here is my code. Also I tried numerous posts eg: Getting the top left coordinates of a WPF UIElement.
But none of them seem to help.
private void CvsSurface_OnDrop(object sender, DragEventArgs e) //In this event I am creating a shape dynamically and adding to a grid which is then added to a canvas.
{
Shape result = null;
Object droppedData = e.Data; //This part is not important
/*Translate Drop Point in reference to Stack Panel*/
Point dropPoint = e.GetPosition(this.cvsSurface);
//Console.WriteLine(dropPoint);
//Label lbl = new Label();
//lbl.Content = draggedItem.Content;
UIElement element = draggedItem.Content as UIElement;
Shape s = element as Shape;
if (s is Ellipse)
{
Ellipse ellipse = new Ellipse()
{
Height = s.Height,
Width = s.Width,
Fill = s.Fill
};
result = ellipse;
}
else if (s is Rectangle)
{
Rectangle rectangle = new Rectangle()
{
Height = s.Height,
Width = s.Width,
Fill = s.Fill
};
result = rectangle;
}
Grid sp = new Grid();
sp.Children.Add(result);
sp.MouseLeftButtonDown += Sp_MouseLeftButtonDown;
sp.MouseLeftButtonUp += Sp_MouseLeftButtonUp;
//sp.PreviewMouseLeftButtonUp += Sp_PreviewMouseLeftButtonUp;
//sp.MouseLeftButtonUp += Sp_MouseLeftButtonUp;
cvsSurface.Children.Add(sp);
Canvas.SetLeft(sp, dropPoint.X);
Canvas.SetTop(sp, dropPoint.Y);
}
private void Sp_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) // The purpose of this event lets say when some one clicks on a shape and drags the mouse to the other shape and when mouse up I want to draw a line between the shapes.
{
bool mouserelease = System.Windows.Input.Mouse.LeftButton == MouseButtonState.Pressed;
if (!mouserelease)
{
x2 = e.GetPosition(stackpanel).X;
y2 = e.GetPosition(stackpanel).Y;
Line l = new Line();
l.X1 = x1;
l.Y1 = y1;
l.X2 = x2;
l.Y2 = y2;
l.Margin = new Thickness(0, 19, 0, 0);
l.Stroke = new SolidColorBrush(Colors.Black);
l.StrokeThickness = 2;
stackpanel.Children.Add(l);
}
}
private void Sp_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) //This method lets say if user clicks twice then he wants to add some text or if he single clicks then I am assuming he is trying to a drag and draw a line
{
stackpanel = sender as Grid; //Sorry, the stackpanel is a global variable name of type Grid. Its actually Grid stackpanel;
if (e.ClickCount == 2)
{
dialog = new UserDialog()
{
DataContext = this,
Height = 180,
Width = 400,
MaxHeight = 180,
MaxWidth = 400
};
dialog.ShowDialog();
}
else
{
x1 = e.GetPosition(stackpanel).X + 18;
y1 = e.GetPosition(stackpanel).Y + 18;
//x1 = GetPosition(stackpanel, cvsSurface).X;
//y1 = GetPosition(stackpanel, cvsSurface).Y;
}
}

Drag from treeview to picture box and connect elements

I'm stuck with this problem. I have in one frame pictureBox and treeview. I want to drag and drop from treeview to picture box and in that picture box I paint another picture (first picture box is map in treeview i have 'Sings')
private void pictureBox1_DragDrop(object sender, DragEventArgs e)
{
Type testTip = new TreeNode().GetType();
TreeNode dragedNode;
_mouseDownSelectionWindow= Rectangle.Empty;
if (e.Data.GetDataPresent(testTip))
{
dragedNode = (TreeNode)e.Data.GetData(testTip);
PictureBox picOneFaceUpA = new PictureBox();
picOneFaceUpA.Parent = MapView;
picOneFaceUpA.Tag = dragedNode;
TreeNode tr = (TreeNode)picOneFaceUpA.Tag;
Sing vr = (Sing)tr.Tag;
picOneFaceUpA.Name = vr.idSing;
vr.onMap = true;
int xCord = e.X;
int yCord = e.Y;
picOneFaceUpA.Location = MapView.PointToClient(new Point (xCord - 20, yCord - 20));
picOneFaceUpA.BackgroundImage = vr.image;
vr.location = picOneFaceUpA.Location;
dictionary.Add(picOneFaceUpA.Location, vr);
picOneFaceUpA.Size = new Size(40, 40);
picOneFaceUpA.BackgroundImageLayout = ImageLayout.Stretch;
picOneFaceUpA.BringToFront();
picOneFaceUpA.Focus();
}
}
And that works, but how I can connect so when I click on Sing on map it gets some kind of focus(frame or something) and it selects treenode in treview that I used to make that picture box.
You already have created a connection when you have stored the dragged node in the PictureBox's Tag.
To make it work you need to code a few events for the created PictureBoxes.
Here is the minimum:
When clicked I set a Border, select the Treenode you have already stored in the Tag and explicitly set the focus on the PictureBox. (PBs don't usually get focus when clicked, so we need to do it in code, so we can catch the LostFocus event..)
picOneFaceUpA.Click += (ss,ee) => {
picOneFaceUpA.BorderStyle = BorderStyle.FixedSingle;
treeView1.SelectedNode = dragedNode;
picOneFaceUpA.Focus();
};
And in the LostFocus I simply remove the Border:
picOneFaceUpA.LostFocus += (ss, ee) =>
{
picOneFaceUpA.BorderStyle = BorderStyle.None;
};
Don't forget to set the treeview HideSelection = false; so you can see the selection while the focus still is on the PB!
Now, depending on the images you show, the border may be a bit weak. For a stronger effect you would have to code the Paint event to draw something more flashy on the top of the control..:
picOneFaceUpA.Paint += (ss, ee) =>
{
if (picOneFaceUpA.BorderStyle == BorderStyle.FixedSingle)
ee.Graphics.DrawRectangle(Pens.Orange, 0, 0,
picOneFaceUpA.ClientSize.Width - 1,
picOneFaceUpA.ClientSize.Height - 1);
};
In your code you use a picOneFaceUpA.Focus();call. This seems to clash with setting the LostFocus event, so will have to remove it!

Selecting part of image on windows form

I'm making instrument to select part of image. I have PictrureBox, and simple way to make it :
void StartPanel(object sender, MouseEventArgs args)
{
xStart = args.X;
yStart = args.Y;
panelStarted = true;
pan.Location = new Point(xStart, yStart);
}
void FinishPanel(object sender, MouseEventArgs args)
{
xFinish = args.X;
yFinish = args.Y;
panelStarted = false;
}
void UpdatePanel(object sender, MouseEventArgs args)
{
if (panelStarted)
{
int x = args.X;
int y = args.Y;
int newxstart = xStart;
int newystart = yStart;
int neww = 0;
int newh = 0;
if (x >= xStart)
neww = x - xStart;
else
{
neww = xStart - x;
newxstart = x;
}
if (y >= yStart)
newh = y - yStart;
else
{
newh = yStart - y;
newystart = y;
}
pan.Size = new Size(neww, newh);
pan.Location = new Point(newxstart, newystart);
}
}
When I move mouse right and down, it is absolutely ok. But when I move it left or up I can see blinks at my area. So I have understood, that it is because when I move mouse left or up, my panel is redrawed, because Panel.Location is changed, and when I move mouse right and down, location is not changed, only size is changed, so it is not redrawed, just some pixels are added to panel. What is standart solution for this?
It's not easy trying to see what you are trying to do, but I guess you are using a panel as a draggable control to drag over the picturebox surface capturing the portion of image below (like a lens) - yes?
If so, then this is not the best way to do it. It is better to just draw a rectangle on the picturebox surface and "drag" that around - this is simple with just using the mouse events to sets the top left corner and use the onpaint to draw the unfilled rectangle over the image. Capturing the image when you are ready is simple too using whatever event you wish, then copy the image giving the same positions to the new bitmap.
Putting one control over another often causes flickers - even with double buffering. It also takes far more code.
Since you are describing a drawing issue when resizing the panel, probably the easiest fix is to replace the panel you are using with one that is double buffered and will invalidate on resize a event:
public class BufferedPanel : Panel {
public BufferedPanel() {
this.DoubleBuffered = true;
this.ResizeRedraw = true;
}
}

Categories

Resources