リストビューのImageList透明度?
-
08-07-2019 - |
質問
編集:賞金を提供しました。さもないと答えが得られないのではないかと思います。
最近、リストビューで作業しており、各アイテムに入力か出力かを示すアイコンを追加することにしました。アイコンは追加できますが、透明ではありません:
ご覧のとおり、アイコンは明らかに透明ではありません。私は現在、このようなアイコンをロードするようなことをしています:
hImageList = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 2, 2);
if (hImageList != NULL)
{
iIN = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(101)));
iOUT = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(102)));
}
ImageList_Create
のフラグをいじってみました& LoadIcon
/ LoadImage
ですが、運がなかったため、正直言ってアイデアが足りませんでした。
ご協力いただければ幸いです。
解決
最初に、ImageList_ReplaceIconは、画像リストに追加するときにアイコンデータをコピーします。そのため、HICONは後でリリースする必要があります。
次に、画像リストはネイティブではビットマップであり、アイコンではありません。また、イメージリストの作成方法により、アイコンからビットマップへの変換が非常に曖昧になります。 ILC_COLOR32は、イメージリストが32ビットのdibセクションとして作成されることを意味します。これには、通常、埋め込まれたアルファチャネルを介した透明度情報が含まれます。 ILC_MASKは、代わりに、内部ビットマップがDDBビットマップであり、透明度情報が1bppマスクビットマップとして保存されていることを意味します。
問題の最も迅速な解決策-2つのアイコンを選択してください:
- 幅32ピクセル、高さ16の単一のビットマップリソースにそれらをマージします。背景をマスク色で塗りつぶします:-紫か何か。
- ILC_COLOR | ILC_MASKを使用してビットマップを作成
- LR_TRANSPARENTを使用しないようにして、ビットマップをロードします。
- ImageList_AddMaskedを使用してビットマップを追加し、マスクの色を表すCOLORREFを渡します。
または、視覚効果を向上させる...
- PNGデータを、事前に乗算されたアルファチャネルデータを含む32x16 32bppビットマップファイルとしてエクスポートします。
- ILC_COLOR32値を使用してイメージリストを作成します。
- LR_CREATEDIBSECTIONを指定したLoadImage()を使用して、32bpp dibセクションとしてビットマップをロードします。
- ImageList_Add()を使用して画像を追加します
(最後のオプションは、アルファチャネルが適切に事前に乗算された32ビットbmpファイルの書き出しをサポートするツールの数が少ないため、やや注意が必要です。
編集して、次のコードサンプルを追加します。開発環境で作成された4bppビットマップを使用すると、非常にうまく機能します:-
HWND hwndCtl = CreateWindowEx(0,WC_LISTVIEW,TEXT("ListView1"),WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL,0,0,cx,cy,hWnd,(HMENU)101,hModule,NULL);
HBITMAP hbm = (HBITMAP)LoadImage(hModule,MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,0,0,0);
COLORREF crMask=RGB(255,0,255);
HIMAGELIST himl = ImageList_Create(16,16,ILC_COLOR|ILC_MASK,2,0);
ImageList_AddMasked(himl,hbm,crMask);
ListView_SetImageList(hwndCtl,himl,LVSIL_NORMAL);
他のヒント
アイコンの背景色を、アイコンのどこにも使用されていない非常にい紫色のようにしたい場合は、LoadImage(...、LR_LOADTRANSPARENT)を使用します。フラグは、0,0の最初のピクセルを見て、その色をすべて透明にします。
あなたのコードは私には見た目が良く、LoadIconではなくLoadImageを常に使用していますが、それは問題ではないと思います。アイコンに実際に透明な領域があり、それ自体が無地の背景になっていないことを確認しましたか?
私のLoadImage呼び出しは次のようになります:
HICON hIcon = (HICON)LoadImage(hinstResources,MAKEINTRESOURCE(IDI_ICON),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
ここ...推奨されるように、ImageListを作成し、アイコンを16ピクセル、長さ16 * nのビットマップにします。n=アイコンの数...
設定したとおり、背景色を255、0、255に設定します。
次に、ここで行ったように、それをロードして、画像リストに追加します:
m_ImageList.Create(16, 16, ILC_COLOR16 | ILC_MASK, 7, 1);
CBitmap bm;
bm.LoadBitmap(IDB_SUPERTREEICONS);
m_ImageList.Add(&bm, RGB(255, 0, 255));
GetTreeCtrl().SetImageList(&m_ImageList, TVSIL_NORMAL);
もちろん、これはMFCで記述されていますが、ご存知のように、Win32の単なるラッパーです...
これ以外では、カスタム描画コントロールに移動する必要があります。このコントロールでは、アイコンが置かれている背景にアイコンを描画します。魔法のような「透明」はありません。これらのコントロールのいずれかで、私が知っている色。
カスタム描画の場合、次のようなコードを使用する必要があります。
#define TRANSPARENT_COLOR (255,0,255)
UINT iBitmap = IDB_ICON_UP
CDC *dc = GetDC();
int x = 0, y = 0;
CDC *pDisplayMemDC = new CDC;
CDC *pMaskDC = new CDC;
CDC *pMemDC = new CDC;
CBitmap *pBitmap = new CBitmap;
CBitmap *pMaskBitmap = new CBitmap;
CBitmap *pMemBitmap = new CBitmap;
int cxLogo, cyLogo;
BITMAP bm;
pBitmap->LoadBitmap(iBitmap);
pDisplayMemDC->CreateCompatibleDC(dc);
CBitmap *pOldBitmap = (CBitmap *)pDisplayMemDC->SelectObject(pBitmap);
pBitmap->GetObject(sizeof(bm), &bm);
cxLogo = bm.bmWidth;
cyLogo = bm.bmHeight;
pMaskBitmap->CreateBitmap(cxLogo, cyLogo, 1, 1, NULL);
pMaskDC->CreateCompatibleDC(dc);
CBitmap *pOldMask = (CBitmap *)pMaskDC->SelectObject(pMaskBitmap);
COLORREF oldBkColor = pDisplayMemDC->SetBkColor(TRANSPARENT_COLOR);
pMaskDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCCOPY);
pMemBitmap->CreateCompatibleBitmap(dc, cxLogo, cyLogo);
pMemDC->CreateCompatibleDC(dc);
CBitmap *pOldMem = (CBitmap *)pMemDC->SelectObject(pMemBitmap);
pMemDC->BitBlt(0, 0, cxLogo, cyLogo, dc, x, y, SRCCOPY);
pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCINVERT);
pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pMaskDC, 0, 0, SRCAND);
pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCINVERT);
dc->BitBlt(x, y, cxLogo, cyLogo, pMemDC, 0, 0, SRCCOPY);
delete pMemDC->SelectObject(pOldMem);
delete pMemDC;
delete pMaskDC->SelectObject(pOldMask);
delete pMaskDC;
delete pDisplayMemDC->SelectObject(pOldBitmap);
delete pDisplayMemDC;
このコードは、アイコンを描画する場所を決定し、背景のスナップショットを作成し、アイコンのマスクを作成し、背景の上に描画して、完全に透明な背景を与えます...
いくらか役立つことを願っています。そうでない場合は、何を実現しようとしているのか、何を見ているのか、何を見ていないのかを詳しく説明してください...