I'm looking for a way to move the form by using a menustrip.
Although there are a few solutions around, there is a particular problem with them which I don't like. In order for those methods to work the form needs to be already focused before dragging the menustrip.
Is there a way of fixing that particular issue so the menustrip will actually behave like a proper windows title bar ?
The best bet is to use pinvoke. Tie the "mousedown" event to which ever control you want to be dragable.
using System.Runtime.InteropServices;
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
private static extern int SendMessage(IntPtr hWnd,
int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
private static extern bool ReleaseCapture();
public Form1()
{
InitializeComponent();
}
private void menuStrip1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
This still require the form to be focused, but you can work around using mouse hover. It is not that elegant but it works.
private void menuStrip1_MouseHover(object sender, EventArgs e)
{
Focus();
}
Update: Hover has a slight delay, mousemove is much more responsive
private void menuStrip1_MouseMove(object sender, MouseEventArgs e)
{
if (!Focused)
{
Focus();
}
}
Related
not sure i explained it well in the title;
if youre on windows, click and drag on the title bar of FireFox/Chrome/other application and drag it to the top or side of the screen. it creates a weird effect and when u release the capture, depending on where you dragged it, it will either maximize or split the screen.
when i use App.FormBorderStyle = FormBorderStyle.None; it doesnt give me the split/max effect when i drag it to top. i have enabled drag by:
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool ReleaseCapture();
// this is the panel i use as a title bar for dragging
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
now, how can i enable this feature of dragging to the top of screen and having windows display the effect of max/split.
thank you.
Maybe you can try to achieve them by determining the location of the form based on Location.X and Location.Y .
Here is a demo you can refer to.
public Form1()
{
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
}
// Save original size
Size original;
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool ReleaseCapture();
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
// Drag to top to maximize
if (this.Location.Y <= 0)
{
this.WindowState = FormWindowState.Maximized;
}
else
{
this.Size = original;
}
// Drag to side to split screen
if (this.Location.X <= 0)
{
this.Location = new Point(0, 0);
this.Size = new Size(SystemInformation.WorkingArea.Width / 2, SystemInformation.WorkingArea.Height);
}
else if (this.Location.X >= SystemInformation.WorkingArea.Width / 2)
{
this.Location = new Point(SystemInformation.WorkingArea.Width / 2, 0);
this.Size = new Size(SystemInformation.WorkingArea.Width / 2, SystemInformation.WorkingArea.Height);
}
else
{
this.Size = original;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
original = this.Size;
}
I've made a circle shaped movable form using the code in the following link
Make a borderless form movable?
this Code:
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
Now my form is moving as I wanted but I want to add a click event to that form, but click event isn't firing. Can anyone tell what I'm missing?
Note: I just want to call a function whenever someone clicks my form.
You can use the MouseMove method instead of the MouseDown method:
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left) {
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
protected override void OnClick(EventArgs e) {
base.OnClick(e);
MessageBox.Show("Clicked");
}
A form does not have to listen to their own events, so I am just overriding the MouseMove and Click procedures in the code above.
I have a windows form without title bar. I want to drag it by mouse. After searching on internet, I found this code for moving form:
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x84:
base.WndProc(ref m);
if ((int)m.Result == 0x1)
m.Result = (IntPtr)0x2;
return;
}
base.WndProc(ref m);
}
But it has a problem: It operates only on form regions which are not covered by any control. For example if I use label or group box, I can't move form by clicking on them.
How can I solve this problem?
One way is to implement IMessageFilter like this.
public class MyForm : Form, IMessageFilter
{
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
public const int WM_LBUTTONDOWN = 0x0201;
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
private HashSet<Control> controlsToMove = new HashSet<Control>();
public MyForm()
{
Application.AddMessageFilter(this);
controlsToMove.Add(this);
controlsToMove.Add(this.myLabel);//Add whatever controls here you want to move the form when it is clicked and dragged
}
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_LBUTTONDOWN &&
controlsToMove.Contains(Control.FromHandle(m.HWnd)))
{
ReleaseCapture();
SendMessage(this.Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
return true;
}
return false;
}
}
This is basically what you are looking to do:
Make a borderless form movable?
You might be able to add the same code to the mouse down event of other controls on your form to accomplish the same thing.
Make a borderless form movable?
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
When the user presses the mouse down over the lblMoveForm Label in the form, the following event handler executes.
// On left button, let the user drag the form.
private void lblMoveForm_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// Release the mouse capture started by the mouse down.
lblMoveForm.Capture = false; //select control
// Create and send a WM_NCLBUTTONDOWN message.
const int WM_NCLBUTTONDOWN = 0x00A1;
const int HTCAPTION = 2;
Message msg =
Message.Create(this.Handle, WM_NCLBUTTONDOWN,
new IntPtr(HTCAPTION), IntPtr.Zero);
this.DefWndProc(ref msg);
}
}
//For base form moving
private const int HT_CAPTION = 0x2;
private const int WM_NCHITTEST = 0x84;
private const int HT_CLIENT = 0x1;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCHITTEST)
m.Result = (IntPtr)(HT_CAPTION);
}
//For any component you also want use to move form
private bool arrastando= false;
private Point pontoinicial= new Point(0,0);
private Point meu_offset;
//use this method for component event called MouseDown
private void dragMouseDown(object sender, MouseEventArgs e)
{
arrastando = true;
pontoinicial = new Point(e.X, e.Y);
}
//use this method for component event called MouseUp
private void dragMouseUp(object sender, MouseEventArgs e)
{
arrastando=false;
}
//use this method for component event called MouseMove
private void dragMouseMove(object sender, MouseEventArgs e)
{
if (arrastando)
{
Point p = PointToScreen(e.Location);
ActiveForm.Location = new Point(p.X - this.pontoinicial.X,
p.Y - this.pontoinicial.Y);
}
}
I have a WinForms project. I have a panel on the top of my window. I want that panel to be able to move the window, when the user clicks on it and then drags.
How can I do this?
Add the following declerations to your class:
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
Put this in your panel's MouseDown event:
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
}
I have this System.Windows.Forms.Panel that I want to enable so that if the user click and drags the mouse drags the window around to.
Can I do this? Do i have to implement multiple events?
The Solution that works best for me is using unmanaged code, which gives you smooth window movements unlike the answer posted by HatSoft.
3 small steps to drag your window on Panel movement
using System.Runtime.InteropServices;
add these six lines inside your class
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
and your MouseMove event on Panel should look like this
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
posted it a little late :) , who knows we might need it again in future.
You can achieve it by using the MouseMove Event of the panel
Example should be something like this (Sorry have not tested it)
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Location = new Point(Cursor.Position.X + e.X , Cursor.Position.Y + e.Y);
}
}
You might want to take a look at this component that I pasted here:
http://pastebin.com/5ufJmuay
It is a component that you will be able to drop on a form, and then drag the form by dragging inside it.
Currently Set For A Panel. VS C# Just Messing About Seems to work for me as I wanted
Sets application left-top corner to mouse position while left-click is pressed.
public form1()
{
InitializeComponent();
this.panel2.MouseMove += new MouseEventHandler(panel2_MouseMove);
}
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point loc1 = MousePosition;
this.Location = loc1;
}
}
Hey Hope this works for you
First you have to put a panel on your form and dock it to top
Then add these lines of codes
using System.Runtime.InteropServices;
public partial class Main_FM : Form
{
[DllImport("user32.dll", EntryPoint = "ReleaseCapture")]
private extern static void ReleaseCapture();
[DllImport("user32.dll", EntryPoint = "SendMessage")]
private extern static void SendMessge(System.IntPtr hwnd, int wmsg, int wparam, int lparam);
}
The create the MouseDown event on the panel and add these codes:
private void Top_PNL_MouseDown(object sender, MouseEventArgs e)
{
ReleaseCapture();
SendMessge(this.Handle, 0x112, 0xf012, 0);
}
Bravo's code works perfectly fine but I couldn't get this working until i explicitly made MouseMove event enable in panel's->properties->event section of my panel i wanted to move.