Why undo Drawline() in my opinion is not work? - c#

I try to remove newest drawline.
declaration
Bitmap DrawArea ; // global variable
Bitmap Previuos_DrawArea; // global variable
when I click button to draw a line
private void button2_Click_1(object sender, EventArgs e)
{
Graphics g = Graphics.FromImage(DrawArea);
Previuos_DrawArea_img = DrawArea;
g.(new Pen(Brushes.BlueViolet, 1.0F),0,10,10,20);
pictureBox1.Image = DrawArea;
}
when I click button to remove a line
private void button3_Click_1(object sender, EventArgs e)
{
pictureBox1.Image = Previuos_DrawArea_img;
}
Concept :
1st step - Declare variable.
2nd step - Backup current picture.
3rd step - Draw new picture.
4th step - if undo just draw the backup picture.

You aren’t creating a copy of the bitmap, you’re only storing it in two variables. They point to the same bitmap so editing one affects the other one. You’ll need to create a copy:
Previuos_DrawArea_img = new Bitmap(DrawArea);
Now it is a separate image and whatever you do to one of them doesn’t affect the other one.

Related

Make a picturebox change itself very fast between 2 pictures (Windows Forms app)

I want to make a picture change itself very fast between 2 pictures. I have the pictures saved in the debug folder of the program.
Here is the image of pictures with there names saved:
https://i.stack.imgur.com/XQ9g5.png
So here is the code were I save a picture in the picturebox so that there is not an empty picturebox
private void Gamble_Load(object sender, EventArgs e)
{
pictureBox1.Image = (Image.FromFile("21.png"));
}
And here is the timer click method I think I need to use for this action
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Image = pictureBox1.Image is null;
}
Try putting this in your Gamble_Load:
var t = new Timer(x => pictureBox1.Image = (Image.FromFile("otherimage.png")), null, 1000);
This creates a timer that will fire after 1 second and update the image.
https://learn.microsoft.com/en-us/dotnet/api/system.timers.timer?view=net-6.0

How to do two different graphics plotting in parallel using C#

I am developing the GUI in C# using picturebox, button, and check box.I need to plot two different plots in parallel using one text file on an image. The image first reads in a picture box. The rest of the program has to be executed in the following way:
Reads text file contains the data points which have to be plotted.
After clicking the button the program execution started with the plotting of the First graphic (rectangular dot), however when the check box is checked the second graphic (continuous dots--path plot) plotting started in parallel with the first graphic.
when the check box is unchecked the second graphic stopped plotting and disappears.(As Both of the graphics style using the same text file).
I need help what to do in this case, should I create the separate thread for check box for this parallel plotting??
please help me where I am mistaken? And pardon my horrible English
From my point of view, the easiest way would be to reload the image into the picture box again and then redraw the first graphics object on it. So, the second one 'disappears'.
An additional thread makes no sense, because drawing must occur on the UI thread only (Windows general rule for GDI+, WinForms, WPF).
Such basic drawing as in your example is very fast.
Edit:
namespace PictureBoxDrawing
{
public partial class Form1 : Form
{
private Bitmap _bmpImage;
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_bmpImage = new Bitmap(#"C:\Image.jpg");
InitializePictureBox(_bmpImage);
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
DrawPictureBox(pictureBox1, 10, 10, checkBox1.Checked);
}
private void button1_Click(object sender, EventArgs e)
{
DrawPictureBox(pictureBox1, 10, 10, checkBox1.Checked);
}
private void button2_Click(object sender, EventArgs e)
{
InitializePictureBox(_bmpImage);
}
private void DrawPictureBox(PictureBox pb, int x, int y, bool drawBlue)
{
using (Graphics g = pb.CreateGraphics())
{
g.FillRectangle(Brushes.Red, x,y, 9,9);
if(drawBlue)
g.FillRectangle(Brushes.Blue, x, y, 7, 7);
}
}
private void InitializePictureBox(Bitmap bmp)
{
pictureBox1.Image = bmp;
}
}
}
From your example, here is my simplified suggestion. Load and cache the bitmap in a field for later use. I have added a second button2, which can be used to reload the image into the picture box to demonstrate the behaviour. Because the red rectangle is greater than the blue (9 > 7), it overwrites it when redrawing. So it is not necessary to reload the bitmap, if the position is constant. If the position changes, call InitializePictureBox prior to the DrawPictureBox call.

How to pass EventArgs to a function

