让 alpha 混合与 CImageList 一起工作
Getting alpha blending to work with CImageList
我遇到的其他几个问题与此非常相似:
- Is it possible to create a CImageList with alpha blending transparency?
- Transparent images in ImageLists for ListViews
- ImageList Transparency on Listviews?
我使用的是WTL9.0。我有一个框架 window,其子项为 CTreeViewCtrlEx。我正在使用 SHGetFileInfo() 来获取我想在树中使用的图标,但它们显示为黑色背景。这是一个完整的示例。
#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;
}
上面的第三个link似乎暗示我需要从图标中获取位图,复制它然后将其添加到图像列表中。
然而,查看 this project 的代码意味着您应该能够简单地使用图标本身。如果您深入研究提供的 class,它只是使用图标句柄将其添加到列表中。这种比较的问题在于它是在 C# 中,情况可能有所不同。
This MSDN article 表示支持 32 位 alpha 混合图标,但我还没有让它们工作。
我已经获得了在提供的代码中加载的图标的位图并查看像素数据,图像确实 包含 alpha 通道并被列为 32 位。
如果有人知道如何让这个工作,你能告诉我吗?
编辑: 这是我通过发布的代码得到的图像。
代码没问题,但是 Windows 没有被告知正在使用的通用控件的版本。
您必须启用 Visual Style。您可以在项目清单中执行此操作,或者至少在您的 *.cpp 文件之一中包含以下行:
#pragma comment(linker,"/manifestdependency:\"type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
请注意此 #pragma
指令是 Visual Studio 特定的,请将清单与其他编译器一起使用。
此外,您可以添加对 windows 主题的支持:
#include <UxTheme.h>
#pragma comment( lib, "UxTheme.lib" )
...
SetWindowTheme(tree.m_hWnd, L"Explorer", NULL);
结果:
我遇到的其他几个问题与此非常相似:
- Is it possible to create a CImageList with alpha blending transparency?
- Transparent images in ImageLists for ListViews
- ImageList Transparency on Listviews?
我使用的是WTL9.0。我有一个框架 window,其子项为 CTreeViewCtrlEx。我正在使用 SHGetFileInfo() 来获取我想在树中使用的图标,但它们显示为黑色背景。这是一个完整的示例。
#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;
}
上面的第三个link似乎暗示我需要从图标中获取位图,复制它然后将其添加到图像列表中。
然而,查看 this project 的代码意味着您应该能够简单地使用图标本身。如果您深入研究提供的 class,它只是使用图标句柄将其添加到列表中。这种比较的问题在于它是在 C# 中,情况可能有所不同。
This MSDN article 表示支持 32 位 alpha 混合图标,但我还没有让它们工作。
我已经获得了在提供的代码中加载的图标的位图并查看像素数据,图像确实 包含 alpha 通道并被列为 32 位。
如果有人知道如何让这个工作,你能告诉我吗?
编辑: 这是我通过发布的代码得到的图像。
代码没问题,但是 Windows 没有被告知正在使用的通用控件的版本。
您必须启用 Visual Style。您可以在项目清单中执行此操作,或者至少在您的 *.cpp 文件之一中包含以下行:
#pragma comment(linker,"/manifestdependency:\"type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
请注意此 #pragma
指令是 Visual Studio 特定的,请将清单与其他编译器一起使用。
此外,您可以添加对 windows 主题的支持:
#include <UxTheme.h>
#pragma comment( lib, "UxTheme.lib" )
...
SetWindowTheme(tree.m_hWnd, L"Explorer", NULL);
结果: