2010-03-05 18 views
6

Özel bir denetim oluşturdum ve kullanıcıların tıpkı pencere başlık çubuğunda sürükleniyormuş gibi kontrolümde tıklatıp sürüklemelerine izin vermek istiyorum. Bunu yapmanın en iyi yolu nedir?Pencere başlık çubuğunun sürüklenmesini simüle eden denetim

Şimdiye kadar, fareyi aşağı yukarı kaldırırken ve pencerenin taşınması gerektiğinde deşifre edilecek olayları gerçekleştirmede başarısız oldum.

cevap

10

benim diğer yanıt yanı sıra, böyle bir Kontrol elle yapabilirsiniz:

Point dragOffset; 

protected override void OnMouseDown(MouseEventArgs e) { 
    base.OnMouseDown(e); 
    if (e.Button == MouseButtons.Left) { 
     dragOffset = this.PointToScreen(e.Location); 
     var formLocation = FindForm().Location; 
     dragOffset.X -= formLocation.X; 
     dragOffset.Y -= formLocation.Y; 
    } 
} 

protected override void OnMouseMove(MouseEventArgs e) { 
    base.OnMouseMove(e); 

    if (e.Button == MouseButtons.Left) { 
     Point newLocation = this.PointToScreen(e.Location); 

     newLocation.X -= dragOffset.X; 
     newLocation.Y -= dragOffset.Y; 

     FindForm().Location = newLocation; 
    } 
} 

EDIT: Test ve sabit - bu artık gerçekten çalışıyor.

+0

Kod için teşekkürler! –

5

Bunu yapmanın en etkili yolu, WM_NCHITTEST bildirimini işlemektir.

formun WndProc yöntemini geçersiz kılın ve aşağıdaki kodu ekleyin

:

if (m.Msg == 0x0084) {    //WM_NCHITTEST 
    var point = new Point((int)m.LParam); 
    if(someRect.Contains(PointToClient(point)) 
     m.Result = new IntPtr(2); //HT_CAPTION 
} 

Ancak, bu noktada bir kontrol varsa mesaj gönderilecektir sanmıyorum.

+0

İlgi duyuyorum ... detaylandırır mısınız? Bu nasıl sorulur? – echo

+0

@echo: Windows'a, formun bu bölümünün sürüklenebilen bir başlık çubuğu olduğunu söyler. Bunun, bu bölümün çift tıklanmasıyla formun en üst düzeye çıkarılmasına da izin vereceğini unutmayın. – SLaks

+0

Hah, düzgün numara, bunu daha önce hiç görmemiştim. Bana neler olduğunu anlayabilmek için bir dakika sürdü! – Aaronaught

3

Eğer formun bir kısmını resim yazısı gibi yapmak istiyorsanız, SLaks'ın verdiği WM_NCHITTEST hilesi gitme yoludur. Ama eğer bir çocuk penceresi yapmak istiyorsanız formu sürükleyebilir ve başka bir yol var.

Temel olarak, bir WM_SYSCOMMAND iletisi MOUSE_MOVE komut kimliği ile DefWindowProc gönderirseniz, Windows sürükleme moduna geçer. Bu temelde altyazı bunu nasıl yapar, ama orta adamı keserek, bu sürüklemeyi bir alt pencereden başlatabiliriz ve diğer tüm altyazı davranışlarını alamayız.

public class form1 : Form 
{ 
    ... 

    [DllImport("user32.dll")] 
    static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, UIntPtr wParam, IntPtr lParam); 
    [DllImport("user32.dll")] 
    static extern bool ReleaseCapture(IntPtr hwnd); 

    const uint WM_SYSCOMMAND = 0x112; 
    const uint MOUSE_MOVE = 0xF012;  

    public void DragMe() 
    { 
    DefWindowProc(this.Handle, WM_SYSCOMMAND, (UIntPtr)MOUSE_MOVE, IntPtr.Zero); 
    } 


    private void button1_MouseDown(object sender, MouseEventArgs e) 
    { 
    Control ctl = sender as Control; 

    // when we get a buttondown message from a button control 
    // the button has capture, we need to release capture so 
    // or DragMe() won't work. 
    ReleaseCapture(ctl.Handle); 

    this.DragMe(); // put the form into mousedrag mode. 
    } 
+0

Bu benim için çalıştı, ancak hiçbir tartışmaya sahip olmamak için ReleaseCapture'ı değiştirmek zorunda kaldım. Bkz. [ReleaseCapture] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646261 (v = vs.85) .aspx) – Erroneous