Windows Presentation Foundation offre un completo supporto per il mouse: hit testing, routed event al click, posizione rispetto agli elementi, argomenti completi nella sollevazione di eventi, ecc … Però nel suo supporto ha una mancanza: non si ha un modo diretto per conoscere la posizione assoluta del puntatore!

Non è quindi possibile ottenere la posizione assoluta del puntatore sul monitor (WPF non permette di conoscere le coordinate assolute del mouse, ma solo relative rispetto ad un altro elemento) e, come ulteriore problema nel passaggio da .NET 2.0 a .NET 3.5, è cambiata la gestione degli eventi di movimento del mouse e posizione: se in .NET 2.0 la chiamata a Cursor.GetPosition(…) restituisce la posizione del mouse rispetto ad uno specifico componente, in .NET 3.5 questa restituisce sempre la posizione del mouse rispetto al componente, ma legata agli estremi.

Per esempio, dato un componente un componente lontano 100 pixel sull’asse X del monitor, con una larghezza di 200 pixel e con il mouse in posizione assoluta 500 pixel lungo l’asse X, in .NET 2.0 Cursor.GetPosition(…) restituirà una posizione relativa di 400 pixel, mentre in .NET 3.5 di 200 pixel! La soluzione definitiva a questo problema è effettuare una chiamata diretta alla funzione GetCursorPos presente in user32.dll e scavalcare così il framework .NET.

Ecco quindi il codice risolutivo:

[DllImport(“user32.dll”)]

[return: MarshalAs(UnmanagedType.Bool)]

private static extern bool GetCursorPos(out PointAPI lpPoint);

Per poterlo utilizzare avremo bisogno della seguente struttura:

struct PointAPI

{

public int X;

public int Y;

}

Un esempio di utilizzo può essere attaccare un elemento grafico al mouse (nell’esempio il metodo è stato aggiunto ad una classe Window ad hoc):

public void AdjustLocation()

{

PointAPI p = new PointAPI();

GetCursorPos(out p);

this.Left = p.X;

this.Top = p.Y;

}

Nell’esempio il metodo non fa altro che attaccare l’oggetto finestra al puntatore del mouse. La finestra in questione può contenere ad esempio informazioni su un’eventuale operazione di Drag & Drop in corso, come anche un metodo personalizzato per visualizzare i ToolTip, da questo punto di vista WPF permette una libertà assoluta.

Si ricorda che comunque il metodo AdjustLocation() deve essere chiamato per ogni spostamento del mouse, nel caso del Drag & Drop suggerito precedentemente il risultato è facilmente ottenibile facendo l’overload di OnGiveFeedBack(…), ovviamente per ogni utilizzo bisogna adattare una nuova soluzione!

Per il codice è stato preso spunto da questo articolo.