Murrgon Murrgon - 1 month ago 19
C++ Question

Getting alpha blending to work with CImageList

There are several other questions that are very similar to this that I have come across:


  1. Is it possible to create a CImageList with alpha blending transparency?

  2. Transparent images in ImageLists for ListViews

  3. ImageList Transparency on Listviews?



I am using WTL9.0. I have a frame window with a CTreeViewCtrlEx as its child. I am using SHGetFileInfo() to obtain the icons I want to use in the tree, but they show up with black backgrounds. Here is a complete sample.

#define WINVER 0x0601 // Windows 7
#define _WIN32_WINNT 0x0601 // Windows 7

#include <atlbase.h>
#include <atlapp.h>

CAppModule g_AppModule; // WTL version of CComModule

#include <atlwin.h>
#include <atlframe.h>
#include <atlcrack.h>
#include <atlctrls.h>

class MainWnd : public CFrameWindowImpl<MainWnd>
{
private:
typedef MainWnd ThisClass;
typedef CFrameWindowImpl<MainWnd> BaseClass;

static const DWORD TREE_STYLE = TVS_HASLINES | TVS_LINESATROOT |
TVS_HASBUTTONS | WS_CHILD | WS_VISIBLE;

CTreeViewCtrlEx m_Tree;
CImageList m_ImgList;

public:
BEGIN_MSG_MAP(ThisClass)
MSG_WM_CREATE(OnCreate)
MSG_WM_DESTROY(OnDestroy)
CHAIN_MSG_MAP(BaseClass)
END_MSG_MAP()

LRESULT OnCreate(CREATESTRUCT* pCreateStruct)
{
// Create the tree control
LPCTSTR TREE_CLASS = CTreeViewCtrlEx::GetWndClassName();
m_Tree.Create(*this, rcDefault, TREE_CLASS, TREE_STYLE);
m_hWndClient = m_Tree;

// Create the image list
m_ImgList.Create(32, 32, ILC_COLOR32, 1, 1);

SHFILEINFO sFileInfo = { 0 };
const UINT FLAGS = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES;
LPCTSTR PATH = _T("C:\\Windows");

// Get the directory icon
if (0 != ::SHGetFileInfo(PATH, FILE_ATTRIBUTE_DIRECTORY, &sFileInfo,
sizeof(SHFILEINFO), FLAGS))
{
CIcon dirIcon(sFileInfo.hIcon);
m_ImgList.AddIcon(dirIcon);
}

m_Tree.SetImageList(m_ImgList);

// Insert three items into the tree
CTreeItem rootItem =
m_Tree.InsertItem(_T("Root"), 0, 0, TVI_ROOT, TVI_LAST);
m_Tree.InsertItem(_T("Sub1"), 0, 0, rootItem, TVI_LAST);
m_Tree.InsertItem(_T("Sub2"), 0, 0, rootItem, TVI_LAST);
m_Tree.Expand(rootItem);

SetMsgHandled(false);
return 0;
}

void OnDestroy()
{
if (m_Tree.IsWindow())
m_Tree.DestroyWindow();

m_ImgList.Destroy();

SetMsgHandled(false);
}
};

int __stdcall WinMain
(
HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/,
LPTSTR /*wzCmdLine*/,
int nCmdShow
)
{
g_AppModule.Init(nullptr, hInstance);

MainWnd mainWindow;
MSG msg = { 0 };

if (nullptr == mainWindow.CreateEx())
return 1;

mainWindow.ShowWindow(nCmdShow);
mainWindow.UpdateWindow();

while (0 < ::GetMessage(&msg, nullptr, 0, 0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

g_AppModule.Term();

return 0;
}


The third link above seems to suggest that I would need to get the bitmap from the icon, make a copy of it and then add it to the image list.

Looking at the code for this project, however, would imply that you should be able to simply use the icons themselves. If you dig into the provided class, it is just using the icon handle to add it to the list. The problem with this comparison is that it is in C# and things may be different.

This MSDN article does indicate that 32bit alpha blended icons are supported, but I have yet to get them to work.

I have obtained the bitmaps for the icon loaded in the provided code and looking at the pixel data, the image does contain an alpha channel as well as being listed as 32bit.

If someone knows how to get this to work, could you please enlighten me?

Edit: Here is an image of what I get with the code I have posted.
TreeView with 32x32 icons

Answer

The code is fine, but Windows is not informed of the version of common control that is being used.

You have to enable Visual Style. You can do that in project manifest, or at the minimum, include the following lines in one of your *.cpp files:

#pragma comment(linker,"/manifestdependency:\"type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

Note this #pragma directive is Visual Studio specific, use manifest with other compilers.

Additionally you can add support for windows theme:

#include <UxTheme.h>
#pragma comment( lib, "UxTheme.lib" )
...    
SetWindowTheme(tree.m_hWnd, L"Explorer", NULL);

Result:

enter image description here