C# How to drag and drop dynamically created rectangles - c#

In the UserControl I made it is possible to add Rectangles by clicking. Those rectangles are saved in a List. Now I want to make it possible for the User to move those Rectangles that are drawn.
First I tried to add the MouseDown, MouseMove and MouseUp event to the Rectangle but that doesn't work because Drawing Rectangle is a Struct and not a control. I already did a Testproject and accomplished to move a button I put in in the UserControl by Designer. I tried with the code I got from Drag and Drop Function with Drawing Rectangle C# .net - Forms but this example isn't about Rectangles. It is about Controls and I don't know how to use this idea for Rectangles because
rectangle.MouseDown += delegate(object sender, MouseEventArgs e)
{
//do something
}
doesn't work. Any Ideas how to drag and drop Rectangles that are added dynamically?

You should add the MouseDown event to the UserControl. Then loop through the list and make a method to see if the coordinates are inside of a Rectangle. If it is, then hook and move it.
So you should add a bool value to, which is set to true inside the MouseDown event and set to false inside the MouseUp event. Then in the MouseMove event, check if the mouseDown value is true. If it is and a Rectangle was found, move it's position.

Related

Picturebox blocks MouseEnter event from firing?

as a part of my WinForms application, I want to move a picturebox (blue box) onto the grid as seen below.
I'm moving the picturebox according to the mouse positions (while the left mouse button is pressed down).
Now my problem is, that when dragging the picturebox over the grid, the MouseEnter event is supposed to be called (each box in the grid is a picturebox in itself, with the event attached to it). The event gets called when simply moving with the mouse over it, but as soon as I'm dragging the blue box over it, it doesn't.
So my question is, is it possible that the picturebox on top (blue box) blocks the MouseEnter event of the picturebox on the bottom from firing? And if so, is there a way to work around it? I've thought about using Drag&Drop, but this seemed as the easier solution.
Thanks in advance.

getting mouse position of different control

I have a panel (panel2) inside another panel (panel1). I want to get mouse position of panel1, but when I move my mouse over panel2, the following code stops working.
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
label1.Text = "Offset: " + e.X + " x " + e.Y;
}
How can I get it to read the mouse arguments, even if the mouse is over panel2? Thanks!
EDIT: panel2 is located at center x=100, y=100 of panel1. if I move my mouse on panel2 left top corner it gives me coordinates for example 1x1, where I need to location on panel1 like 101x101
EDIT 2: I'm not trying to drag it, just read the coordinates of original panel (panel1) so I can calculate the offset for zooming the panel2. So I only need mousemove, nothing else. Thanks
If you only need to do this while a mouse button is being held down (for example, because you are tracking a drag and drop operation or a selection) then you can do the following:
In your MouseDown handler, call this.Capture = true;
Now your MouseMove handler will receive mouse move messages even when the mouse is over another control.
In your MouseUp handler, call this.Capture = false; - Note: If you forget to do this, your other controls in the same process will not receive any mouse messages.
Other than that, it's very tricky to get MouseMove messages from other controls without adding mouse handlers to those other controls.
The main thing about this.Capture is that you need a good time to set it to true and another good time to set it back to false. Generally, that's done in MouseDown and MouseUp as I described.
However, you could also convert the coords from Panel2-relative to Panel1-relative like so:
Convert from Panel2 coords to screen coords:
Point screenCoords = panel2.PointToScreen(mouseCoordInPanel2);
Then convert from screen coords to Panel1-relative coords:
Point mouseCoordInPanel1 = panel1.PointToClient(screenCoords);
To do this you would have to have a MouseMove handler in Panel2 where you did this conversion, and Panel2 would need a reference to Panel1 in order to call panel1.PointToClient()
You must also assign to the event of the other panel.
can't you put the event handler in panel2, then use the left/top properties of panel1 and panel2 to offset the mouse position within panel2 to get your desired location in panel1?
I also think that assigning an event to the second panel would be the best thing. When the mouse is on Panel 1, the coordinates would be provided directly; when it is on Panel 2, they would be converted by accounting for the relative positions between both panels (pretty straightforward: variation in X/Y positions; values which do not need to be hardcoded but updated at runtime).

How can I make the rectangles clickable, C#

The code can generate rectangles (Rectangle rectangle) at runtime. The position of rectangles may change according to users' choices.
I want to add code in the method where it creates rectangles to make the rectangles clickable. And after user clicking the rectangle, there will be a new window to show content just like text.
You can use Contains method of the Rectangle object.
private Rectangle _myRectangle;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (this._myRectangle.Contains(e.Location))
{
}
}
Create a label control with the border property and transaparent background(so that it will look as rectangle) and add click event handler for each label you add. It will be good if you create your own Rectangle control by deriving from Label class or you can create your own control(Many other solutions).
I would consider handling the click event on the window itself (or whatever your "background" control is), getting its coordinates, and comparing those to the known locations/sizes of your rectangles.

