Trying to implement ctrl z option in windows form - c#

I have been trying to implement a ctrl z feature in my mini paint application.
The problem is that for the picture box side of things, it doesn't work. At the the beggining of the mouse up event before the new drawing, I save the current picture box image in a stack and when I press ctrl z, I pop that image and save it in the picture box image. The problem is that it always saves the new modified image in the stack not the previous one even if I saved it technically before the new updates (at the begining of the mouse up event).
A snippet of the code
void key(object sender, KeyEventArgs e){
...
else if ( e.Control && e.KeyCode == Keys.Z) {
if (save.Count > 0) {
//trying to save the previous image
pictureBox9.Image = save.Peek() as Image;
drawArea = save.Pop() as Bitmap;
pictureBox9.Image = drawArea;
g1 = Graphics.FromImage(drawArea);
// pictureBox9.Refresh();
}
}
}
private void pictureBox9_MouseUp(object sender, MouseEventArgs e){
save.push(pictureBox9.Image);
//save is the stack and that should be the current image
....
}

Related

How do I add a picture to a form in runtime using a click from computer mouse in C#?

I want to be ale to add an image to a form in runtime using a click from the left mouse button. When I tried the code below, nothing happens. I don't get an error message and the picture doesn't appear where I click. I'm not sure if I'm on the right track or not. I don't know how to start if this isn't how I go about doing this operations.
private void button7_Click(object sender, EventArgs e)
{
Floors floors = new Floors();
floors.ShowDialog();
if(Mouse.LeftButton == MouseButtonState.Pressed)
{
var picture = new PictureBox
{
Name = "pictureBox",
Size = new Size(16, 16),
Location = new Point(100, 100),
Image = Final_Project_1_.Properties.Resources.fire_icon,
};
this.Controls.Add(picture);
}
}
So I tried the following code:
private void button1_Click(object sender, EventArgs e)
{
var picture = new PictureBox
{
Name = "pictureBox",
Size = new Size(16, 16),
Location = new Point(100, 100),
Image = WinFormsTestApp.Properties.Resources.Copy,
SizeMode = PictureBoxSizeMode.StretchImage
};
this.Controls.Add(picture);
}
and this worked perfectly fine. If this doesn't work on your machine, your image link may be corrupted or something else is overlapping the image.
However, if this works, I guess it's currently not working because of the if statement with the mouse button. It could be, that the click event will only be raised, if the mouse button is up again so the if statement can never be true. If you want to achieve, that the image is created the moment the mouse button goes down, you should be able to do so with the MouseDown Event.

C# - Winforms - Custom Drag Image is Not Displayed When Dragging by Touch

