2017-02-06 74 views
0

我在写一个.Net WPF应用程序,允许其他程序写入它。设计人员想要实现的功能之一是在第三方程序中使用的自定义光标来代替文本编辑器“I-Beam”。低级别将系统光标设置为在.Net Office Interop中自定义

我一直在搞的第一个第三方程序是MS Word 2013,使用.Net的Office Interop的东西。我在我的程序的应用程序域中有一个全局C#DLL,用于保存游标资源。

Interop不允许您分配自定义游标(尽管它允许您切换光标)。所以在经过大量的挖掘之后,我尝试了一些低级别的东西。

在互操作加载项,我加入这个类:

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); 


} 

在我的插件类,我这样做:

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 

} 

然而,光标不会改变(即使代码叫做)。我错过了什么?

顺便说一句,我了解有关如何静态类可能不是最好的资源使用的更大的图片。但现在,我只是想让游标做我想做的事情,在完成之后我会继续努力。

在此先感谢!

编辑

我已经修改了代码,如下所示:

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); 




} 

现在就简单多了周围的一切,在很大程度上要归功于以下HansPassant的评论。它现在实际上也有些作用,现在呢!

然而,仍然有两个错误。

1)图标颜色不对。我知道这是自定义图标的问题,并且有解决方法,所以我会自己研究。

什么有我卡住: 2)图标将变成在打开Word我的自定义图标,并单击字之外时就会变回默认的。但之后它会拒绝改回我的图标。每次“激活”MS Word时,SetSystemCursor()都会返回false。为什么?

+0

它是安全的假设,目标窗口处理[WM_SETCURSOR(https://msdn.microsoft.com/en-us/library/windows/desktop/ms648382.aspx)设置自己的光标,从而消除您试图改变光标形状的天真想法。 – IInspectable

+0

除了我正在尝试更改系统光标,所以它不关心目标窗口是什么。 – Moe45673

+1

假设目标窗口正在使用SYSTEM光标。 – IInspectable

回答

0

下面是最终的代码。它可以工作,但游标不是彩色的。由于彩色游标是Windows中已知的头痛,这是一个不同的问题。非常感谢汉斯帕桑特

public static class CursorHook 

{ 




    private static IntPtr programCursor = IntPtr.Zero; 
    private static IntPtr systemCursor = IntPtr.Zero; 
    private static Cursor ProgramCursor = null; 

    private static Cursor DefaultCursor = null; 


    public static void Init() 
    { 


     using(MemoryStream ms = new MemoryStream(resourceCursor.marker_cursor2)) 
     { 
      ProgramCursor = new Cursor(ms); 
     } 
     DefaultCursor = new Cursor(Cursors.IBeam.CopyHandle()); 



    } 

    public static void Start() 
    { 
     //as the GC has likely invalidated the IntPtr, each time you have to assign it anew 
     programCursor = ProgramCursor.CopyHandle(); 
     SetSystemCursor(programCursor, UNS_OCR_IBEAM); 

    } 


    public static void Stop() 
    { 
     //as the GC has likely invalidated the IntPtr, each time you have to assign it anew 
     systemCursor = DefaultCursor.CopyHandle(); 
     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); 




} 
相关问题