Yanıtlar:
CodeProject hakkındaki bu makale bir tekniği detaylandırmaktadır. Temelde şu şekilde özetlenebilir:
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);
}
}
Bu , pencere yöneticisinin bakış açısından, bir pencerenin başlık çubuğunu almakla tam olarak aynı şeyi yapar .
Form1_MouseDown
, gerçek MouseDown
olayına atanmadığı için çalışmaz Form1
.
this.MouseDown += ...
için Main()
işleve eklemeniz gerekiyor
İşleri olması gerekenden daha zor hale getirmeyelim. Bir formu (veya başka bir Kontrolü) sürüklemenize izin veren çok sayıda kod parçacığı ile karşılaştım. Ve birçoğunun kendi dezavantajları / yan etkileri vardır. Özellikle Windows'u bir form üzerindeki Kontrolün gerçek form olduğunu düşünmesi için kandırdıkları kişiler.
Olduğu söyleniyor, işte benim pasajım. Ben her zaman kullanırım. Ayrıca bunu kullanmamanız gerektiğini de not etmek isterim.Invalidate (); Bazı durumlarda formun titremesine neden olduğu için diğerleri yapmaktan hoşlanır. Ve bazı durumlarda bunu yapar. Bunu kullanarak Güncelle, titreyen herhangi bir sorun yaşamadım:
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;
}
Aynı şeyi yapmanın başka bir basit yolu.
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;
}
MouseDown, MouseMove ve MouseUp'ı kullanın. Bunun için değişken bir bayrak ayarlayabilirsiniz. Bir örneğim var, ama revize etmeniz gerektiğini düşünüyorum.
Fare eylemini bir panele kodluyorum. Paneli tıkladığınızda, formunuz onunla birlikte hareket edecektir.
//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);
}
}
Yalnızca WPF
Elde edilecek tam kod yok, ancak son projede MouseDown olayını kullandığımı ve basitçe şunu koyduğumu düşünüyorum:
frmBorderless.DragMove();
Bu test edilmiştir ve anlaşılması kolaydır.
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
kılık değiştirmiş.
Bunun sihirli bir şekilde gerçekleşmesi için çevirebileceğiniz hiçbir özellik yok. Form için olaylara bakın ve bunu this.Top
ve ayarlayarak uygulamak oldukça önemsiz hale geliyor this.Left
. Özellikle bakmak isteyeceksiniz MouseDown
, MouseUp
ve 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;
}
}
bu senin problemini çözebilir ....
Yukarıdaki bağlantıdaki bu kod parçası benim durumumda hile yaptı :)
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);
}
}
Bulduğum en iyi yol (elbette değiştirildi)
// 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; }
}
}
Bir kontrole sürükleme uygulamak için bunu InitializeComponent () sonrasına eklemeniz yeterlidir.
AddDrag(NameOfControl);
Benim için çalıştı.
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);
}
}
.NET Framework 4 için,
Sürüklemek için kullandığınız bileşenin (bu örnekte mainLayout) olayı this.DragMove()
için kullanabilirsiniz MouseDown
.
private void mainLayout_MouseDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
En kolay yol:
Önce label1 adında bir etiket oluşturun. Label1 olayları> mouse olayları> Label1_Mouse Move seçeneğine gidin ve şunları yazın:
if (e.Button == MouseButtons.Left){
Left += e.X;
Top += e.Y;`
}
Bir WPF Element Host kontrolü ve bir WPF Kullanıcı kontrolü içeren hareketli bir kenarlıksız pencere formu oluşturmaya çalışıyordum.
WPF kullanıcı kontrolümde StackPanel adında bir yığın paneli buldum, bu da hareket etmek için tıklamayı denemek için mantıklı bir şey gibi görünüyordu. Fareyi yavaşça hareket ettirdiğimde junmats kodunu denemek işe yaradı, ancak fareyi daha hızlı hareket ettirirsem, fare formdan çıkacak ve form, hareketin ortasında bir yere sıkışacaktı.
Bu, CaptureMouse ve ReleaseCaptureMouse kullanarak durumum için verdiği yanıtta gelişti ve şimdi hızlı hareket etsem bile fare, onu hareket ettirirken formdan çıkmıyor.
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);
Bazı cevaplar çocuk kontrollerinin sürüklenebilir olmasına izin vermediğinden, küçük bir yardımcı sınıf oluşturdum. Üst düzey formdan geçilmelidir. İstenirse daha jenerik yapılabilir.
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);
}
}
}
Ayrıca DoubleClick'e ihtiyacınız varsa ve Formunuzu büyütmeniz / küçültmeniz gerekiyorsa, İlk yanıtı kullanabilir, bir global int değişkeni oluşturabilir, kullanıcı sürüklemek için kullandığınız bileşene her tıkladığında 1 ekleyebilirsiniz. Eğer variable == 2
o zaman daha küçük / formunuz büyük yapmak. Ayrıca, her yarım saniye veya saniyede bir zamanlayıcı kullanarak variable = 0
;
MouseLeftButtonDown
MainWindow'a bir olay işleyicisi eklemek benim için çalıştı.
Otomatik olarak oluşturulan olay işlevinde aşağıdaki kodu ekleyin:
base.OnMouseLeftButtonDown(e);
this.DragMove();
Jay_t55'teki çözümü ToolStrip1_MouseLeave
, farenin hızlı hareket etmesi ve bölgeden ayrılması olayını işleyen bir yöntemle genişletiyorum .
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;
}
Aşağıdakini denedim ve değiştirmeye çalıştım, şeffaf pencerem artık yerinde donmuştu ama hareket ettirilebilirdi !! (yukarıdaki diğer tüm karmaşık çözümleri atın ...)
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
// Begin dragging the window
this.DragMove();
}
Form1 (): new Moveable(control1, control2, control3);
Sınıf:
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);
}