2012年11月29日木曜日

[C#] ListView のカラム部分に画像表示(其の2:HDITEM版)

[共通] 当 Blog の投稿に関する基本事項について
→ http://fuunyan.blogspot.jp/2012/09/blog.html


先日、ほぼ同様のタイトルでカラムに画像を表示する方法を投稿しました。
[C#] ListView のカラム部分に画像表示
この時は ImageList を利用して表示する方法となっていましたが、今回は別の方法で画像を表示してみたいと思います。

表示パターンが確定していて動作中に変更が必要無い場合は、画像ファイルを準備した状態で前回の方法を利用してもらうのが一番だと思います。
しかし状況により表示内容を変更したい(動的に描画する)場合は、少々不便です。
確かに該当する ImageList の内容を書き換えてしまえば前回の方法で表示することは可能ですが、それだと ImageList を利用して準備している意味がありません。

そこで今回は動的に描画した画像をカラムに表示させてみたいと思います。
(妙に説明調になっているのは、自分が忘れそうだからです)
Header Control (Windows)


まずは宣言。
// 前回も宣言したもの
using System.Runtime.InteropServices;

public const UInt32 LVM_GETHEADER = 0x101F;
public const int HDF_BITMAP_ON_RIGHT = 0x1000;

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, UInt32 wParam, UInt32 lParam);

// 以下前回より追加宣言したもの
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct HDITEM
{
 public uint mask;
 public int cxy;
 public IntPtr pszText;
 public IntPtr hbm;
 public int cchTextMax;
 public int fmt;
 public int lParam;
 public int iImage;
 public int iOrder;
 public uint type;
 public IntPtr pvFilter;
 public uint state;
}

public const int HDF_BITMAP = 0x2000;
public const uint HDI_FORMAT = 0x0004;
public const uint HDI_BITMAP = 0x0010;
public const uint HDM_FIRST = 0x1200;
public const uint HDM_GETITEM = HDM_FIRST + 3;
public const uint HDM_SETITEM = HDM_FIRST + 4;

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, UInt32 wParam, ref HDITEM lParam);
前回と似たような感じですが、新規宣言したものがあります。
相変わらず情報源は CommCtrl.h となっています。

次はコード本体です。
今回もボタン押下イベントに書いています。
IntPtr colHeader;

// リストビューのカラム部分のハンドルを取得
colHeader = SendMessage(listView1.Handle, LVM_GETHEADER, (UInt32)0, (UInt32)0);

// 設定対象のカラム情報を取得
HDITEM hdItem = new HDITEM();
hdItem.mask = HDI_FORMAT;
SendMessage(colHeader, HDM_GETITEM, 0, ref hdItem);

// 設定対象のカラム情報を変更、反映
hdItem.mask = HDI_FORMAT | HDI_BITMAP;
hdItem.fmt |= HDF_BITMAP | HDF_BITMAP_ON_RIGHT;
Bitmap bmp = CreateSortOrderBmp(1, 1);
hdItem.hbm = bmp.GetHbitmap(SystemColors.Window);
SendMessage(colHeader, HDM_SETITEM, 0, ref hdItem);

/* 参考:Header_GetItem と Header_SetItem の定義内容
#define Header_GetItem(hwndHD, i, phdi) \
    (BOOL)SNDMSG((hwndHD), HDM_GETITEM, (WPARAM)(int)(i), (LPARAM)(HD_ITEM *)(phdi))
            
#define Header_SetItem(hwndHD, i, phdi) \
    (BOOL)SNDMSG((hwndHD), HDM_SETITEM, (WPARAM)(int)(i), (LPARAM)(const HD_ITEM *)(phdi))
*/
CreateSortOrderBmp(1, 1)の中でBMP画像を作成しています。
利用される場合は、その辺を適当に変更していただければいいかと。

このコードでリストのカラムテキストの右側に画像を表示することはできるのですが、少し後に問題があることに気付きました。
ほとんど保護色になっていて気付かなかったのですが、背景色が透過していないため、画面の色指定次第で画像部分が目立って表示されることがあります。
それなりに考えた背景色にしておけば気づかれない可能性はありますが、完璧を求めるならばこの方法では駄目だということになります。
その辺の対策は ImageList を利用した前回のパターンで解消できます。

じゃ何でこの記事投稿したんだ?って話になるのですが、そこはそれメモです。
せっかく調べたのに消すのはもったいないですからね。

上記理由から、特に理由がないようでしたら前回か次回(予定)の投稿を参照してください。

0 件のコメント:

コメントを投稿