Click interface Clarification (Entry-Level) - c#

I'm trying to create a graph editor using WinForms.
I have a picture box, whenever I click on it the program draws a vertex by creating a label about 15px in size where I store a string, the location, etc.
I can draw the edges by drawing lines from location to location, but I need other boxes to do this, I wonder if there is a way to do this purely by touch (with the mouse cursor).
I need some kind of object that if clicked will start an event that will draw an edge up to the vertex I click next. I considered adding little picture boxes instead of labels, but the labels are convenient for storing the name of the vertexes, also I think adding both a label and an other box in the same position may hide one of the objects.

You can get the x and y coordinate's of the mouse on a user controls click event.
I would store the coordinate's of the last point you clicked on outside of the mouse click event and then draw a line from the last point to the new point.
lastPoint = null;
private void userControl_MouseClick(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left)
{
Point newPoint = e.Location;
if(lastPoint != null)
{
drawLine(lastPoint, newPoint);
}
lastPoint = newPoint;
}
}
Hope this helps.

Related

How to set Selection start based on Mouse Position WinForms

I need to set Selection start of a text box based on the mouse position, i tried to load the text box on Double Click, once the text box is loaded, i need to set the selection start based on the Mouse position. (i.e) if a text box contains some values like "abcdef", if the mouse cursor is near "c" when textbox is loaded, then the selection start should be after "c".
I have also tried this
textBox.GetCharIndexFromPosition(e.Location);
but i didn't get it right,
Thanks in advance.
Regards,
Venkatesan R
Putting #Reza's code in the correct event will work just fine:
private void textBox_MouseDoubleClick(object sender, MouseEventArgs e)
{
textBox.Text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // load the text data here
// now position the caret onto the mouse position
textBox.SelectionStart = textBox.GetCharIndexFromPosition(e.Location);
// and clear a selection
textBox.SelectionLength = 0;
}
Note that you need to use the MouseDoubleClick, not the simple DoubleClick or else you miss the e.Location param!
This is the simplest and most direct way to get the mouse coordinates relative to the TextBox.
If your loading method is complex you can call it by passing in the MouseEventArgs e but simply calling it instead of the textBox.Text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; is the most natural way.
If you want to you could also use
textBox.SelectionStart = textBoxtextBox1.PointToClient(Control.MousePosition));
This will work in any event or method. PointToClient will calulate the relative position from the screen position Control.MousePosition.

Coloring area of an image on mouse click over picturebox

I would like to be able to fill any given area of an image with a given color, much like you can use paint to fill a rectangle, circle or any other shape delimited by a color.
To make this simpler I already have made the picture box source image to have the same size as the picture box itself, which should make things a bit easier.
How can I do this given that I have a picture box with an image and an already defined color and the user only has to click over the picture box to fill in any area with such color.
void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
// The color to be used
Color color = Color.Red;
// Image has same dimensions as picturebox to make things easier
Image img = pictureBox1.Image;
// Where it was clicked.
Point clickCoords = new Point(e.X, e.Y);
// Coloring that area clicked much like Paint does. How?
...
// After coloring show the result in the picture box again
pictureBox1.Image = img;
}
Thanks.
EDIT: Example of my desired behavior.
To make my goal obvious, let me add this small example.
You know MS Paint right?
You selected the pencil tool and start doing anything on the canvas, doesn't matter form or shape or even if the points your are doing with the pencil are connected or not.
Now you select the bucket tool and start clicking on the canvas. What will it do? Fill in the selected area according to the color you clicked over and how far she goes without changing with the color you have selected on the color pallet.
This is the behavior I want to emulate on my picture box mouse click event.
What you are looking for is a flood-fill algorithm. This should do the trick just fine.
The algorithm recursively searched for neighboring uncolored pixels, until it hits a wall.
You can use the code from here:
// Load the image (probably from your stream)
Image image = Image.FromFile( imagePath );
using (Graphics g = Graphics.FromImage(image))
{
Color customColor = Color.FromArgb(50, Color.Gray);
SolidBrush shadowBrush = new SolidBrush(customColor);
g.FillRectangles(shadowBrush, new RectangleF[] { rectFToFill });
}
image.Save( imageNewPath );
, but there is a one thing you missed - a rectFToFill, which you should define according your click event. There are a lot of strategies you can use, I suggest you to handle a Drag event or something like that, save the event start point and end point, after that define the rectangular you must fill:
You should examine the event points and after that create the Rectangle(F) structure using some of its constructors.
The Graphics class has a dozen methods you can use to draw some shapes or lines on your Image.

how to detect a mouse click on drawn image?

I am new to c# Windows Form Application Development.
I created a form with a panel in which the user can draw image on it. How do I check if the image is clicked?
In designer mode, right-click on the panel, go to Properties.
In the Properties window, choose EVENTS (Lightning icon).
Double click on Click, then this code will be generated:
private void panel1_Click(object sender, EventArgs e)
{
//--what to do when user clicks on panel--
MessageBox.Show("Clicked");
}
Just double-click on the form's image-panel (or whatever object you wish to detect click events on) and Visual Studio will automatically generate a OnClick() event. Needless to say, I'm talking about the forms designer, not the actual form you will see when testing your code.
Alternatively, you can set which events you want to implement through the object's properties. That way you can also implement OnKeyDown() or OnFocus() or any other kind of events.
Edit: If the image doesn't cover the entire panel, you'll have to check if the mouse position is within the image's dimension. Assuming the image is drawn at position (imgOriginX, imgOriginY) and has the size (imgWidth, imgHeight):
// Fires, when user clicks on panel
private void panel_Click(object sender, EventArgs e)
{
// Cast to MouseEventArgs
MouseEventArgs mouse = (MouseEventArgs)e;
// If mouse is within image
if (mouse.X >= imgOriginX && mouse.Y >= imgOriginY && mouse.X < imgOriginX + imgWidth && mouse.Y < imgOriginY + imgHeight)
{
// do something here
}
}

