C# keep drawed images with Graphics.DrawImage - c#

I am trying to draw images on a panel with a click event.I managed to do that,but I want to keep the generated images.After each click,the previously generated image disapears.How can I keep all the drawed images?
This is my code untill now:
private void drawdot(object sender,PaintEventArgs e)
{
Image dot = Image.FromFile("dot.png");
var points = this.PointToClient(new Point(Cursor.Position.X-20, Cursor.Position.Y-30));
e.Graphics.DrawImage(dot, points);
}
private void grid2_Paint(object sender, EventArgs e)
{
if(started==true)
{
var points = this.PointToClient(new Point(Cursor.Position.X, Cursor.Position.Y));
coord2.Add(points.ToString());
clickuri2++;
test2_puncte.Text = "Testul 2 | Puncte: " + clickuri2;
//draw
grid2.Paint -= drawdot;
grid2.Paint += drawdot;
grid2.Invalidate();
}
}

Since you are invalidating the whole grid is redrawn, you should invalidate only the parts that you just redrawn. This is create a region and pass it to grid2.Invalidate as a parameter. Roughly it would look like something like this:
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
path.AddLines(points);
lvResults.Invalidate(new Region(path));
UPDATE:
You could also keep a list of all the clicked points and call the imagedraw method once for each new points, just add a new item to the list when clicking on the object and you should be good to go. I don't know if you could get into some race condition scenario where someone clicks while it's trying to draw on all points but it would be easily handled if that was the case

Related

Click on image and show message box depending on the clicked place

I have this idea of this world map image and when I click a country on it, it shows information of that country in a MessageBox for example does anyone have an idea how to do that?
I have a rectangle and a button and when i click the button it shows the image in the rectangle but i thought if i use polygons to shape the country's but I'm a little stuck.
I would like to have every country apart and maybe that the borders light up when clicked
You can do this pretty easily using WPF:
Find a nice World Map in SVG format. I used this one from Wikipedia:
Download and install Inkscape then open the SVG you've just downloaded. Inkscape has a nice feature that makes it possible to save an SVG as a XAML.
Import the ViewBox from the XAML file into your WPF window/etc:
For each Path in the XAML you can add a MouseEnter/MouseLeave event handler or you can use the same one for all the Paths
Sample code:
private void CountryMouseEnter(object sender, MouseEventArgs e)
{
var path = sender as Path;
if (path != null)
{
path.Fill = new SolidColorBrush(Colors.Aqua);
}
}
private void Country_MouseLeave(object sender, MouseEventArgs e)
{
var path = sender as Path;
if (path != null)
{
path.Fill = new SolidColorBrush(Colors.Black);
}
}
Now it's just a matter of changing colors/showing MessageBoxes etc.
GitHub
My first thought: You could bind a command to the view that will be triggered by a click on a position. If you're using WPF you can bind command parameters to the command to get the x and y of your click...
After that you have to handle the content of your messagebox and the highlighting of the borders depending on the position xy.
have fun :D
Option 1
There is a project on Code Project that someone created that defines hotspots that are clickable with events. You could use that to overlay your map and define the hotspots where you need them.
C# Windows Forms ImageMap Control
Option 2
You could bind to the MouseUp Event on the Image and use the following to see if it is in a Rectangle
private void mapMouseUp(object sender, MouseEventArgs e) {
Rectangle rect1 = new Rectangle(0, 0, 100, 100);
Rectangle rect2 = new Rectangle(0, 100, 100, 100);
if (rect1.Contains(e.Location)) {
// Do your stuff
} else if (rect2.Contains(e.Location)) {
// Do your stuff
}
}

Problems with creating combined image view / camera view window using EmguCV & Windows Forms

