2008-08-26 11 views
15

Sürükle ve bırak işleminin tamamlanamamasından sonra, MouseUp olayının çerçeve tarafından yok edilmediğinden ve yok sayıldığından emin olmanın kolay bir yolu var mı?DoDragDrop ve MouseUp

one mechanism belgesini açıklayan bir blog yazısı buldum, ancak durum bayrakları, MouseMove olayları, manuel "fare izni" denetimi dahil olmak üzere manuel defter tutma işlemlerinin iyi bir şekilde yapılmasını içerir. önlenebilir.

+0

argh, ben de bu problemle karşılaştım. Bana sorarsan çok sinir bozucu! –

cevap

20

Son zamanlarda projemde Sürükle ve Bırak işlevini kullanmak istemiştim ve bu konuya rastlamamıştım, ancak merak ettim ve gerçekten de anlatılandan daha iyi bir yöntemle gelip gelemeyeceğimi görmek istedim. bağlandığınız sayfa. Umarım yapmak istediğin her şeyi açıkça anladım ve genel olarak problemi daha zarif ve basit bir şekilde çözmeyi başarabildiğimi düşünüyorum.

Hızlı bir yan notta, böyle bir sorun varsa, bazı kodları sağlamanız harika olur, böylece ne yapmaya çalıştığınızı tam olarak görürüz. Bunu sadece çözümümdeki kodunuzla ilgili birkaç şey üstlendiğim için söylüyorum ... yani umarım oldukça yakındır.

İşte aşağıda açıklayacağım kodu verilmiştir:

this.LabelDrag.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.LabelDrag_QueryContinueDrag); 
this.LabelDrag.MouseDown += new System.Windows.Forms.MouseEventHandler(this.LabelDrag_MouseDown); 
this.LabelDrag.MouseUp += new System.Windows.Forms.MouseEventHandler(this.LabelDrag_MouseUp); 

this.LabelDrop.DragDrop += new System.Windows.Forms.DragEventHandler(this.LabelDrop_DragDrop); 
this.LabelDrop.DragEnter += new System.Windows.Forms.DragEventHandler(this.LabelMain_DragEnter); 

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void LabelDrop_DragDrop(object sender, DragEventArgs e) 
    { 
     LabelDrop.Text = e.Data.GetData(DataFormats.Text).ToString(); 
    } 


    private void LabelMain_DragEnter(object sender, DragEventArgs e) 
    { 
     if (e.Data.GetDataPresent(DataFormats.Text)) 
      e.Effect = DragDropEffects.Copy; 
     else 
      e.Effect = DragDropEffects.None; 

    } 

    private void LabelDrag_MouseDown(object sender, MouseEventArgs e) 
    { 
     //EXTREMELY IMPORTANT - MUST CALL LabelDrag's DoDragDrop method!! 
     //Calling the Form's DoDragDrop WILL NOT allow QueryContinueDrag to fire! 
     ((Label)sender).DoDragDrop(TextMain.Text, DragDropEffects.Copy); 
    } 

    private void LabelDrag_MouseUp(object sender, MouseEventArgs e) 
    { 
     LabelDrop.Text = "LabelDrag_MouseUp"; 
    } 

    private void LabelDrag_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) 
    { 
     //Get rect of LabelDrop 
     Rectangle rect = new Rectangle(LabelDrop.Location, new Size(LabelDrop.Width, LabelDrop.Height)); 

     //If the left mouse button is up and the mouse is not currently over LabelDrop 
     if (Control.MouseButtons != MouseButtons.Left && !rect.Contains(PointToClient(Control.MousePosition))) 
     { 
      //Cancel the DragDrop Action 
      e.Action = DragAction.Cancel; 
      //Manually fire the MouseUp event 
      LabelDrag_MouseUp(sender, new MouseEventArgs(Control.MouseButtons, 0, Control.MousePosition.X, Control.MousePosition.Y, 0)); 
     } 
    } 

} 

Ben tasarımcı kod çoğu bırakmış, ama ne var bağlıdır emin olabilirsiniz kod Olay işleyicisi bağlantısını yukarı dahil. Örneğimde, LabelDrag ve LabelDrop etiketleri arasında sürükleme/bırakma gerçekleşiyor.

Çözümümün ana parçası QueryContinueDrag olayını kullanıyor. Bu olay, DoDragDrop'un bu denetime çağrılmasının ardından klavye veya fare durumu değiştiğinde tetiklenir. Bunu zaten yapıyor olabilirsiniz, ancak kaynağınız olan denetimin DoDragDrop yöntemini çağırmanız ve formla ilişkili yöntemi değil. Aksi takdirde QueryContinueDrag ateş etmeyecektir! Unutulmaması gereken

Bir şey damla kontrolü fareyi bıraktığınızda QueryContinueDrag aslında bu yüzden biz bunun için izin verdiğinden emin olmak gerekir yangın olmasıdır. Bu, Fare konumunu (genel Control.MousePosition özelliği ile alınan) LabelDrop denetim dikdörtgeninin içinde olduğunu kontrol ederek işlenir. Ayrıca, MousePosition'ı PointToClient ile Denetim Penceresi olarak İstemci Penceresine göre bir noktaya dönüştürdüğünüzden emin olmalısınız.MousePosition bir ekran göreli konumunu döndürür.

Yani fare damla kontrolü üzerinde değil olduğunu kontrol ederek ve o fare düğmesi artık etkili bir LabelDrag kontrolü için bir MouseUp olayı ele geçirdi kadar olduğunu! :) Şimdi, sadece burada yapmak istediğiniz işlemi yapabilirdiniz, ancak zaten MouseUp olay işleyicisinde kullandığınız kodunuz varsa, bu verimli değildir. Bu yüzden, buradan MouseUp olayınızı arayın, gerekli parametreleri geçirin ve MouseUp işleyicisi farkı asla bilmeyecektir. gerçi sadece bir not

, benim örnekte içinde den MouseDown olay işleyicisi DoDragDrop dediğimiz gibi, bu kod aslında doğrudan MouseUp olayı ateşe olsun asla. Bunu yapmak için mümkün olduğunu göstermek için o kodu koydum.

Bu yardımcı olur umarım!

+0

çözümünüzden çok şey öğrendiniz! teşekkürler! –

+1

Fikir harika, teşekkürler!Ama sanırım if ifadeniz şöyle görünmelidir (düğme formdan başka bir şey olabilir, sahte olmayan bir şeyden kurtulmuş olabilir): (Control.MouseButtons! = MouseButtons.Left && rect.Contains (button.Parent.PointToClient (Control) .MousePosition))) – colithium

+0

'// ÇOK ÖNEMLİ - LabelDrag'ın DoDragDrop yöntemini çağırması GEREKİR !!' Çok teşekkür ederim! Bunu saatlerce anlamaya çalışıyorum. – Dan