Shell_NotifyIcon
関数 [ 1 ] を C# から呼び出そうとしています。NOIFYICONDATA
関数の 1 つのパラメーターは、構造体へのポインターです[ 2 ]。この構造体にはTCHAR
配列、ポインターが含まれており、4 つの異なるバージョンがあります (使用中の OS/API によって異なります)。構造体の最初のフィールド ( cbSize
) は、関数に渡す前に、呼び出し元が構造体のサイズ (バイト単位) に設定する必要がありShell_NotifyIcon
ます。
私の現在のアプローチは、4つのクラスを使用することです:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[BestFitMapping(false, ThrowOnUnmappableChar = true)]
public class NotifyIconData { ... }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[BestFitMapping(false, ThrowOnUnmappableChar = true)]
public class NotifyIconData2 : NotifyIconData { ... }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[BestFitMapping(false, ThrowOnUnmappableChar = true)]
public class NotifyIconData3 : NotifyIconData2 { ... }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[BestFitMapping(false, ThrowOnUnmappableChar = true)]
public class NotifyIconData4 : NotifyIconData3 { ... }
のコンストラクターで、構造体のサイズを決定するためNotifyIconData
に使用します。Marshal.SizeOf(this.GetType());
結果は正しいです (少なくとも、管理されていない Unicode/Ansi/x86/x64 ビルドの , , と同じですNOTIFYICONDATA_V1_SIZE
。NOTIFYICONDATA_V2_SIZE
このアプローチの理由は、特にパディングが行われているため、マジック ナンバーを使用したくないためです。構造体の正しいサイズを計算します. フィールドの実装にはちょっとしたトリックもあります. このフィールドは 64文字の配列 (バージョン 1) または 128文字の配列 (バージョン 2) のいずれかになります.このクラスをシミュレートするには、次のフィールド定義が含まれています。NOTIFYICONDATA_V3_SIZE
sizeof(NOTIFYICONDATAW)
szTip
TCHAR
TCHAR
NotifyIconData
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
protected string szTip;
クラスではNotifyIconData2
、次の定義でこのフィールドを「拡張」します。
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
private string szTipExtension;
このフィールドは、実際の値を 2 つのフィールドに分割する仮想プロパティを介してアクセスされます。
これらのクラスは、Shell_NotifyIcon
次のように宣言された関数で使用されます。
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private delegate bool ShellNotifyIconFunction(
[In, MarshalAs(UnmanagedType.U4)] uint dwMessage,
[In] NotifyIconData lpdata);
NotifyIconData4
インスタンスを関数に渡すことができるようになったと思う人もいるでしょう。コンパイル時にこれは機能します (期待どおり)。しかし、実行時に MDAFatalExecutionEngineError
例外が発生します。パラメータのタイプを から に変更するNotifyIconData
とNotifyIconData4
、呼び出しが成功し、機能します。
NotifyIconData
マーシャラーは動的型ではなく静的型を使用しNotifyIconData4
てデータをマーシャリングしているようです。誰でもそれを確認できますか?または、マーシャリングが継承でどのように機能するかについての情報を誰かに教えてもらえますか?