I have an old WinForms app written in C# with custom drag and drop capabilities. And this app has an issue when it is run on a touch screen device, such as the Surface Pro 3.
Basically there is a treeview control that allows the items to be dragged to a different area of the app and have some calculations done. If I use the mouse or the stylus the custom drag image is drawn on the screen. If I drag an item using touch the image is not displayed but the code is executed properly, including the drawing of a custom cursor.
It seems that the custom drag image is not displayed because the mouse cursor is hidden by the O.S. during a touch drag operation. How do I get the drag image to display?
UPDATE
Here is some code to demonstrate what I am trying to fix. Create a new WinForms app, add a treeview to it and wire up the events. You'll notice that if you use a stylus or the mouse the drag operation will show an icon. If you touch-drag an item, nothing shows.
public Form1()
{
InitializeComponent();
TreeNode node = new TreeNode("welp");
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
treeView1.Nodes.Add(node);
}
private void treeView1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
private void treeView1_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
e.UseDefaultCursors = true;
}
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
((TreeView)sender).DoDragDrop(e.Item, DragDropEffects.Move);
}
Ok, So I got this working exactly the way that I want it to. Wasn't easy and it's probably not the preferred way to go about it but it does what I want and I was on a time crunch to get this finished.
First, I found this article Shell Style Drag and Drop. It worked, for the most part, but it was written about 7 years ago and doesn't take into consideration how the O.S. has changed. Too much to go into the details about that and why it didn't work for me.
The main issue I was trying to fix was that my original drag and drop code used the old school way of drawing a new cursor in the GiveFeedback event of a drag and drop operation. Worked great except on touch devices because the Windows O.S. hid the cursor during a touch-drag operation so my custom drawn cursor would never be displayed. A few (used lightly) Google searches revealed that Windows won't allow two pointer devices to be active at the same time, even with calling the native ShowCursor method. Fair enough.
The biggest issue with trying to draw on the screen while in a drag and drop operation is that most of the messages sent to a window, such as WM_MOUSEMOVE and WM_PAINT are suspended. The only way I could draw anything was in the GiveFeedback event.
So, I found this article that covers drawing using a transparent overlay. Again, it didn't do exactly what I wanted but with a little tweaking it worked perfectly. I was able to grab the HDC of the overlay and the HDC of my form and do a nice BitBlt operation to display my custom bitmap on the screen and erase the old drawing by grabbing the underlying image of the form. I also changed the method that draws a custom cursor to a method that draws a custom bitmap.
Here is what I changed in regards to the article above
this.BackColor = Color.White;
this.Opacity = 1; // Tweak as desired
this.TransparencyKey = Color.White;
And what I added to allow the message pump to go through
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= Win32.WS_EX_TRANSPARENT;
return createParams;
}
}
The details of the rest are not overly complex but require a nice blending of the drag and drop operations, the overlay, drawing and erasing and double buffering. And there are situations, like in my case, where I have a TreeView control updating while I am dragging and I have to expand the rectangle of the draw operation so the bitblt image covers the areas outside of my drawing.
If you are interested in this article and want to see what I did and how I accomplished it, let me know in the comments and I will post code.
try this code
hope is helped you
public Form1()
{
InitializeComponent();
TreeNode node;
for (int x = 0; x < 3; ++x)
{
node = treeView1.Nodes.Add(String.Format("Node{0}", x * 4));
for (int y = 1; y < 4; ++y)
{
node = node.Nodes.Add(String.Format("Node{0}", x * 4 + y));
}
}
treeView1.AllowDrop = true;
treeView1.Dock = DockStyle.Fill;
treeView1.ItemDrag += new ItemDragEventHandler(treeView1_ItemDrag);
treeView1.DragEnter += new DragEventHandler(treeView1_DragEnter);
treeView1.DragOver += new DragEventHandler(treeView1_DragOver);
treeView1.DragDrop += new DragEventHandler(treeView1_DragDrop);
}
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
DoDragDrop(e.Item, DragDropEffects.Move);
}
else if (e.Button == MouseButtons.Right)
{
DoDragDrop(e.Item, DragDropEffects.Copy);
}
}
private void treeView1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.AllowedEffect;
}
private void treeView1_DragOver(object sender, DragEventArgs e)
{
Point targetPoint = treeView1.PointToClient(new Point(e.X, e.Y));
treeView1.SelectedNode = treeView1.GetNodeAt(targetPoint);
}
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
Point targetPoint = treeView1.PointToClient(new Point(e.X, e.Y));
TreeNode targetNode = treeView1.GetNodeAt(targetPoint);
TreeNode draggedNode = (TreeNode)e.Data.GetData(typeof(TreeNode));
if (!draggedNode.Equals(targetNode) && !ContainsNode(draggedNode, targetNode))
{
if (e.Effect == DragDropEffects.Move)
{
draggedNode.Remove();
targetNode.Nodes.Add(draggedNode);
}
else if (e.Effect == DragDropEffects.Copy)
{
targetNode.Nodes.Add((TreeNode)draggedNode.Clone());
}
targetNode.Expand();
}
}
private bool ContainsNode(TreeNode node1, TreeNode node2)
{
if (node2.Parent == null) return false;
if (node2.Parent.Equals(node1)) return true;
return ContainsNode(node1, node2.Parent);
}

If PictureBox Clicked Event

