Antworten:
Dieser Artikel über CodeProject beschreibt eine Technik. Im Grunde läuft es darauf hinaus:
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, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
Dies gilt im Wesentlichen genau die gleiche wie die Titelleiste eines Fensters greifen, aus der Sicht des Window - Manager.
Form1_MouseDown
nicht dem tatsächlichen MouseDown
Ereignis von zugewiesen ist Form1
.
this.MouseDown += ...
die Main()
Funktion für das Formular hinzufügen
Machen wir die Dinge nicht schwieriger als nötig. Ich bin auf so viele Codeausschnitte gestoßen, mit denen Sie ein Formular (oder ein anderes Steuerelement) verschieben können. Und viele von ihnen haben ihre eigenen Nachteile / Nebenwirkungen. Insbesondere diejenigen, bei denen Windows zu der Annahme verleitet wird, dass ein Steuerelement in einem Formular das eigentliche Formular ist.
Davon abgesehen ist hier mein Ausschnitt. Ich benutze es die ganze Zeit. Ich möchte auch darauf hinweisen, dass Sie dies nicht verwenden sollten.Invalidate (); wie andere es gerne tun, weil es in einigen Fällen dazu führt, dass die Form flackert. Und in einigen Fällen auch. Aktualisieren. Mit this.Update hatte ich keine flackernden Probleme:
private bool mouseDown;
private Point lastLocation;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
lastLocation = e.Location;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if(mouseDown)
{
this.Location = new Point(
(this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);
this.Update();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
Ein weiterer einfacher Weg, um das Gleiche zu tun.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// set this.FormBorderStyle to None here if needed
// if set to none, make sure you have a way to close the form!
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCHITTEST)
m.Result = (IntPtr)(HT_CAPTION);
}
private const int WM_NCHITTEST = 0x84;
private const int HT_CLIENT = 0x1;
private const int HT_CAPTION = 0x2;
}
Verwenden Sie MouseDown, MouseMove und MouseUp. Sie können dafür ein Variablenflag setzen. Ich habe ein Beispiel, aber ich denke, Sie müssen es überarbeiten.
Ich codiere die Mausaktion in ein Panel. Sobald Sie auf das Bedienfeld klicken, wird Ihr Formular mit verschoben.
//Global variables;
private bool _dragging = false;
private Point _offset;
private Point _start_point=new Point(0,0);
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
_dragging = true; // _dragging is your variable flag
_start_point = new Point(e.X, e.Y);
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
_dragging = false;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(_dragging)
{
Point p = PointToScreen(e.Location);
Location = new Point(p.X - this._start_point.X,p.Y - this._start_point.Y);
}
}
Nur WPF
Ich habe nicht den genauen Code zur Hand, aber in einem kürzlich durchgeführten Projekt habe ich das MouseDown-Ereignis verwendet und einfach Folgendes ausgedrückt:
frmBorderless.DragMove();
Dies ist getestet und leicht zu verstehen.
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);
}
WM_NCHITTEST
in Verkleidung.
Es gibt keine Eigenschaft, die Sie umdrehen können, um dies einfach magisch geschehen zu lassen. Schauen Sie sich die Ereignisse für das Formular an und es wird ziemlich trivial, dies durch Setzen von this.Top
und zu implementieren this.Left
. Insbesondere möchten Sie sich ansehen MouseDown
, MouseUp
und MouseMove
.
public Point mouseLocation;
private void frmInstallDevice_MouseDown(object sender, MouseEventArgs e)
{
mouseLocation = new Point(-e.X, -e.Y);
}
private void frmInstallDevice_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point mousePos = Control.MousePosition;
mousePos.Offset(mouseLocation.X, mouseLocation.Y);
Location = mousePos;
}
}
Dies kann Ihr Problem lösen ....
Dieses Stück Code vom obigen Link hat in meinem Fall den Trick gemacht :)
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
{
this.Capture = false;
Message msg = Message.Create(this.Handle, 0XA1, new IntPtr(2), IntPtr.Zero);
this.WndProc(ref msg);
}
}
Der beste Weg, den ich gefunden habe (natürlich modifiziert)
// This adds the event handler for the control
private void AddDrag(Control Control) { Control.MouseDown += new System.Windows.Forms.MouseEventHandler(this.DragForm_MouseDown); }
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 DragForm_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
// Checks if Y = 0, if so maximize the form
if (this.Location.Y == 0) { this.WindowState = FormWindowState.Maximized; }
}
}
Um Drag auf ein Steuerelement anzuwenden, fügen Sie dies einfach nach InitializeComponent () ein.
AddDrag(NameOfControl);
Es hat bei mir funktioniert.
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
_mouseLoc = e.Location;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int dx = e.Location.X - _mouseLoc.X;
int dy = e.Location.Y - _mouseLoc.Y;
this.Location = new Point(this.Location.X + dx, this.Location.Y + dy);
}
}
Für .NET Framework 4
Sie können this.DragMove()
für das MouseDown
Ereignis der Komponente (in diesem Beispiel mainLayout) verwenden, die Sie zum Ziehen verwenden.
private void mainLayout_MouseDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
Der einfachste Weg ist:
Erstellen Sie zunächst ein Label mit dem Namen label1. Gehen Sie zu den Ereignissen von label1> Mausereignisse> Label1_Mouse Verschieben und schreiben Sie diese:
if (e.Button == MouseButtons.Left){
Left += e.X;
Top += e.Y;`
}
Ich habe versucht, ein randloses Fensterformular beweglich zu machen, das ein WPF-Element-Host-Steuerelement und ein WPF-Benutzersteuerelement enthielt.
Am Ende hatte ich ein Stack-Panel namens StackPanel in meinem WPF-Benutzersteuerelement, das logisch zu versuchen schien, auf zu klicken, um es zu verschieben. Der Versuch, den Code von junmats zu verwenden, funktionierte, wenn ich die Maus langsam bewegte. Wenn ich die Maus jedoch schneller bewegte, bewegte sich die Maus vom Formular weg und das Formular blieb irgendwo in der Mitte der Bewegung hängen.
Dies verbesserte seine Antwort auf meine Situation mit CaptureMouse und ReleaseCaptureMouse, und jetzt bewegt sich die Maus nicht mehr vom Formular weg, während sie es bewegt, selbst wenn ich es schnell bewege.
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
_start_point = e.GetPosition(this);
StackPanel.CaptureMouse();
}
private void StackPanel_MouseUp(object sender, MouseButtonEventArgs e)
{
StackPanel.ReleaseMouseCapture();
}
private void StackPanel_MouseMove(object sender, MouseEventArgs e)
{
if (StackPanel.IsMouseCaptured)
{
var p = _form.GetMousePositionWindowsForms();
_form.Location = new System.Drawing.Point((int)(p.X - this._start_point.X), (int)(p.Y - this._start_point.Y));
}
}
//Global variables;
private Point _start_point = new Point(0, 0);
Da bei einigen Antworten untergeordnete Steuerelemente nicht ziehbar sind, habe ich eine kleine Hilfsklasse erstellt. Es sollte das oberste Formular übergeben werden. Kann auf Wunsch allgemeiner gestaltet werden.
class MouseDragger
{
private readonly Form _form;
private Point _mouseDown;
protected void OnMouseDown(object sender, MouseEventArgs e)
{
_mouseDown = e.Location;
}
protected void OnMouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int dx = e.Location.X - _mouseDown.X;
int dy = e.Location.Y - _mouseDown.Y;
_form.Location = new Point(_form.Location.X + dx, _form.Location.Y + dy);
}
}
public MouseDragger(Form form)
{
_form = form;
MakeDraggable(_form);
}
private void MakeDraggable(Control control)
{
var type = control.GetType();
if (typeof(Button).IsAssignableFrom(type))
{
return;
}
control.MouseDown += OnMouseDown;
control.MouseMove += OnMouseMove;
foreach (Control child in control.Controls)
{
MakeDraggable(child);
}
}
}
Wenn Sie doppelklicken und Ihr Formular vergrößern / verkleinern müssen, können Sie die erste Antwort verwenden, eine globale int-Variable erstellen und jedes Mal 1 hinzufügen, wenn der Benutzer auf die Komponente klickt, die Sie zum Ziehen verwenden. Wenn variable == 2
ja, machen Sie Ihr Formular größer / kleiner. Verwenden Sie auch einen Timer für jede halbe Sekunde oder Sekunde, um Ihre variable = 0
;
Das Hinzufügen eines MouseLeftButtonDown
Ereignishandlers zum MainWindow hat für mich funktioniert.
Fügen Sie in der Ereignisfunktion, die automatisch generiert wird, den folgenden Code hinzu:
base.OnMouseLeftButtonDown(e);
this.DragMove();
Ich erweitere die Lösung von jay_t55 um eine weitere Methode ToolStrip1_MouseLeave
, die das Ereignis behandelt, dass sich die Maus schnell bewegt und die Region verlässt.
private bool mouseDown;
private Point lastLocation;
private void ToolStrip1_MouseDown(object sender, MouseEventArgs e) {
mouseDown = true;
lastLocation = e.Location;
}
private void ToolStrip1_MouseMove(object sender, MouseEventArgs e) {
if (mouseDown) {
this.Location = new Point(
(this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);
this.Update();
}
}
private void ToolStrip1_MouseUp(object sender, MouseEventArgs e) {
mouseDown = false;
}
private void ToolStrip1_MouseLeave(object sender, EventArgs e) {
mouseDown = false;
}
Ich habe folgendes versucht und Presto Changeo, mein transparentes Fenster war nicht mehr eingefroren, sondern konnte verschoben werden !! (werfen Sie all diese anderen komplexen Lösungen oben weg ...)
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// Begin dragging the window
this.DragMove();
}
Form 1(): new Moveable(control1, control2, control3);
Klasse:
using System;
using System.Windows.Forms;
class Moveable
{
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();
public Moveable(params Control[] controls)
{
foreach (var ctrl in controls)
{
ctrl.MouseDown += (s, e) =>
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(ctrl.FindForm().Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
// Checks if Y = 0, if so maximize the form
if (ctrl.FindForm().Location.Y == 0) { ctrl.FindForm().WindowState = FormWindowState.Maximized; }
}
};
}
}
}
[DllImport("user32.DLL", EntryPoint = "ReleaseCapture")]
private extern static void ReleaseCapture();
[DllImport("user32.DLL", EntryPoint = "SendMessage")]
private extern static void SendMessage(System.IntPtr hWnd, int Msg, int wParam, int lParam);
private void panelTitleBar_MouseDown(object sender, MouseEventArgs e)
{
ReleaseCapture();
SendMessage(this.Handle, 0x112, 0xf012, 0);
}