2017-02-06 6 views
0

他のプログラムが書き込むことができる.Net WPFアプリケーションを作成しています。設計者が実装したい機能の1つは、テキストエディタ「I-Beam」の代わりにサードパーティのプログラムで使用されるカスタムカーソルです。ローレベルシステムカーソルを.Net Office Interopでカスタムに設定する

私が困惑している最初のサードパーティプログラムは、.NetのOffice Interopのものを使用しているMS Word 2013です。カーソルリソースを保持する私のプログラムのアプリケーションドメイン内のグローバルC#DLLを持っています。

Interopでは、カスタムカーソルを割り当てることはできません(ただし、カーソルを切り替えることはできます)。だから、たくさんの掘り出した後、私はいくつかの低レベルを混乱させようとしました。 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 

} 

しかし、カーソルがさえコードかかわらず、(変更されません。が呼び出されます)。私は何が欠けていますか?

私は、静的クラスがリソースを最大限に活用していない可能性があるという大きなイメージを理解しています。しかし今は、カーソルを私が欲しいものをするようにしようとしています。これが達成された後、私はエレガンスに取り組んでいきます。

ありがとうございます!

EDIT

私はこのように見えるようにコードを変更した:

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さんのコメントのおかげで非常に簡単です。それは実際には、今でもいくらか働いています!

まだ、2つのバグがあります。

1)アイコンの色が変わっています。私はこれがカスタムアイコンの問題であり、回避策があることを知っているので、私は自分自身でそれを研究します。 2)アイコンは、Wordを開くには、私のカスタムアイコンに変わります、およびWordの外側をクリックすると、既定1に戻って変更されます:私はを立ち往生している何

。しかしその後、私のアイコンに戻って変更を拒否します。 SetSystemCursor()は、MS Wordを「アクティブにする」たびに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); 




} 
関連する問題