Problem with MouseMove event, launched when the content of control beneath is moved with arrow keys

My UserControl is a kind of a container that has a set of controls inside. One of the UI behaviours I designed is that the move over nested control makes it selected for some keyboard triggered actions.
The other way of setting up the nested control that is targeted to receive keyboard input is with arrow keys that change focus to certain control within my UserControl.
The problem is that in most cases my UserControl has scrollbars and switching between its elements with arrow keys causes contents to move. Because of that movement it seems that mousemove event is launched also when the mouse arrow stands still, but its over my usercontrol. In the end, the wrong nested control is being selected.
I tried to set a boolean flag to temporary lock the actions of mousemove event while the arrow keys handling function is launched, but it seems to not to work at all.
Does anybody have an idea how to prevent that unwanted triggering of mousemove event and avoid the problems it causes?
I did some debugging/experiments and it appears that though mouse stays still over controll the MouseMove is actually called frequently and not only when control move is caused by some UI behaviour (scrolling of parent controll called using keyboard).
It also seems like it is called twice every single second (but probably only when application is launched form VS during debug session?), the calls are separated by few hundred parts of seconds and for now i couldnt determine what causes those.
Solution (maybe not only, and not the best) is to store last position of cursor and compare it inside event to check if mouse was really moved from last MouseMove call. I achieved it using System.Windows.Forms.Cursor.Position because position from MouseEventArgs will be diffrent depending on circumstances but still will be inconclusive to determine if mouse cursor was moved.
Point lastCursorPosition = new Point();
private void panelPictures_MouseMove(object sender, MouseEventArgs e)
{
if (System.Windows.Forms.Cursor.Position != lastCursorPosition)
{
Console.WriteLine("mouse moved");
lastCursorPosition = System.Windows.Forms.Cursor.Position;
}
else
{
Console.WriteLine("mouse in place");
}
}

Canvas Click events in Silverlight when not over a UIElement

I have a canvas object and I am sprinkling fantastic controls all over it. I'm using a ScaleTransform object to scale the canvas so I can zoom in/out.
I have wired up the controls so that I can drag them around, and the drag and drop works well by using MouseLeftButtonDown, MouseLeftButtonUp, and MouseMove. Now, I want to work on enabling an event when I click only on the Canvas. When I read the docs for the canvas object, I see that the MouseLeftButtonDown event only fires when it's over a UIElement.
Occurs when the left mouse button is
pressed (or when the tip of the stylus
touches the tablet PC) while the mouse
pointer is over a UIElement.
(Inherited from UIElement.)
Unfortunately, I want the opposite behavior. I want to know when the mouse is clicked on the Canvas while the mouse pounter isn't over any controls. Since I'm new to Silverlight, I could be doing this the wrong way. Is there something I have overlooked? Am I going about this the wrong way? I'm looking for a little help, and perhaps a lot of direction.
I'm no Silverlight guru, but could you add a transparent UIElement to the Canvas, below all other UIElements, and use it to determine if the user has clicked outside of any of the other drag/drop-able elements.
You want to know when a click happens on the Canvas and isn't over other controls?
The most natural thing is to capture the Canvas's MouseLeftButtonDown. Inside of that event, take a peak to see where the click happened. Then peak at the UIElements under the click. I recommend you keep everything in absolute coordinates to keep things straight. Something like:
void Page_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(null);
var elements = VisualTreeHelper.FindElementsInHostCoordinates(p, App.Current.RootVisual);
foreach (var element in elements)
{
//Figure out if you're over a particular UI element
}
}
I think you may be interpreting the documentation wrong. According to MSDN, Canvas itself is an implementation of a UIElement:
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Panel
System.Windows.Controls.Canvas
From my experience, and correct me if I'm wrong, MouseLeftButtonDown usually only fires for the top-most UIElement clicked. So if you implement MouseLeftButtonDown for your Canvas, it should only fire when the Canvas is clicked, and NOT when the buttons are clicked. I'd say try it out first.
In WPF, I think this would be easily solved by routed events. However, Silverlight didn't get this feature. You may want to check out VisualTreeHelper.FindElementsInHostCoordinates. This article covers it a little bit.
http://www.andybeaulieu.com/Default.aspx?tabid=67&EntryID=95

Categories

Resources