Getting alpha blending to work with CImageList

元气小坏坏 提交于 2019-12-23 17:58:10

问题


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.


回答1:


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:



来源:https://stackoverflow.com/questions/40097312/getting-alpha-blending-to-work-with-cimagelist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!