3

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

Community
  • 1
  • 1
Murrgon
  • 375
  • 4
  • 13
  • An icon consists of two bitmaps: The image information plus a monochrome mask. This is incompatible with your choice of image list (`ILC_COLOR32`). You cannot just add the icon data to your image list. You'll have to convert to 32-bit ARGB color format first. This won't give you alpha transparency, though. Since the mask is monochrome, you have pixels that are either fully transparent or fully opaque. – IInspectable Oct 18 '16 at 00:35
  • The MSDN article I linked describes using icons specifically. Also, I know for a fact that the image information of the icon I loaded in the sample is ARGB, having verified that with GetBitmapBits and looking at the pixels. The BITMAP structure also says it is 32bit. – Murrgon Oct 18 '16 at 01:56
  • I tried your code in MFC, it looks fine. Post some images of what you are getting and what you expect to get. Increase TreeView's item height to 32 or 64 so you can get better look at the icons. – Barmak Shemirani Oct 18 '16 at 03:02
  • I added the requested image. I didn't need to change the height of the items. By using 32x32 icons in the image list, the tree view automatically adjusted the size of the tree items. – Murrgon Oct 18 '16 at 14:58

1 Answers1

4

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

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77