J'écris une application .Net WPF qui permet à d'autres programmes d'y écrire. L'une des fonctionnalités que les concepteurs veulent implémenter est un curseur personnalisé qui est utilisé dans les programmes tiers pour remplacer l'éditeur de texte "I-Beam".Bas niveau Réglage du curseur système sur personnalisé dans .Net Office Interop
Le premier programme tiers avec lequel j'ai joué est MS Word 2013, en utilisant Office Interop de .Net. J'ai une DLL C# globale dans le domaine d'application de mon programme qui contient la ressource de curseur.
Interop ne vous permet pas d'attribuer des curseurs personnalisés (bien que cela vous permette de changer de curseur). Donc, après beaucoup de creuser, j'ai essayé de déconner.
Dans l'Interop Addin, j'ai ajouté cette classe:
public static class CursorHook
{
private static IntPtr programCursor = IntPtr.Zero;
private static IntPtr systemCursor = LoadCursor(IntPtr.Zero, OCR_IBEAM);
public static void Init()
{
programCursor = Marshal.AllocHGlobal(resourceCursor.marker_cursor2.Length);
Marshal.Copy(resourceCursor.marker_cursor2, 0, programCursor, resourceCursor.marker_cursor2.Length);
}
public static void Start()
{
SetSystemCursor(programCursor, OCR_IBEAM);
}
public static void Stop()
{
SetSystemCursor(systemCursor, OCR_IBEAM);
}
public static void Dispose()
{
Marshal.FreeHGlobal(programCursor);
}
private static IntPtr _hookID = IntPtr.Zero;
private const int OCR_IBEAM = 32513;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetSystemCursor(IntPtr hCursor, uint id);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadCursor(IntPtr hInstance, int id);
[DllImport("user32.dll")]
private static extern IntPtr SetCursor(IntPtr hCursor);
}
Dans ma classe Addin, je fais ceci:
public partial class ThisAddIn
{
//Stuff
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
CursorHook.Init();
CursorHook.Start();
this.Application.WindowDeactivate += new WordInterop.ApplicationEvents4_WindowDeactivateEventHandler(Deactivated);
this.Application.WindowActivate += new WordInterop.ApplicationEvents4_WindowActivateEventHandler(Activated);
//Stuff
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
CursorHook.Stop();
CursorHook.Dispose();
}
//stuff
private void Activated(WordInterop.Document Doc, WordInterop.Window Wn) { CursorHook.Start(); }
private void Deactivated(WordInterop.Document Doc, WordInterop.Window Wn) { CursorHook.Stop(); }
//stuff
}
Cependant, le curseur ne change pas (même si le code est appelé). Qu'est-ce que je rate? Par ailleurs, je comprends mieux la façon dont une classe statique peut ne pas être la meilleure utilisation des ressources. Mais en ce moment, j'essaie juste d'amener le curseur à faire ce que je veux, je vais travailler sur l'élégance après que cela soit accompli.
Merci d'avance!
EDIT
J'ai modifié le code pour ressembler à ceci:
public static class CursorHook
{
private static IntPtr ptr_IBeam = IntPtr.Zero;
private static IntPtr programCursor = IntPtr.Zero;
private static IntPtr systemCursor = IntPtr.Zero;
private static Cursor ProgramCursor = null;
public static void Init()
{
using(MemoryStream ms = new MemoryStream(resourceCursor.marker_cursor2))
{
ProgramCursor = new Cursor(ms);
}
programCursor = ProgramCursor.Handle;
systemCursor = Cursors.IBeam.CopyHandle();
}
public static void Start()
{
SetSystemCursor(programCursor, UNS_OCR_IBEAM);
}
public static void Stop()
{
SetSystemCursor(systemCursor, UNS_OCR_IBEAM);
}
public static void Dispose()
{
}
private const int OCR_IBEAM = 32513;
private const uint UNS_OCR_IBEAM = OCR_IBEAM;
private static IntPtr PTR_OCR_IBEAM = new IntPtr(OCR_IBEAM);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool SetSystemCursor(IntPtr hCursor, uint id);
}
Il est maintenant beaucoup plus simple tout autour, en grande partie grâce au commentaire de HansPassant ci-dessous. Cela fonctionne un peu, maintenant, aussi!
Pourtant, il y a encore deux bogues.
1) L'icône n'est pas en couleur. Je sais que c'est un problème avec les icônes personnalisées et il existe des solutions de contournement, donc je vais faire des recherches moi-même.
Ce qui m'a bloqué: 2) L'icône tournera à mon icône personnalisée sur la Parole d'ouverture, et revenir à la valeur par défaut d'un en cliquant en dehors de Word. Mais ensuite, il refusera de revenir à mon icône après cela. SetSystemCursor() retournera faux chaque fois que j'activerai MS Word. Pourquoi?
Il est sûr de supposer que la fenêtre cible gère le [WM_SETCURSOR] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms648382.aspx), mettre son propre curseur à sa guise, annulant ainsi votre tentative naïve de changer la forme du curseur. – IInspectable
Sauf que j'essaie de changer le curseur SYSTEM, peu importe ce que fait la fenêtre cible. – Moe45673
Cela suppose que la fenêtre cible utilise le curseur SYSTEM. – IInspectable