I have a function that will draw a image to a form.
private void DrawImage()
{
OpenFileDialog openfiledialog = new OpenFileDialog();
if (openfiledialog.ShowDialog() == DialogResult.OK)
{
Bitmap image = (Bitmap)Image.FromFile(openfiledialog.FileName, true);
TextureBrush texturebrush = new TextureBrush(image);
texturebrush.WrapMode = System.Drawing.Drawing2D.WrapMode.Tile;
Graphics formGraphics = this.CreateGraphics();
formGraphics.FillRectangle(texturebrush, new RectangleF(90.0F, 110.0F, 00, 300));
formGraphics.Dispose();
}
}
But i will not draw any image and same code works if i write in button click event.
private void button1_Click(object sender, EventArgs e)
{
//Same code as written in DrawImage()
}
The problem I think is it needs "EventArgs e" in it. I read some where in msdn but not sure.No idea what is the role of EventArgs in drawing image on form.
Is there any way that I can achieve this functionality.
TL;DR
You don't have to. For your case, just ignore them. They may be, however, useful sometimes. Read full answer to understand.
Full answer
When dealing with events, you receive a generic EventArgs object and if you write a custom event, you may want to receive a custom implementation of EventArgs.
To make things simple, consider it a base class that holds event-related data.
So, for instance, if you are implementing a click event, as shown, you will receive two arguments: a source for the event and a holder for the event-related data.
Sometimes this is just useless. As on your sample. You don't have to receive it, nor use it. You may, however, perform some check on the source or the event data but that's not the goal of your code so both are just useless here.
As for me, I prefer to keep my methods apart from events, and call them from the event. I do place every event binding in a "group" on the bottom of the class to keep everything clean and readable. That's just a suggestion, you have to find your very own way of keeping code.
For the sake of this answer, here follows two samples:
1. Useless arguments
This sample just closes a form or window.
public void btn1_Click(object sender, EventArgs e) { Close(); }
2. Usefull arguments
Consider a component with a data grid of some type which fires a SelectedRowsChanged event with the id's (PK) of the selected rows.
// Event declaration. You can, after that, bind it elsewhere.
public event EventHandler<SelectionEventArgs> SelectedRowsChanged;
// This is the local implementation wich will fire the event.
// Here you invoke the event with the selected rows id's.
public void OnSelectedRowsChanged() { if (SelectedRowsChanged != null) CustomSelection(this, new SelectionEventArgs(this.SelectedRows)); }
// This is the custom implementation of the EventArgs to include the
// event-related data (row id)
public class SelectionEventArgs : EventArgs
{
public int[] SelectedRows{ get; private set; }
public SelectionEventArgs(int[] selectedRows) { SelectedRows = selectedRows; }
}
// ... then, somewhere else on your code
this.myControl.SelectedRowsChanged += myControl_SelectedRowsChanged;
public void myControl_SelectedRowsChanged(object sender, SelectionEventArgs e)
{
if (e.SelectedRows.Length > 0) { /* do something */ }
}
For the strong of heart, you may play a bit with lambda too. So, instead of:
this.button1.Click += button1_Click;
public void button1_Click(object sender, EventArgs e) { DoSomething(); }
you may have just this:
this.button1.Click += (s, e) => { DoSomething(); };
As on the first sample, event args are there ((s, e)) but they are just useless for the DoSomething method.
Lambdas are available in C# 5 (.NET 4.5) and above.
Sometimes it's easier to just do this in a form constructor or something alike.
Consider these tips to solve the problem:
If you use this.CreateGraphics for drawing on your form, then your drawing will disappear if the form refershes, for example if you minimize and restore it. You should put drawing logic in Paint event.
When refactoring your method, you should pass a parameter of Graphics type to your method and use it for drawing. Also you should not dispose passed parameter. You should pass e.Graphics in Paint event to your method.
In your method you should dispose your brush. Put it in a using block.
When refactoring your method, you should move the part of code which shows a dialog to out of your method. You should call it just when you need not in Paint event handler.
Preferably Don't use Image.FromFile to load image, it locks the file until the images disposes. Instead use Image.FromStream.
You are using a rectangle with 0 as Width. So if you draw even using current method, you will not see any result because of width of rectangle.
Code
Bitmap image;
private void DrawImage(Bitmap image, Graphics g, Rectangle r)
{
using (var brush = new TextureBrush(image))
{
brush.WrapMode = System.Drawing.Drawing2D.WrapMode.Tile;
g.FillRectangle(brush, r);
}
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
using (var s = new System.IO.FileStream(dialog.FileName, System.IO.FileMode.Open))
image = new Bitmap(Image.FromStream(s));
this.Invalidate();
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (image != null)
this.DrawImage(image, e.Graphics, new RectangleF(10, 10, 200, 200));
}

Refreshing image on panel creates infinite loop (C# - Winforms)

I'm having a problem with refreshing graphics on panels and forms.
When I draw the image it works fine but when I want to replace it with another image using Panel.Refresh it makes the event handler auto activate itself without end. If I use Panel.Update it will just draw the second image onto the first. A lot of people recommended that I use the Invalidate method but that has the same infinite loop problem.
Bitmap bitmap = new Bitmap(Resources.Image1);
private void panel1_Paint(object sender, PaintEventArgs e)
{
if (parameter == 0) { bitmap = new Bitmap(Resources.Image1); }
if (parameter >= 2) { bitmap = new Bitmap(Resources.Image2); }
e.Graphics.DrawImage(bitmap, 60, 10);
panel1.Refresh();
}
panel1.Refresh();
Causes the paint event to trigger. I put the refresh code where the parameter value is changed.

Cursor.Position resets automatically?

I have a simple method :
private void button1_Click(object sender, EventArgs e)
{
System.Windows.Forms.Cursor.Position = new System.Drawing.Point(200, 200);
}
The cursor changes to the point (200,200) but as soon as the mouse is moved the cursor returns back to the original point (where the button is).
I will note that I run this on 2 different computers, on one of them it is working fine, on the other the above problem occurs.
Any suggestions ?
This might be due to a feature called Snap To and can be enabled or disabled from the control panel.
It makes that the mouse moves to a focussed button.
On other option you might try is to set the focus to a different control:
private void button1_Click(object sender, EventArgs e)
{
// I have a pictureBox1 on my form that I could set the focus to
this.pictureBox1.Focus();
System.Windows.Forms.Cursor.Position = new System.Drawing.Point(20, 20);
}

Categories

Resources