2

Vista では、項目がない場合にリスト ビュー コントロールにテキストを表示する新しい API が導入されました。MSDN ライブラリに記載されているように、LVN_GETEMPTYMARKUP通知を処理する必要があります。

継承されたListViewコントロールでは、WndProcメソッドがオーバーライドされます。

protected override void WndProc(ref Message m) {
  try {
    if(m.Msg == 78 /* WM_NOTIFY */) {
      var nmhdr = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
      if(nmhdr.code == -187 /* LVN_GETEMPTYMARKUP */) {
        var nmlvemptymarkup =
          (NMLVEMPTYMARKUP)Marshal.PtrToStructure(m.LParam, typeof(NMLVEMPTYMARKUP));
        nmlvemptymarkup.szMarkup = "The ListView is empty.";
        m.Result = (IntPtr)1;
      }
    }
  } finally {
    base.WndProc(ref m);
  }
}

ただし、機能しません (ただし、例外はスローされません)。実際にnmhdr.codeは、-187 に等しくなることはありません。何か案は?

4

4 に答える 4

3

WM_NOTIFYメッセージはコントロール (リストビュー) ではなく、親 (フォーム) に送信されます。これは Win32 の世界では理にかなっています。これらのメッセージはインターセプトするのに非常に便利ですが、特にそれぞれのケースで異なる動作が必要な場合は、コントロールをサブクラス化するのは中程度の苦痛でした。.NET では、そうではなくなりました。

便利なことに、標準の .NET メッセージ処理はメッセージをコントロールに "反射" するので、メッセージをインターセプトしてコントロールの WndProc 内で処理できますが、反映されたメッセージはもはやWM_NOTIFY(0x004E) ではなくWM_REFLECT| WM_NOTIFY(0x204E)。

したがって、代わりにその値を探すように WndProc を変更すると、機能するはずです。

于 2008-12-29T05:16:32.313 に答える
0

私自身、これにはかなり苦労しました。

元の質問のコードを機能させるには、NMLVEMPTYMARKUP 構造体を [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] でマークします (CharSet.Unicode が重要です)。

また、マークアップ値を設定した後、Marshal.StructureToPtr(nmlvemptymarkup, m.LParam, false) を呼び出して、LParam が指すバッファーにデータをコピーして戻します。

于 2009-05-04T15:11:20.193 に答える
0

この記事SetWindowThemeに示されているように、コントロールを呼び出してみましたか?

于 2008-11-13T15:54:14.250 に答える
0

別の解決策 (WndProc を監視する必要がないようにするため) は、次のようなペイント ハンドラーを追加することです。

listview_onPaint(object sender, eventargs e)
{
  if ( listview.items.count <= 0 )
  {
     e.graphics.drawstring("The Listview is empty"); //put all the proper args in here!
  }
}

それは記憶によるものですが、アイデアを得る必要があります。

それが助けになることを願っています。

于 2008-11-13T15:59:17.830 に答える