1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Win32 APIでListViewに背景画像を付けようとしたときに気付いた事

Last updated at Posted at 2020-02-26

Win32 APIでListViewに背景画像を付ける際にはSendMessageでListViewのウインドウハンドルに LVM_SETBKIMAGE を送ります。その設定で試行錯誤した箇所です。
透過対応について間違った部分があったので追記しました。

1. LVBKIF_SOURCE_HBITMAP は使えない

LVBKIMAGEWの ulFlags にLVBKIF_SOURCE_HBITMAP を設定し hbm に画像のHBITMAPを設定すれば、ListViewの背景にその画像が表示されますが、表示が崩れる ので使い物になりませんでした。
その他の特徴は多分、2.の LVBKIF_SOURCE_URL とほぼ同じだと思います。

透明・透過に対応しておらず、透明部分が白くなってしまいます。
ビットマップが乗算済みアルファの場合は透明部分が黒くなりました。

2. LVBKIF_SOURCE_URL はそこそこ使える

LVBKIMAGEWの ulFlags にLVBKIF_SOURCE_URL を設定し pszImage に画像のパス、cchImageMaxにその長さを設定すれば、ListViewの背景にその画像が表示されます。
file:///C:/image/bg.pngみたいなURLだけでなく、普通のファイルパスC:\image\bg.pngみたいなものでOKでした。
また、data URI schemeにも対応しているので、ファイル無しでも、パスにdata URI schemeを渡してあげればOKです。
※data URI schemeはdata:image/png;base64,データ みたいにパスに直接Base64でデータを書く方法です。

LVBKIF_STYLE_TILEを指定すると 同じ画像を上下にタイル状に並べて表示できます。
LVBKIF_STYLE_TILEを指定していない場合は ListView に合わせて画像もスクロールします。
指定した場合は 背景画像は固定されます。(Windows XPを除く)

LVBKIF_SOURCE_URL にも問題点が一つありました。
透明・透過に対応しておらず、透明部分が黒くなってしまいます。

3. LVBKIF_TYPE_WATERMARK は透明・透過に対応

LVBKIMAGEWの ulFlags にLVBKIF_TYPE_WATERMARK を設定し hbm に画像のHBITMAPを設定すれば、ListView の背景にその画像が表示されます。
2.の LVBKIF_SOURCE_URL と違ってListViewの右下が画像の右下とぴったりくっつきます。
右下はListViewのデータが被りにくい部分なので逆にメリットかもしれません。
また、タイル状に並べて表示できません。

透明・透過に対応する場合は、LVBKIF_FLAG_ALPHABLEND を指定してhbm に乗算済みアルファ (premultiplied alpha)のデータを使います。

hbm のアルファチャンネル

※Windows 10の場合は LVBKIF_FLAG_ALPHABLEND を指定しない場合は hbm に通常のアルファのデータを使うと、透明に対応している様に見えるが、透過が微妙に違うことが判明
※Windows 7の場合はLVBKIF_FLAG_ALPHABLEND を指定しないでhbm に通常のアルファのデータを使うと、透明部分が白くなった
Windows XP は LVBKIF_TYPE_WATERMARK は動作しない

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?