Transparência do ImageList no ListViews?
-
08-07-2019 - |
Pergunta
EDITAR: Eu ofereci uma recompensa, já que duvido que receba respostas.
Ultimamente, tenho trabalhado com ListViews e decidi adicionar um ícone para cada item indicando se é entrada ou saída. Os ícones acrescentam bem, mas não são transparentes:
Como pode ser visto, os ícones claramente não são transparentes. Atualmente, estou fazendo algo assim, os ícones:
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)));
}
Eu tentei mexer com as bandeiras para ImageList_Create
& LoadIcon
/LoadImage
Mas não tive sorte e, para ser sincero, fiquei sem idéias.
Qualquer ajuda será muito apreciada.
Solução
Primeiro, o ImageList_replaceicon copia os dados do ícone ao adicioná -los a uma lista de imagens. Portanto, o hicon precisa ser liberado depois.
Em seguida, os listradores imageieis são nativamente bitmaps, não ícones. E a maneira como você está criando sua lista de imagens torna a conversão do ícone em bitmap muito ambíguo. O ILC_COLOR32 implica que a lista de imagens deve ser criada como uma seção DIB de 32 bits, que normalmente contém informações de transparência por meio de um canal alfa incorporado. O ILC_MASK implica que os bitmaps internos são bitmaps DDB, com as informações de transparência armazenadas como um bitmap de máscara de 1BPP.
A solução mais rápida para o seu problema - pegue seus dois ícones:
- Mescre -os em um único recurso de bitmap com 32 pels de largura por 16 alta. Encha o fundo com uma cor de máscara:- roxo ou algo assim.
- Crie o bitmap usando ILC_COLOR | ILC_MASK
- Carregue o bitmap, certificando -se de não usar lr_transparent.
- Adicione o bitmap usando o imageList_addmasked Passando em um ColorRef que representa a cor da máscara.
Ou, para um melhor efeito visual ...
- Export seus dados PNG como um arquivo de bitmap de 32x16 32bpp contendo dados de canal alfa pré-multiplicado.
- Crie a lista de imagens usando o valor ILC_COLOR32.
- LoadImage () com lr_createdibSection para carregar o bitmap como uma seção DIB de 32bpp.
- Adicione a imagem usando imageList_add ()
(A última opção é complicada como o número de ferramentas que suportam os arquivos BMP de 32 bits com canais alfa pré -multiplicados adequadamente é bastante baixa).
Editado para adicionar o seguinte exemplo de código. Usando um bitmap de 4bpp criado no ambiente de desenvolvimento, isso funciona ótimo:-
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);
Outras dicas
Você deseja fazer com que seus ícones tenham uma cor de fundo que não seja usada em nenhum outro lugar do ícone, como um roxo realmente feio, e depois use o loadImage (..., lr_loadtransparent); A bandeira diz olhar para o primeiro pixel em 0,0 e fazer tudo o que é transparente.
Seu código parece bom para mim, eu sempre uso o LoadImage em vez do loadicon, mas suspeito que isso não importa. Você verificou se os ícones realmente têm áreas transparentes e não têm um fundo sólido?
Minhas chamadas de carregamento parecem:
HICON hIcon = (HICON)LoadImage(hinstResources,MAKEINTRESOURCE(IDI_ICON),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
Aqui ... Crie uma lista de imagelestos, como sugerido, transforme seus ícones em um bitmap, 16 pixels de altura, por 16*n de comprimento, onde n = o número de ícones ...
Defina a cor de fundo para 255, 0, 255, como você fez.
Em seguida, carregue -o e adicione -o à lista de imagens como eu fiz aqui:
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);
Claro, isso foi escrito no MFC, mas como você sabe, é apenas um invólucro para o Win32 ...
Fora disso, você terá que ir a um controle personalizado, no qual desenhe o ícone sobre qualquer fundo que o ícone esteja sentado. Não há realmente nenhuma cor "transparente" mágica, que eu conheço, em qualquer um desses controles.
No caso de um sorteio personalizado, você precisa usar o código como o seguinte:
#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;
Este código decide onde desenhar o ícone e tira um instantâneo do fundo, cria uma máscara para o ícone e depois o desenha sobre o fundo, dando -lhe um fundo totalmente transparente ...
Espero que ajude um pouco. Caso contrário, explique com mais detalhes o que você está tentando fazer acontecer, e o que você está vendo, ou o que não está vendo ...