2013-03-10 19 views
8

Ho un metodo Drag() sull'evento form_MouseDown. Ho anche un evento click sul modulo. Il problema è che se faccio clic sul modulo, l'evento MouseDown viene attivato e non ha mai la possibilità di attivare l'evento click.MouseDown e conflitto Click

Qual è il modo migliore per risolvere questo problema? Stavo pensando di contare i pixel se il modulo è stato effettivamente trascinato, ma deve esserci un modo migliore. Eventuali suggerimenti?

+0

"contare pixel" è abbastanza comune, perché nella maggior parte dei casi che in realtà ** ** non si desidera la resistenza al fuoco quando il la "distanza di movimento" è più corta rispetto, ad esempio, a 7,15 pixel. Anche il desktop di Windows ha una soglia di pochi pixel. – quetzalcoatl

+2

Non utilizzare 'Click', e invece usare' MouseUp'? – Neolisk

+0

Ho creato una demo e non sto ottenendo questo comportamento. Dopo aver raggiunto MouseDown, viene raggiunto. Puoi pubblicare del codice? –

risposta

2

Stavo pensando di contare i pixel se il modulo è in realtà trascinato, ma deve esserci un modo migliore.

No, è esattamente come devi farlo.

Questa non è solo una limitazione del software; è anche molto pratico. Se pensate al problema dal punto di vista dell'utente, vedrete immediatamente il problema e la soluzione. Chiediti, qual è la differenza tra un clic e un trascinamento?

Entrambi iniziano con il pulsante del mouse che scende sopra l'oggetto, ma uno di essi termina con il pulsante del mouse che torna sopra l'oggetto nella stessa posizione e l'altro termina con il pulsante del mouse che risale in una posizione completamente diversa.

Dal momento che le macchine del tempo non sono ancora state perfezionate, non si ha modo di saperlo in anticipo.

Quindi sì, è necessario mantenere una sorta di soglia di distanza, e se il puntatore si muove al di fuori di tale soglia di distanza mentre è giù sull'oggetto, allora si considera un trascinamento. Altrimenti, lo consideri un clic.

Tale soglia di distanza non deve essere 0. L'utente non deve essere tenuto a tenere il mouse completamente immobile per iniziare un trascinamento. Molti utenti sono meno esperti. È molto probabile che si contraggano leggermente quando si tenta di fare clic. Se la soglia è 0, finiranno per fare un sacco di trascinamento involontario quando provano a fare clic.

Ovviamente, non devi preoccuparti di nulla di tutto questo né calcolare la soglia di trascinamento.Utilizzare invece i valori predefiniti di Windows, ottenibili chiamando la funzione GetSystemMetrics e specificando SM_CXDRAG o SM_CYDRAG. (Questi potrebbero essere esposti da qualche parte dal quadro WinForms, ma io non la penso così. E 'altrettanto facile P/Invoke da soli.)

const int SM_CXDRAG = 68; 
const int SM_CYDRAG = 69; 
[DllImport("user32.dll")] 
static extern int GetSystemMetrics(int index); 

Point GetDragThreshold() 
{ 
    return new Point(GetSystemMetrics(SM_CXDRAG), GetSystemMetrics(SM_CYDRAG)); 
} 
+0

Anche se qui ci sono dei buoni punti, il programma dovrebbe essere progettato in modo che il trascinamento di qualsiasi parte di 5px sul lato non provochi nulla. Altrimenti non lo saprai mai, forse la scossa di 5px non è sufficiente per alcune persone per eseguire un clic e hanno bisogno di 10px. Con una corretta implementazione, il movimento del mouse è irrilevante. Ad esempio, se drap e rilascia il file su se stesso in Windows, non succede nulla. – Neolisk

+0

Immagina di creare il designer WinForms. Anche se correttamente implementato, il movimento del mouse è ancora rilevante. È un design completamente diverso da quello di Windows Explorer in cui non ha senso lasciare cadere un'icona su se stesso. Ma puoi certamente trascinare un controllo di alcuni pixel in qualsiasi direzione. O una selezione in un editor di foto. O qualsiasi numero di altri casi in cui la regola della "corretta implementazione" non funzionerà. –

+0

In questi casi si usa il posizionamento della tastiera (tasti freccia). Fa esattamente questo: muoverti nella direzione designata di 1 pixel. Altrimenti si vorrebbe, ad esempio in VS, che il controllo si attacchi a una griglia o ad altri controlli. In entrambi i casi, VS ti aiuterà con il posizionamento. In Photoshop o Paint puoi 1) utilizzare i tasti freccia o 2) farlo scorrere verso il basso fino al punto in cui lo spostamento di diversi pixel in entrambe le direzioni diventa irrilevante. – Neolisk

2

Purtroppo, nel momento in cui "il pulsante è premuto" non si sa ancora se l'azione desiderata è solo un clic o un trascinamento. Lo scoprirete successivamente.

Per un clic, il determinante è "nessun movimento" e "pulsante su".

Per un trascinamento, il determinante è "movimento" e "pulsante su".

Quindi, per disambiguare quelle interazioni, devi tracciare non solo i pulsanti, ma anche il movimento. Non è necessario tenere traccia del movimento generale, ma è interessante solo il movimento tra pulsante giù e abbottonatura.

Tali eventi sono quindi un buon punto di partenza/fermare i meccanismi Mouse.Capture (dinamicamente presente adorners trascinamento posizione e goccia accenna), o, in forma più semplice - per immagazzinare l'origine e la destinazione del movimento vector e controlla se la distanza è> D (anche se si è verificato un movimento, dovrebbe esserci qualche distanza minima sicura all'interno della quale il DRAG è cancellato.Il mouse è "jaggy" a volte, e la gente non gradirebbe davvero che la tua app iniziasse a trascinare quando si fa doppio clic alla fine del movimento rapido del puntatore del mouse :))

2

ho trovato questa soluzione, anche se è per un doppio clicca e un mouse verso il basso gli eventi:

void pictureBox_MouseDown(object sender, MouseEventArgs e) 
{ 
if (e.Button == MouseButtons.Left && e.Clicks ==1) 
{ 
PictureBox pb = (PictureBox)sender; 
DoDragDrop((ImageData)pb.Tag, DragDropEffects.Copy); 
} 
} 

fonte: http://code.rawlinson.us/2007/04/c-dragdrop-and-doubleclick.html