I have a panel, that can be moved left or right (chosen automatically according to its current position, distance is static) by click. Also, the user can drag the panel vertically however he wants by clicking the panel, holding the button and moving his mouse. The problem is, that the panel does the left/right move also, when it is dropped after being moved vertically, so the user has to click it again afterwards, to get to correct side (left/right). Here are the methods I am using:
Adding eventhandlers to panel(called Strip here)
Strip.MouseDown += new MouseEventHandler(button_MouseDown);
Strip.MouseMove += new MouseEventHandler(button_MouseMove);
Strip.MouseUp += new MouseEventHandler(button_MouseUp);
Strip.Click += new EventHandler(strip_Click);
And here all the methods mentioned above:
void button_MouseDown(object sender, MouseEventArgs e)
{
activeControl = sender as Control;
previousLocation = e.Location;
Cursor = Cursors.Hand;
}
void button_MouseMove(object sender, MouseEventArgs e)
{
if (activeControl == null || activeControl != sender)
return;
var location = activeControl.Location;
location.Offset(0, e.Location.Y - previousLocation.Y);
activeControl.Location = location;
}
void button_MouseUp(object sender, MouseEventArgs e)
{
activeControl = null;
Cursor = Cursors.Default;
}
void strip_Click(object sender, EventArgs e) // The one moving strip to left or right
{
activeControl = sender as Control;
if (activeControl.Left != 30)
activeControl.Left = 30;
else
activeControl.Left = 5;
}
How to make the panel not move left or right when it was moved vertically?
You'll need to distinguish between a click and a drag. So add a private field named "dragged".
private bool dragged;
In the MouseDown event handler add:
dragged = false;
In the MouseMove event handler add:
if (Math.Abs(location.Y - previousLocation.Y) >
SystemInformation.DoubleClickSize.Height) dragged = true;
In the Click event handler add:
if (dragged) return;
Related
I have been trying to fix an error for the last week.
I got a panel and inside this panel there is a picturebox (a map).
Whenever you press the mouse button and you move it to somewhere it moves the map, but whenever you release it and press it again and move it, it goes back to the default position of the map (but still dragable).
I need it to be that whenever someone release the button press, and click and move it again it proceed from the position it is currently.
I am sure it has something to with my MouseMove event and I have tried a lot of things and couldn't manage to fix it.
Here are my codes for the MouseUp, MouseDown and MouseMove events.
private bool Dragging;
private Point lastLocation;
private void countryMapImage_MouseUp(object sender, MouseEventArgs e)
{
Dragging = false;
lastLocation = e.Location;
}
private void countryMapImage_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Dragging = true;
lastLocation = e.Location;
}
}
private void countryMapImage_MouseMove(object sender, MouseEventArgs e)
{
if (Dragging == true)
{
int dx = e.X - lastLocation.X;
int dy = e.Y - lastLocation.Y;
countryMapImage.Padding = new Padding(Padding.Left + dx, Padding.Top + dy, Padding.Right - dx, Padding.Bottom - dy);
countryMapImage.Invalidate();
}
}
Would appreciate the help!
I have tried changing some values on the mousemove padding event, mousedown and mouseup events and nothing solved it. I have already tried to look for some answers but couldn't find any that solves the problem.
Try this: When user clicks the Map, capture the location of the cursor (in "screen" coordinates) and also the current location of the Map control. Now, as you move the mouse (and only if LButton is down) calculate a delta of the current cursor position (in "screen" coordinates) relative to the cursor position captured on the MouseDown event. Then, set the new position of the Map control to be the sum of its location that you captured on the MouseDown event plus the delta.
One key to having this work properly is to take the e.Location of the handler events and convert the point to screen coordinates relative to the sender.
public MainForm()
{
InitializeComponent();
countryMapImage.MouseMove += onMapMouseMove;
countryMapImage.MouseDown += onMapMouseDown;
}
Point
// Where's the cursor in relation to screen when mouse button is pressed?
_mouseDownScreen = new Point(),
// Where's the 'map' control when mouse button is pressed?
_controlDownPoint = new Point(),
// How much has the mouse moved from it's original mouse-down location?
_mouseDelta = new Point();
private void onMapMouseDown(object sender, MouseEventArgs e)
{
if (sender is Control control)
{
_mouseDownScreen = control.PointToScreen(e.Location);
Text = $"{_mouseDownScreen}";
_controlDownPoint = countryMapImage.Location;
}
}
private void onMapMouseMove(object sender, MouseEventArgs e)
{
if (MouseButtons.Equals(MouseButtons.Left))
{
if (sender is Control control)
{
var screen = control.PointToScreen(e.Location);
_mouseDelta = new Point(screen.X - _mouseDownScreen.X, screen.Y - _mouseDownScreen.Y);
Text = $"{_mouseDownScreen} {screen} {_mouseDelta}";
var newControlLocation = new Point(_controlDownPoint.X + _mouseDelta.X, _controlDownPoint.Y + _mouseDelta.Y);
if(!countryMapImage.Location.Equals(newControlLocation))
{
countryMapImage.Location = newControlLocation;
}
}
}
}
The MouseUp event shouldn't need to be handled in this simple scenario.
I have Form with textboxes and they have MouseEvent(MouseMove, MouseDown) and they are enabled on form load, but my question is how to call them just when i Click the Edit Button, so just then the textboxes can move?
My code:
private void textBox_MouseMove(object sender, MouseEventArgs e)
{
TextBox txt = sender as TextBox;
foreach (TextBox text in textBoxs)
{
if (e.Button == MouseButtons.Left)
{
if (txt.Name == text.Name)
{
txt.Left = e.X + txt.Left - MouseDownLocation.X;
txt.Top = e.Y + txt.Top - MouseDownLocation.Y;
}
}
}
}
private void textBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MouseDownLocation = e.Location;
}
}
private void btnEdit_Click(object sender, EventArgs e)
{
btnEdit.Visible = false;
btnPrint.Visible = false;
btnSave.Visible = true;
//Want to call mouse function here.
}
any suggestions?
Instead of hooking the events from the Visual Studio designer, you should manually hook the events in the btnEdit_Click handler method by adding this line:
textboxname.MouseMove += new MouseEventHandler(textBox_MouseMove);
Then unhook the event when your save button is clicked (I'm assuming you have some method btnSave_Click) by doing the following:
textboxname.MouseMove -= new MouseEventHandler(textBox_MouseMove);
The same goes for your MouseDown event.
If I understand your post, you want the textbox functionality to become "active" after you click the btnEdit button?
You could set a flag in btnEdit_Click, and only process the functionality in the other functions if that flag is true
Or, maybe add the event in the btnEdit_Click function, e.g.
private void btnEdit_Click(object sender, EventArgs e)
{
btnEdit.Visible = false;
btnPrint.Visible = false;
btnSave.Visible = true;
//Want to call mouse function here.
textBox.MouseDown += new MouseEventHandler(textBox_MouseDown);
}
But remove that extra line from where it currently exists in your code.
I am trying to create a form which contains panels created programmaticaly and controls able to drag drop and resize just like Microsoft Visual Studio IDE.
And I created something like this. there should be so many lines (blue one) and also so many boxes(yellow one) and I can be able to move yellow boxes inside of blue lines. everything works with defined controls on design time.
and the source codes here
public partial class Form1 : Form
{
bool allowResize = false;
public Form1()
{
InitializeComponent();
panel1.AllowDrop = true;
panel2.AllowDrop = true;
panel3.AllowDrop = true;
panel4.AllowDrop = true;
panel1.DragEnter += panel_DragEnter;
panel2.DragEnter += panel_DragEnter;
panel3.DragEnter += panel_DragEnter;
panel4.DragEnter += panel_DragEnter;
panel1.DragDrop += panel_DragDrop;
panel2.DragDrop += panel_DragDrop;
panel3.DragDrop += panel_DragDrop;
panel4.DragDrop += panel_DragDrop;
panelMove.MouseDown += panelMove_MouseDown;
}
void panelMove_MouseDown(object sender, MouseEventArgs e)
{
panelMove.DoDragDrop(panelMove, DragDropEffects.Move);
}
void panel_DragEnter(object sender, DragEventArgs e)
{
e.Effect = DragDropEffects.Move;
}
void panel_DragDrop(object sender, DragEventArgs e)
{
((Panel)e.Data.GetData(typeof(Panel))).Parent = (Panel)sender;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
allowResize = true;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
allowResize = false;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (allowResize)
{
this.panelMove.Height = pictureBox1.Top + e.Y;
this.panelMove.Width = pictureBox1.Left + e.X;
}
}
}
but I dont know how to create thoose controls (blue and yellow boxes ) on runtime.
You should check the Anchor property of Control. Anchor allows the control to automatically re-sized at runtime.
Use the Anchor property to define how a control is automatically
resized as its parent control is resized. Anchoring a control to its
parent control ensures that the anchored edges remain in the same
position relative to the edges of the parent control when the parent
control is resized.
You can anchor a control to one or more edges of its container. For
example, if you have a Form with a Button whose Anchor property value
is set to Top and Bottom, the Button is stretched to maintain the
anchored distance to the top and bottom edges of the Form as the
Height of the Form is increased.
MSDN : Control.Anchor
I have a problem with my winforms C# project.
I want to move a new (custom) button around the form (at run time).
How can I do that?
Button[] buttons = new Button[1000];
int counter = 0;
Button myText = new Button();
private void button2_Click(object sender, EventArgs e)
{
Button myText = new Button();
myText.Tag = counter;
myText.Location = new Point(x2,y2);
myText.Text = Convert.ToString(textBox3.Text);
this.Controls.Add(myText);
myText.MouseMove += new MouseEventHandler(myText_MouseMove);
myText.MouseDown += new MouseEventHandler(myText_MouseDown);
buttons[counter] = myText;
counter++;
}
public void myText_MouseMove(object sender, MouseEventArgs e)
{
int s = e.GetHashCode();
int check = 0;
for (int i = 0; i < counter; i++)
{
if (buttons[i].GetHashCode() == s)
check = i;
}
if (e.Button == MouseButtons.Left)
{
buttons[check].Left += e.X - move.X;
buttons[check].Top += e.Y - move.Y;
}
}
void myText_MouseDown(object sender, MouseEventArgs e)
{
move = e.Location;
}
I use the code above to create the new button and I am trying to move it around the form.
If I code for just 1 button I am able to move it but, I want to be able to do this for more buttons as well.
Try this
public void myText_MouseMove(object sender, MouseEventArgs e)
{
Button button = (Button)sender;
if (e.Button == MouseButtons.Left)
{
button .Left += e.X - move.X;
button .Top += e.Y - move.Y;
}
}
I've come across this thread while doing something similar.
Even though the thread is quite old; I'm sharing the way I've achieved this.
Notes:
Unlike the operator question above; in the example bellow; I'm not using a Button[] (array) with 1000 buttons; (but this can be easily changed).
In the example bellow I have:
A Form with 1 Button on it.
When this button is clicked; it will create a new (Custom) Button
(hence; having two button click events in the code simply for the test purpose).
Bellow you can find: A way to generate the button; and so how to drag it around the form.
/* Variables */
// Used to Store the Mouse Location on the Screen when Button is Clicked
private Point mouseDownLocation;
// Used to know if the Button can be Moved.
private bool isMoveable = false;
// Used to prevent clicking the button when being dragged
private bool clickEnabled = true;
/// <summary> Occurrs when the visible button on the Form is clicked. </summary>
private void Button_Click(object sender, EventArgs e)
{
// Create a variable to set the Size of the new Button.
Size size = new Size(100, 100);
// Create the Button. Specifying the Button Text and its Size.
CreateButton("Button Text", size);
}
/* Custom Button : Create & Configure the Button */
private void CreateButton(string btnText, Size btnSize)
{
// Create the Button instance:
Button btn = new Button();
// Custom Button Style Configuration Code.
// i.e: FlatStyle; FlatAppearance; BackColor; ForeColor; Text; Size; Location; etc...
btn.FlatStyle = FlatStyle.Standard;
btn.FlatAppearance.BorderColor = Color.White;
btn.BackColor = Color.Purple;
btn.ForeColor = Color.White;
btn.Text = btnText;
btn.Size = btnSize;
btn.Location = new Point(100, 100);
// Custom Button Event.
btn.Click += new EventHandler(CustomButton_Click);
btn.MouseDown += new MouseEventHandler(CustomButton_MouseDown);
btn.MouseMove += new MouseEventHandler(CustomButton_MouseMove);
btn.MouseUp += new MouseEventHandler(CustomButton_MouseUp);
// Add Button to Control Collection.
Controls.Add(btn);
// Show Button.
btn.Show();
}
/* Custom Button Events */
/// <summary> Occurrs whenever the Custom Button is Clicked </summary>
private void CustomButton_Click(object sender, EventArgs e)
{
if (clickEnabled)
{
// Note: The "for" loop bellow lets you get the current button; so you can drag it.
Button btn = (Button)sender;
// Iterate over the Form Controls
for (int i = 0; i < Controls.Count; i++)
{
// If the Button Clicked Corresponds to a Found Index in Control Collection...
if (i == Controls.IndexOf(btn))
{
// Perform Corresponding Button Action.
MessageBox.Show(btn.Name + " Clicked!");
}
}
}
}
/// <summary> Occurrs whenever Left Mouse Button Clicks the Button and is Kept Down. </summary>
private void CustomButton_MouseDown(object sender, MouseEventArgs e)
{
// Check if Left Mouse Button is Clicked.
if (e.Button == MouseButtons.Left)
{
// Set mouseDownLocation (Point) variable, according to the current mouse location (X and Y).
mouseDownLocation = e.Location;
// Enable the hability to move the Button.
isMoveable = true;
}
}
/// <summary> Occurrs whenever Left Mouse Button is Down and Mouse is Moving the Button. </summary>
private void CustomButton_MouseMove(object sender, MouseEventArgs e)
{
Button btn = (Button)sender;
// If the hability to move the button is "true" and the mouse button used to drag the button is the left mouse button:
if (isMoveable)
{
if (e.Button == MouseButtons.Left)
{
// Set the Button location X and Y...
btn.Left = e.X + btn.Left - mouseDownLocation.X;
btn.Top = e.Y + btn.Top - mouseDownLocation.Y;
}
}
// Disable Click hability (See: Note at the end of this post).
clickEnabled = false;
}
/// <summary> Occurrs whenever Left Mouse Button is not longer being hold down (Left Mouse Button is Up). </summary>
private void CustomButton_MouseUp(object sender, MouseEventArgs e)
{
// Disables the hability to move the button
isMoveable = false;
clickEnabled = true;
}
Note: The Custom Button Click interferes with the MouseDown Event. In a "simple" manner:
I updated the code by including a boolean value to prevent clicking the button when actually it is being dragged.
Hope this helps you out understanding how to accomplish this feature.
Hope this helps people out achieving this goal.
I have a fom which has one user control docked to fill.
this user control displays different images.each image has Id and I have a list of imageId vs imageDetail object dictionary.
Mouse Move event of this user control is captured and i am displaying current X and Y position of mouse in tool tip.
I also want to display image detail in tool tip when user keeps the mouse over image for some time.
I tried to do this with Mouse Hover event but it only raised when mouse enters in user control bound. after this if i move mouse within user control mouse hover event does not fire...
How can i display current X, Y position along image detail in tool tip.
is there any way to simulate Mouse Hover event within Mouse Move using some timer.
Is there any sample code..
I solved this problem by
public partial class Form1 : Form
{
Timer timer;
bool moveStart;
int count = 0;
Point prev;
public Form1()
{
InitializeComponent();
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(timer_Tick);
}
void timer_Tick(object sender, EventArgs e)
{
this.timer.Stop();
this.moveStart = false;
this.toolTip1.SetToolTip(this, string.Format("Mouse Hover"));
this.textBox1.Text = (++count).ToString();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (this.prev.X == e.X && this.prev.Y == e.Y)
return;
if (moveStart)
{
this.prev = new Point(e.X, e.Y);
this.timer.Stop();
this.toolTip1.SetToolTip(this, string.Format("Mouse Move\nX : {0}\nY : {1}", e.X, e.Y));
this.timer.Start();
}
else
{
moveStart = true;
}
}
}
The simplest way would be to call the MouseOver subroutine from the MouseMove subroutine as such:
void MouseMove(object sender, MouseEventArgs e)
{
//Call the MouseHover event
MouseHover(sender, e);
}
void MouseHover(object sender, EventArgs e)
{
//MouseHover event code
}
If you want more control over when and how to display your tooltip, however, you'll need to do something similar to the following:
Declare a listening variable at class level.
Hook to the MouseHover event so the listening variable is turned on when the mouse enters.
Hook to the MouseLeave event so the listening variable is turned off when the mouse leaves.
Put your tooltip code in the MouseMove handler so it displays your tooltip if the listening variable is on.
Here's some code to demonstrate what's I outlined above.
class Form1
{
bool showPopup = false;
void MouseHover(object sender, EventArgs e)
{
showPopup = true;
}
void MouseLeave(object sender, EventArgs e)
{
showPopup = false;
toolTip.Hide(this);
}
void MouseMove(object sender, MouseEventArgs e)
{
if (showPopup)
{
toolTip.Show("X: " + e.Location.X + "\r\nY: " + e.Location.Y,
this, e.Location)
}
}
}
Of course, you'll have to add a ToolTip with the name toolTip and associate the various methods (subroutines) with the appropriate events of your control (Form, PictureBox, etc).