3

編集:そうでなければ答えが得られるとは思えないので、賞金を提供しました。

最近、私はリストビューで作業しており、各項目に入力か出力かを示すアイコンを追加することにしました。アイコンは問題なく追加されますが、透明ではありません:

アイコンが透明でない例

ご覧のとおり、アイコンは明らかに透明ではありません。私は現在、このようなアイコンをロードするようなことをしています:

  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が、うまくいきませんでした。正直言って、アイデアが尽きてしまいました。

どんな助けでも大歓迎です。

4

4 に答える 4

13

まず、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 値を使用してイメージリストを作成します。
  • LoadImage() と LR_CREATEDIBSECTION を使用して、ビットマップを 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);
于 2009-03-13T08:36:11.890 に答える
0

アイコンの背景色を、アイコンの他の場所では使用されていない非常に醜い紫色のようにしたい場合は、LoadImage(..., LR_LOADTRANSPARENT); を使用します。このフラグは、0,0 の最初のピクセルを見て、その色のすべてを透明にすることを示しています。

于 2009-03-10T23:02:54.700 に答える
0

ここで...提案されているように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;

このコードは、アイコンを描画する場所を決定し、背景のスナップショットを取得し、アイコンのマスクを作成してから、背景の上に描画して、完全に透明な背景にします...

それが多少役立つことを願っています。そうでない場合は、何を実現しようとしているのか、何が見えているのか、何が見えていないのか、さらに詳しく説明してください...

于 2009-03-18T22:03:54.063 に答える
0

あなたのコードは私には問題ないように見えます。私は常に LoadIcon の代わりに LoadImage を使用していますが、それは問題ではないと思います。アイコンに実際に透明な領域があり、それ自体の背景が無地でないことを確認しましたか?

私の LoadImage 呼び出しは次のようになります。

HICON hIcon = (HICON)LoadImage(hinstResources,MAKEINTRESOURCE(IDI_ICON),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
于 2009-03-13T05:00:10.007 に答える