Basically, what I'm trying to do is to create a window with list of images and large image view box. If user points at one of the images in the list, imagebox should display it, otherwise it should display live feed from a webcam.
I'm trying to achieve that by using ImageGrabbed event of EmguCV.Capture, and a field that stores index of the currently viewed image. Camera feed works alright, however, when I move the mouse over listbox, image view merely stops updating. It stays stuck at the last frame it saw, and doesn't display the image I'm pointing at. I've checked that the list has images in it, that index is correct, and that image coming from the camera is different from ones saved in the list. Also, same behavior happens when I use vanila PictureBox.
See the code (stripped of extra parts) below.
Initialization:
int ViewedFrame = -1;
var Frames = new List<Image<Rgb, byte>>();
// This list will have some images added to it along the way.
// They will be displayed in a custom drawn ListBox bound to the list.
Camera = new Emgu.CV.Capture(cameraid);
Camera.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_WIDTH, width);
Camera.SetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_HEIGHT, height);
Camera.ImageGrabbed += UpdateCamera;
Camera.Start();
Frame capture:
private void UpdateCamera(object sender, System.EventArgs ev)
{
if (ViewedFrame == -1)
Preview.Image = Camera.RetrieveBgrFrame();
else
// !!! this line has no apparent effect, image in the ImageBox is still the same
Preview.Image = Frames[ViewedFrame];
}
Mouse handling:
private void FrameList_MouseMove(object sender, MouseEventArgs e)
{
int index = FrameList.IndexFromPoint(e.Location);
if (index == ListBox.NoMatches)
ViewedFrame = -1;
else if (index != ViewedFrame)
{
ViewedFrame = index;
}
}
private void FrameList_MouseLeave(object sender, EventArgs e)
{
ViewedFrame = -1;
}
UPD: I tried adding Preview.Update() and Preview.Refresh() into the same branch as Frames[ViewedFrame], and after the conditional operator. In first case it doesn't have any effect. In second case nothing is shown at all. In case the ImageBox can't keep up updating itself, I enabled doublebuffering, but that didn't help either. Moreover, after I hover the mouse over an image in the list, the camera stream breaks too. The code above is the only one that's somewhat working.

Trying to add a image to a group box, however, it doesnt show up

Solved: Using design toolbox.
I'm using the following method to add a image
private void cobertura1vertente_Load(object sender, EventArgs e)
{
PictureBox pb1 = new PictureBox();
pb1.Image = Image.FromFile("C:/cobertura1vertente.png");
pb1.Location = new Point(3, 3);
pb1.Size = new Size(250, 250);
//doubt right below
groupBox81.Controls.Add(pb1);
}
I usually would add a image to a entire form, but now i want to add it to a specific groupbox, who lies inside a tab.
If the code is correct, my guess is that the location that i've set is relative to the whole form, and not to the groupBox, why would that happen?

Zoom effect on buttons inside a FlowLayoutPanel

I have some buttons inside a FLP and I want when the mouse is over a button, to increase the size of the button a little, like a zoom effect. The problem is that when the button size increases, all buttons next to it slide to the right and down.. Probably the issue is caused by the space added by the FLP between items, but how can I prevent this, so when the size is increasing to go over that space not to add more..?
My ZOOM class:
class zoom
{
public zoom(Control cst)
{
cst.MouseEnter += delegate(object sender, EventArgs e)
{
cst.Size = new Size(70, 75);
cst.Font = new Font(cst.Font.FontFamily, 9);
};
cst.MouseLeave += delegate(object sender, EventArgs e)
{
cst.Size = new Size(68, 73);
cst.Font = new Font(cst.Font.FontFamily, 8);
};
}
}
It's the way the FlowLayoutPanel works. It moves the rest of the controls to fit them all following the flow.
If you have some space between the buttons it's because of the Margin property, you could reduce the margin of the button as you zoom it.
This won't work if you want the button to show over the other ones. In that case, probably the only way to go is to use a simple Panel instead of the FlowLayoutPanel and do a BringToFront() with the Zoom.

how to make the cursor lines to follow the mouse in charts using C#

The picture below shows a chart in my project. As you can see there are two dotted crossing lines. I’m asked to make it to follow the mouse, but now only if I click on the chart it moves. I tried to use CursorPositionChanging but it didn’t work.
CursorEventHandler also is not shown in the command below:
this.chart1.CursorPositionChanging += new System.Windows.Forms.DataVisualization.Charting.Chart.CursorEventHandler(this.chart1_CursorPositionChanging);
do we need to add extra lib for that?
So I have two problems now:
1. Make the lines to follow the mouse
2. Missing CursorEventHandler
the project is window form application with C#
private void chData_MouseMove(object sender, MouseEventArgs e)
{
Point mousePoint = new Point(e.X, e.Y);
Chart.ChartAreas[0].CursorX.SetCursorPixelPosition(mousePoint, true);
Chart.ChartAreas[0].CursorY.SetCursorPixelPosition(mousePoint, true);
// ...
}
The chart supports a 'MouseMove' event which is fired each time the mouse is moved inside the chart. The MouseEventArgs contain the position of the mouse so u can move the dotted lines based on that data each time the event fires.
A more generalized form to synchronized all areas without any additional logic is as follows:
var mousePoint = new Point(e.X, e.Y);
var chart = (Chart)sender;
//foreach child
foreach (var ca in chart.ChartAreas)
{
ca.CursorX.SetCursorPixelPosition(mousePoint, true);
ca.CursorY.SetCursorPixelPosition(mousePoint, true);
}

Categories

Resources