他のプログラムが書き込むことができる.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を返します。どうして?
にビッグおかげでそれはターゲットウィンドウは、[WM_SETCURSOR](https://msdn.microsoft.com/en-us/library/windows/desktop/ms648382.aspx)を扱うことを想定しても安全です、カーソルが適切に見えるように設定して、カーソルの形状を変更しようとする単純な試みを元に戻します。 – IInspectable
私はシステムカーソルを変更しようとしているので、ターゲットウィンドウが何をしているかは関係ありません。 – Moe45673
これは、ターゲットウィンドウがSYSTEMカーソルを使用していることを前提としています。 – IInspectable