I'm trying to make a button follow the cursor, but my code only seems to just go to the mouse cursor right after execution and just stay there. Can anyone give me the correct code and help me?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
button1.Location = Cursor.Position;
}
}
}
I would suggest overriding the OnMouseMove method of the MainForm and using the Location property of the MouseEventArgs e argument. This will provide the correct Client coordinates of the cursor taking into account where MainForm is located on the screen. Then you can offset that value using the Width and Height properties of buttonMoveMe to center it on the mouse.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
var point = new Point(
e.Location.X - (buttonMoveMe.Width / 2),
e.Location.Y - (buttonMoveMe.Height / 2));
buttonMoveMe.Location = point;
}
}
Be aware that this event _will not be received when the mouse is over the button itself. The button will be getting the MouseMove events (not the MainForm) in this case. In other words, this basic suggestion only moves the button when the mouse leaves the button.
I think you need to use the MouseMove event.
So these are things you need to do:
Create a button control which is going to follow the cursor. (I will call it yourButton)
Open event menu of the control (click on it in the constructor).
Find event MouseMove inside Mouse category.
Double click on it. (This will automatically create the method which will be linked to the event)
In this method write: yourButton.Location = e.Location;
So it should look like that:
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
yourButton.Location = e.Location;
}
In my example I made button follow my cursor inside the form.
If you need shorter way, you can just copy-paste the method I wrote before and in the form class constructor add:
this.MouseMove += Form1_MouseMove;
In this way your code would look like that:
public Form1()
{
InitializeComponent();
this.MouseMove += Form1_MouseMove;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
yourButton.Location = e.Location;
}
Hope this will help you, have a nice day!
UPD:
In case you want the cursor to be in the center of the button, you should edit our previous Form1_MouseMove and add one more event.
Edit the code of Form1_MouseMove, now it should be:
yourButton.Location = new Point(e.X - yourButton.Width / 2, e.Y - yourButton.Height / 2);
Now you need to use MouseMove method of the button (Follow the previous steps, but for button (Click on it -> Events -> Mouse category -> double click on MouseMove))
In newly created method write:
yourButton.Location = new Point(e.X + yourButton.Left - yourButton.Width / 2, e.Y + yourButton.Top - yourButton.Height / 2);
Hope this helped now)
Your Form1_Load method is only executed, as its name says, when the form is loaded.
You want to execute your code every time the mouse move, si you can do it like this (not tested):
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseMove += Form1_MouseMove;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
button1.Location = Cursor.Position;
}
}
Related
How do I drag borderless Form? I tried almost everything but most of the solutions are pretty confusing as I don't have decent experience in C#.
so i find this approach. feel free to delete if its duplicate but for me it looks the most simple.
in order to drag window we need some sort of loop that runs while we have mouse button pressed, im doing it with timer.
also we need variable that will store initial mouse press location.
using System.Timers;
using Timer = System.Timers.Timer;
public partial class Form1 : Form
{
private static Timer moveTimer;
private static Point pnt;
public Form1()
{
InitializeComponent();
moveTimer = new Timer();
moveTimer.Interval = 0.1;
moveTimer.Enabled = false;
moveTimer.Elapsed += moveTimerEvent;
moveTimer.AutoReset = true;
}
next we just add MouseDown and MouseUp Events to every control we want to be able to move window. usually i have this event on menustrip like most browsers do nowadays but you can use any control
private void AddHub_MouseDown(object sender, MouseEventArgs e)
{
pnt = new Point(e.Location.X+(sender as Control).Location.X, e.Location.Y + (sender as Control).Location.Y);
moveTimer.Enabled = true;
}
private void AddHub_MouseUp(object sender, MouseEventArgs e)
{
moveTimer.Enabled = false;
}
we are getting mouse location with respect to control with e.location and then controls location with respect to form with (sender as Control).Location
so mouse location with respect to form is mouse location with respect to control + controls location with respect to form
and finally we use timer event moveTimerEvent to actually drag a window
private void moveTimerEvent(Object source, ElapsedEventArgs e)
{
if (InvokeRequired)
{
Invoke(new MethodInvoker(delegate { Location = new Point(Cursor.Position.X - pnt.X, Cursor.Position.Y - pnt.Y); }));
}
}
we need to invoke a method as timer moveTimerEvent is running in another thread and cant directly affect Form1.
this is a pseudo code to calculate Form1 location from mouse location: Form1.location = Cursor.Position - pnt and this location is with respect to screen.
Is this possible to detect a mouse click (Left/Right) anywhere (Inside and Outside the Form) in an if statement? And if it's possible, how?
if(MouseButtons.LeftButton == MouseButtonState.Pressed){
...
}
Here is a starter, if I understood your needs of "clicking from outside the window" and Hans Passant's suggestion doesn't fit your needs. You might need to add an event handler for Form1_Click.
CAUTION: This code is provided to illustrate the concept. The threading synchronization in this sample is not 100% correct. Check the history of this answer for an attempt at a more "threading correct" one that sometimes throws exceptions. As an alternative, to get rid of all threading issues, you could have the task in StartWaitingForClickFromOutside be instead always running (aka be always in "listen" mode) as opposed to trying to detect the "within the form" or "outside the form" states and starting/stopping the loop accordingly.
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseLeave += Form1_MouseLeave;
this.Leave += Form1_Leave;
this.Deactivate += Form1_Deactivate;
this.MouseEnter += Form1_MouseEnter;
this.Activated += Form1_Activated;
this.Enter += Form1_Enter;
this.VisibleChanged += Form1_VisibleChanged;
}
private AutoResetEvent are = new AutoResetEvent(false);
// You could create just one handler, but this is to show what you need to link to
private void Form1_MouseLeave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void Form1_Leave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void Form1_Deactivate(object sender, EventArgs e) => StartWaitingForClickFromOutside();
private void StartWaitingForClickFromOutside()
{
are.Reset();
var ctx = new SynchronizationContext();
var task = Task.Run(() =>
{
while (true)
{
if (are.WaitOne(1)) break;
if (MouseButtons == MouseButtons.Left)
{
ctx.Send(CLickFromOutside, null);
// You might need to put in a delay here and not break depending on what you want to accomplish
break;
}
}
});
}
private void CLickFromOutside(object state) => MessageBox.Show("Clicked from outside of the window");
private void Form1_MouseEnter(object sender, EventArgs e) => are.Set();
private void Form1_Activated(object sender, EventArgs e) => are.Set();
private void Form1_Enter(object sender, EventArgs e) => are.Set();
private void Form1_VisibleChanged(object sender, EventArgs e)
{
if (Visible) are.Set();
else StartWaitingForClickFromOutside();
}
}
}
If I understood you incorrectly, you might find this useful: Pass click event of child control to the parent control
When user clicks outside the form control, it losses the focus and you can make use of that.which means you have to use the _Deactivate(object sender, EventArgs e) event of the form control to make this work. Since which will trigger when the form loses focus and is no longer the active form. Let Form1 be the form, then the event will be like the following:
private void Form1_Deactivate(object sender, EventArgs e)
{
// Your code here to handle this event
}
One method is to cover the entire screen with a borderless form with the properties set to transparent (a few percent above completely transparent, not sure if total transparency works but you won't notice the difference) and also set to topmost. Then use the events from the form. As soon as a click is detected this will not affect anything underneath the form (which in my application is something I want to happen) but the form could be closed and another mouse click simulated a fraction of a second later to activate the controls that are underneath. I had no problem using the windows API to use mouse hooks in VB6 but cannot seem to find something that works in c# with the 2019 version of .NET so this is a good workaround. Of course to be really clever you could use an irregular forms method to make the transparent form the same shape as the mouse and follow it.
Note: I have just found the complete code to do it using hooks that mere mortals can get up and running at once! KeyboardMouseHooks C# Library - CodePlex Archive
PS if you use my (dumb) method remember to create an escape key or button or you will have to restart your computer unless the form is programmed to disappear for real clicks as suggested!
I know this is late but maybe it helps someone. Using the MouseEventArgs of the MouseUp event of any control you can check for mouse button and wheel among other things. Here is an example.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.MouseUp += Form1_MouseUp;
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
DoSomething_LeftClick();
}
else if(e.Button == MouseButtons.Right)
{
DoSomething_RightClick();
}
}
private void DoSomething_LeftClick()
{
//Here some code
}
private void DoSomething_RightClick()
{
//Here some code
}
}
After looking at Mousewheel event not firing and at MouseWheel event doesn't fire when using any control with scrolbars (in C# Windows Forms) and at MouseWheel Event With Picturebox?, I have coded the following fragment which, well .... doesn't work (i.e., mouse wheel won't fire in VS2013, Win7, x64). Appericate any help.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
namespace MyWinForm
{
class Program
{
private Form theForm;
private PictureBox thePictureBox;
static void Main(string[] args)
{
Program theProgram = new Program();
Application.Run(theProgram.theForm);
}
Program()
{
theForm = new Form();
thePictureBox = new PictureBox();
theForm.Controls.Add(thePictureBox);
thePictureBox.Image = Image.FromFile(#"D:\cameraman.bmp");
thePictureBox.Width = theImage.Width;
thePictureBox.Height = theImage.Height;
thePictureBox.MouseWheel += new MouseEventHandler(this.PictureBox_MouseWheel);
thePictureBox.MouseHover += new EventHandler(this.PictureBox_MouseHover);
}
private void PictureBox_MouseWheel(object sender, MouseEventArgs e)
{
Console.WriteLine("2 + 2 = 5");//Will never get here....
}
private void PictureBox_MouseHover(object sender, EventArgs e)
{
thePictureBox.Focus();
}
}
}
It works for me with mouseMove instead of mousehover:
pictureBox1.MouseMove += newEventHandler(this.PictureBox_MouseHover);
Just change the name now from Hover to move so it makes sense:p
In case someone else is looking for the solution.
To make the pictureBox1 fire MouseWheel event I added a MouseEnter event:
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
pictureBox1.Focus();
}
MouseWheel event is center mouse event. You have to scroll center mouse then MouseWheel event will be handled.
thanks to http://www.eqqon.com/index.php/Piccolo_Snippets, i had mousewheel zooming working well until i added winform widgets to the form outside of the canvas; see pic of a test form below:
i found that if i clicked on button1, and moused back onto the canvas, i no longer get mousewheel events. Other mouse events (e.g. PNode entry/leave) still work however. even after clicking on the canvas, the mousewheel is still dead. the canvas's mousedown event works fine also. so only the mousewheel breaks. below is minimalist code to demonstrate what i'm seeing.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using UMD.HCIL.Piccolo;
using UMD.HCIL.Piccolo.Event;
using UMD.HCIL.Piccolo.Nodes;
namespace piccolo_wheel_test {
public partial class Form1 : Form {
int mdown_count = 0;
int mwheel_count = 0;
public Form1() {
InitializeComponent();
PNode rect = PPath.CreateRectangle(40, 40, 20, 50);
rect.Brush = Brushes.Blue;
pCanvas1.Layer.AddChild(rect);
pCanvas1.Camera.MouseWheel += new PInputEventHandler(Camera_MouseWheel);
pCanvas1.Camera.MouseDown += new PInputEventHandler(Camera_MouseDown);
}
void Camera_MouseWheel(object sender, PInputEventArgs e) {
Debug.WriteLine("got mouse wheel: " + (mwheel_count++).ToString());
}
void Camera_MouseDown(object sender, PInputEventArgs e) {
Debug.WriteLine("got mouse down: " + (mdown_count++).ToString());
}
private void pCanvas1_Enter(object sender, EventArgs e) {
Debug.WriteLine("enter pcanvas");
}
private void pCanvas1_Leave(object sender, EventArgs e) {
Debug.WriteLine("leave pcanvas");
}
private void button1_Enter(object sender, EventArgs e) {
Debug.WriteLine("enter button");
}
private void button1_Leave(object sender, EventArgs e) {
Debug.WriteLine("leave button");
}
}
}
as an aside, i see that the canvas does not raise "enter"/"leave" events consistently; i see one "enter" when the form loads and one "leave" if i click button1 but no more "enter"/"leave" if i go back and forth. further, when i click on button1, i raises its "enter" event but when i click back on the canvas, "button1" doesn't raise its "leave" event (which it does if i clicked on other winform widgets, such as the trackbar.) thanks.
So I am just experimenting with drawing images and other things, however it seems that my code only works in the load form event?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Interface_Editing_Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//This works perfectly
/*Image i = Image.FromFile(#"C:\Users\Simon\Pictures\clickedbutton.jpg");
Bitmap b = (Bitmap)panel1.BackgroundImage;
using (Graphics g = Graphics.FromImage(b))
{
g.DrawImage(i, 0, 0, i.Size.Width, i.Size.Height);
}*/
}
private void panel1_Click(object sender, EventArgs e)
{
//Doesnt draw anything, but will show the message box
Image i = Image.FromFile(#"C:\Users\Simon\Pictures\clickedbutton.jpg");
Bitmap b = (Bitmap)panel1.BackgroundImage;
using (Graphics g = Graphics.FromImage(b))
{
//MessageBox.Show(" ");
g.DrawImage(i, 0, 0, i.Size.Width, i.Size.Height);
}
}
}
}
I know it is most likely something simple that I am overlooking but I would appreciate if someone could give me some insight in to whats happening. Thanks
Windows doesn't know that you changed the image. The Image class doesn't have any events that anybody could listen to so it knows that the image was changed. It works in the Load event because the window isn't visible yet, it will get painted right after that. So you can see the changed image. It doesn't work in the Click event handler since the panel is already displayed and has no reason to repaint itself.
Simply let it know that repainting is required. Add this line of code to the bottom of the method:
panel1.Invalidate();
It seems that this is probl;em related to handling click event inside a panel due to different controls inside it.
Make sure that your application handles panel1_click event. (May be through debugger you will come to know it).
Application may not handle this event due to different reasons such as different controls presence on panels,etc.
You can refer Following question having the same issue as you:
Panel events won't work in c#
Handling a click event anywhere inside a panel in C#
This working example might guid you:
private Bitmap _bmp = new Bitmap(250, 250);
public Form1()
{
InitializeComponent();
panel1.Click += new MouseEventHandler(panel1_Click);
panel1.Paint += new PaintEventHandler(panel1_Paint);
using (Graphics g = Graphics.FromImage(_bmp))
g.Clear(SystemColors.Window);
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(_bmp, new Point(0, 0));
}
private void panel1_Click(object sender, MouseEventArgs e)
{
using (Graphics g = Graphics.FromImage(_bmp))
{
g.DrawString("Mouse Clicked Here!", panel1.Font, Brushes.Black, e.Location);
}
panel1.Invalidate();
}