Cursore della mano non antialias nelle app Windows Form!

Ok, quindi sai come in Windows Vista e Windows 7 MS hai cambiato il Cursore della mano (quello che compare quando passi il mouse su un collegamento ipertestuale), e hai aggiunto più dettagli in modo che sia antialiased e bello e liscio intorno ai bordi?

Bene, perché non è così nelle app di Windows Form?

Sono stufo di guardare un cursore della mano schifoso che sembra disegnato da un uomo delle caverne, c’è un modo per dirlo programmaticamente di visualizzare quello effettivamente installato nel sistema? Ho guardato nella cartella Cursors nella mia directory di Windows, e il cursore della vecchia mano non è nemmeno lì! Quindi, perché WinForms sta ancora utilizzando quello vecchio? Come posso “aggiornarlo”?

Sì, i controlli di WinForm continuano a utilizzare il cursore della vecchia scuola, fornito con Windows 98/2000. Manca l’effetto anti-aliasing che fa quello incluso con i cursori Aero. Questo perché .NET Framework include il proprio cursore hard-coded, che utilizza al posto del sistema predefinito. Presumo che questo sia dovuto al fatto che le prime versioni di .NET riguardavano sistemi operativi come Windows 95 che non erano inclusi in questo cursore, ma non hanno fatto l’archeologia per dimostrarlo.

Fortunatamente, è abbastanza facile costringerlo a usare quello giusto. Devi solo dire al sistema operativo che vuoi che usi il cursore della mano predefinito, e quindi sarà corretto indipendentemente dalla versione di Windows in cui l’utente esegue il tuo programma, e anche se hanno cambiato i loro cursori del mouse dall’impostazione predefinita tema.

Il modo più semplice per farlo è quello di sottoclass il controllo esistente, sovrascrivere la funzione WndProc per intercettare il messaggio WM_SETCURSOR e dirgli di usare il cursore IDC_HAND sistema. Hai solo bisogno di un po ‘di magia P / Invoke.

Il seguente codice è un esempio di come potrebbe apparire utilizzando il controllo LinkLabel :

 public class LinkLabelEx : LinkLabel { private const int WM_SETCURSOR = 0x0020; private const int IDC_HAND = 32649; [DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)] private static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName); [DllImport("user32.dll", CharSet=CharSet.Auto)] private static extern IntPtr SetCursor(IntPtr hCursor); protected override void WndProc(ref Message m) { if (m.Msg == WM_SETCURSOR) { // Set the cursor to use the system hand cursor SetCursor(LoadCursor(IntPtr.Zero, IDC_HAND)); // Indicate that the message has been handled m.Result = IntPtr.Zero; return; } base.WndProc(ref m); } } 

Mi scusi per aver risuscitato un thread di un anno !!!

Dopo aver risolto il problema con la soluzione originale e dando un’occhiata al codice sorgente LinkLabel riflesso , ho “finalmente” trovato un modo rapido e pulito per farlo:

 using System.Runtime.InteropServices; namespace System.Windows.Forms { public class LinkLabelEx : LinkLabel { private const int IDC_HAND = 32649; [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName); private static readonly Cursor SystemHandCursor = new Cursor(LoadCursor(IntPtr.Zero, IDC_HAND)); protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); // If the base class decided to show the ugly hand cursor if(OverrideCursor == Cursors.Hand) { // Show the system hand cursor instead OverrideCursor = SystemHandCursor; } } } } 

Questa class fa effettivamente ciò che vogliamo: mostra il cursore della mano di sistema corretto senza sfarfallio e lo fa solo sul LinkArea del controllo.