I'm trying to program a matching game. My idea is:
(1). When a certain pictureBox1 is clicked, it becomes invisible
(2). A MessageBox shows up, prompting "Pick another box."
(3). Finally, I need to program an if/else statement where if pictureBox13 is clicked it becomes invisible; else, (if another pictureBox is clicked) a MessageBox prompts "Try again." And both picture boxes become invisible, but I don't know what I am doing wrong:
// Program From Below
private void pictureBox1_Click(object sender, EventArgs e)
{
MessageBox.Show("Now Pick Another Hidden Picture!");
pictureBox1.Visible = false;
if (pictureBox13_Click)
{
MessageBox.Show("Great!");
pictureBox13.Visible = false;
}
else
{
MessageBox.Show("Try Again!");
}
}
There is a red squiggly line under if (pictureBox13_Click)
It would be better if every PictureBox had it's a state, that you would then manipulate using a Click_Event. Microsoft has a comprehensive tutorial for a matching game here: https://msdn.microsoft.com/en-us/library/dd553235.aspx
As other suggested, you can use same event handler for all your pictureBoxes and cast sender to PictureBox to see what PB was clicked :
List<string> selectedPictureBoxes;
public MyForm() // ctor
{
selectedPictureBoxes = new List<string>();
foreach(Control c in this.Controls)
if(c is PictureBox) c.Click += pictureBox_Click;
}
private void pictureBox_Click(object sender, EventArgs e)
{
PictureBox _clicked = sender as PictureBox;
if(!selectedPictureBoxes.Contains(_clicked.Name))
selectedPictureBoxes.Add(_clicked.Name);
else ....
}
You could create an int for the selected boxes (in this example, box1 and box2) which are both set to 0 and then create an on click event which sets the int to the clicked box.
if(box1 != 0)
{
box2 = 'insert selected box number'
}
else
{
box1 = 'insert selected box number'
}
After two boxes have been selected, both integers can be set to false, this allows for you to use a switch instead of if, which could shorten the code substantially if a separate if statement is required for each pair of pictures.

Image disappears when dropped outside our pictureboxes

First off, thanks for reading this and taking the time to try help us.
We are currently making this project for our c# class, we had to study Drag&Drop by ourselves but we are having a problem.
Situation:
We have 6 starting pictureboxes with images, we also have 6 textboxes with a description, the idea is simple, match them together. However, if we drag an image from the starting picturebox into one of the 6 answer pictureboxes but by accident drop it on the form, it disappears.
We are clueless to find a way to actually 'reset' the image back to starting position when not placed in a picturebox.
private void Picture_MouseDown(object sender, MouseEventArgs e)
{
try
{
PictureBox source = (PictureBox)sender;
naam = source.ImageLocation;
source.DoDragDrop(source.Image, DragDropEffects.Move);
source.Image = null;
}
catch (NullReferenceException)
{
try
{
throw new RijException("Picturebox is momenteel leeg.");
}
catch (RijException)
{
}
}
}
private void Picture_DragEnter(object sender, DragEventArgs e)
{
PictureBox source = (PictureBox)sender;
e.Effect = DragDropEffects.Move;
}
private void Picture_DragDrop(object sender, DragEventArgs e)
{
PictureBox source = (PictureBox)sender;
source.Image = (Image)e.Data.GetData(DataFormats.Bitmap);
source.Tag = naam;
}
So when we actually drop the image (while dragging) outside the picturebox (in the form) It will just disappear, What we need is a solution to reset it to starting position, but don't know how we could manage to pull that off.

Which pictureBox was selected? C#

I am working on a piano in C#. I have encountered a small problem.
I have a piano keyboard which, when pressed, displays the relevant note on the staff.
The notes created are stored in an array of type PictureBox, called picBox. I have constructed the following event handler, however it is not working.
private void pictureBox_Click(object sender, MouseEventArgs e)
{
picBox[0].MouseDown += new MouseEventHandler(pic_Click); //testing for first location
}
private void pic_Click(object sender, MouseEventArgs e)
{
ClickedTextBox.Text = "I was clicked";
}
I am just testing to see if the first note was clicked. Why is this not working?
Here is the method which adds the picturebox (containing the note) to the staff (panel3).
public void addPictureBox(int x, int y, Image image)
{
picBox[cnt] = new PictureBox();
picBox[cnt].Image = image;
picBox[cnt].Location = new Point(x, y);
picBox[cnt].BackColor = Color.Transparent;
panel3.Controls.Add(picBox[cnt]);
picBox[cnt].BringToFront();
cnt++;
}
What is wrong with my event handler please? Also, what can I do to identify the location in the array of the picturebox clicked? Thank you
As said in the first comment, you subscribe to the event in a wrong location.
Also use the sender parameter of your event handler to know which picturebox is clicked (it'll contain an instance of the picturebox).

Categories