draw and remove a line with gdi+

I owned complex drawing code with GDI+ which draws something like a chart on a user control.
If the user clicks with control pressed, a vertical marker line in dash style should be shown.
Now I look for a way to extend the drawing code without touching the complex drawing code.
I created a marker class which attaches to the mouse-up event of the user control.
In the eventhandler a check against (ModifierKeys == Keys.Control) is done.
If the user holds the control key and click with the left mouse button the draw method of the marker class is called with the Graphics object of the usercontrol as a parameter.
The current behaviour is that for each click a new line is drawn, but the line should be deleted and a new one should be drawn.
How can i erase the drawed line?
Do I have to redraw the comlete content of the user control?
You cannot delete a drawn line because there is no way to restore the underlying graphics.
What you could do is either:
Redraw the entire graph (without the line)
or
Stack a second transparent usercontrol on top and use that to display the line. Removing and drawing it when needed.
The answer here is clearly yes. With GDI+ you just draw directly on a bitmap buffer, so if you want to undo a previous drawing operation you can do one of those things (depending on the complexity of the issue and performance):
restore the bytes that have been changed on the bitmap buffer
reload a previous state of the drawing bitmap
A simple solution would be to have 2 bitmaps (something like that is usually called double buffering). One that is shown currently (and contains the final state) and one that is used for preview only. The preview one is always a copy of the first one - just with current modifications.
So basic algorithm for this simple implementation:
start with two bitmaps (blank but identical sizes) [named A and B]
if the user draws a line always make a copy of the bitmap A in B and draw on B - show B
if the user finishes the line then make a copy of B in A and again - show B
So always show the preview bitmap, which is just a modified bitmap of the original one.
Here is an example programming code in C# (assuming all events are connected and the preview Bitmap, B, is the picture box itself (which is just named pictureBox1 here):
Bitmap bmp;
bool isDrawing;
Point previous;
void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
isDrawing = true;
previous = e.Location;
}
void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
isDrawing = false;
}
void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (isDrawing)
{
using (Graphics g = Graphics.FromImage(bmp))
{
double wf = (double)bmp.Width / (double)pictureBox1.Width;
double hf = (double)bmp.Height / (double)pictureBox1.Height;
g.ScaleTransform((float)wf, (float)hf);
g.DrawLine(Pens.Black, e.Location, previous);
}
pictureBox1.Refresh();
previous = e.Location;
}
}
This code will do everything to display drawing a straight line from a point to another by simply pressing the left mouse button.

windows forms: create transparent graphic upon a chart in C#

I exhaustively used the search but have not been able to find a satisfying solution to my problem.
I programmed a data visualization using a chart (datavisualization.charting.chart). This chart changes steadily since it shows some kind of simulation results.
I would like to draw for example a line upon the chart (depending on the mouse position) in order to show context sensitive information.
Therefore, I tried two implementations, none of both works exactly as I would like it to:
plotLine is called on MouseMove- Event
gGraph is created from the underlying graph using: chartCreateGraphics();
protected void plotLine(object sender, System.EventArgs e)
{
if (this.chart.Series.Count > 0) //ensure that the chart shows data
{
plotChart(); // this plots the underlying chart
penGraph = new Pen(Color.Black);
Point point1 = new Point(Form1.MousePosition.X - chart.Location.X, 0);
Point point2 = new Point(Form1.MousePosition.X - chart.Location.X,
chart.Location.Y + chart.Size.Height);
gGraph.DrawLine(penGraph, point1, point2);
penGraph.Dispose();
}
}
Here, the line disappears each time immediately after being plotted, but should remain as long as the mouse is not moved.
protected void plotLine(object sender, System.EventArgs e)
{
penGraph = new Pen(Color.Black);
Point point1 = new Point(Form1.MousePosition.X - chart.Location.X, 0);
Point point2 = new Point(Form1.MousePosition.X - chart.Location.X,
chart.Location.Y + chart.Size.Height);
gGraph.DrawLine(penGraph, point1, point2);
penGraph.Dispose();
}
Here, all plotted lines remain in the graphics surface as long as the chart is not plotted by new. (only the last line should remain in order to indicate the mouse position)
Can anybody help me?
You should be drawing in the OnPaint event. You are circumventing the update model and are seeing the effects of doing so. Sure, you do some drawing in MouseMove, but when the Paint event fires it will simply be erased.
Put your code in OnPaint first. On mouse move simply record whatever data you need to (i.e., mouse position) and then call Invalidate() on the chart. When you do that the Paint event will be called and your drawing code will fire.
Rule of thumb; never draw from anywhere but the Paint event.

Categories

Resources