class DemoDuilib : public WindowImplBase, public CButtonUI
{
public:
DemoDuilib();
~DemoDuilib();
void test();
static std::vector<uint8_t> thumbData;//存储BLOB类型二进制数据
private:
void PaintStatusImage(HDC hDC) override;//保持纵横比并裁剪
HBITMAP CreateHBITMAPFromMemory(const std::vector<uint8_t>& data);//BLOB类型二进制数据转换成Bitmap类型数据
void DemoDuilib::SetNormalBitmap(HBITMAP hBitmap);
)
void test(){
DemoDuilib* pButton = new DemoDuilib();
CDuiString strName;
strName.Format(_T("btn_square_%d"), i + 1);
pButton->SetName(strName);
pButton->SetFixedHeight(BUTTONSIZE);//const int BUTTONSIZE = 85;
pButton->SetFixedWidth(BUTTONSIZE);
HBITMAP hBitmap = CreateHBITMAPFromMemory(thumbData);
if (hBitmap)
{
pButton->SetNormalImage(hBitmap);
}
pButton->SetPadding(CDuiRect(10,0,0,0));
pButtonLayout->Add(pButton);
}
void DemoDuilib::SetNormalBitmap(HBITMAP hBitmap)
{
m_hNormalBitmap = hBitmap;
Invalidate();
}
/*
- 功能:设置控件的普通状态位图,并使控件无效以触发重绘。
- 参数:
HBITMAP hBitmap 是一个位图句柄。
- 操作:
- 将传入的位图句柄
hBitmap 赋值给成员变量 m_hNormalBitmap。
- 调用
Invalidate() 函数,使控件无效,从而触发重绘。
*/
void DemoDuilib::PaintStatusImage(HDC hDC)
{
if (m_hNormalBitmap)
{
HDC hMemDC = CreateCompatibleDC(hDC);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hNormalBitmap);
BITMAP bitmap;
GetObject(m_hNormalBitmap, sizeof(bitmap), &bitmap);
float aspectRatio = static_cast<float>(bitmap.bmWidth) / bitmap.bmHeight;
int targetWidth = m_rcItem.right - m_rcItem.left;
int targetHeight = m_rcItem.bottom - m_rcItem.top;
int newWidth, newHeight;
if (aspectRatio > 1.0f) {
newWidth = targetWidth;
newHeight = static_cast<int>(targetWidth / aspectRatio);
} else {
newHeight = targetHeight;
newWidth = static_cast<int>(targetHeight * aspectRatio);
}
int offsetX = (targetWidth - newWidth) / 2;
int offsetY = (targetHeight - newHeight) / 2;
StretchBlt(hDC, m_rcItem.left, m_rcItem.top, targetWidth, targetHeight,
hMemDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
SelectObject(hMemDC, hOldBitmap);
DeleteDC(hMemDC);
} else {
CButtonUI::PaintStatusImage(hDC);
}
}
/*
- 功能:绘制控件的状态图像。
- 参数:
HDC hDC 是设备上下文句柄,用于绘制图像。
- 操作:
- 检查
m_hNormalBitmap 是否有效。
- 如果有效:
- 创建一个兼容的内存设备上下文
hMemDC。
- 将
m_hNormalBitmap 选择到 hMemDC 中,并保存旧的位图句柄 hOldBitmap。
- 获取位图信息(宽度和高度)。
- 计算位图的宽高比
aspectRatio。
- 计算目标区域的宽度
targetWidth 和高度 targetHeight。
- 根据宽高比调整新的宽度
newWidth 和高度 newHeight,以保持图像的比例。
- 计算图像在目标区域中的偏移量
offsetX 和 offsetY。
- 使用
StretchBlt 函数将位图从内存设备上下文 hMemDC 绘制到目标设备上下文 hDC。
- 恢复旧的位图句柄并删除内存设备上下文
hMemDC。
- 如果
m_hNormalBitmap 无效,调用基类 CButtonUI 的 PaintStatusImage 函数。
*/
HBITMAP DemoDuilib::CreateHBITMAPFromMemory(const std::vector<uint8_t>& data)
{
HBITMAP hBitmap = NULL;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
IStream* pStream = SHCreateMemStream(data.data(), data.size());
if (pStream)
{
Gdiplus::Bitmap* pBitmap = Gdiplus::Bitmap::FromStream(pStream);
if (pBitmap)
{
pBitmap->GetHBITMAP(Gdiplus::Color(0, 0, 0), &hBitmap);
delete pBitmap;
}
pStream->Release();
}
Gdiplus::GdiplusShutdown(gdiplusToken);
return hBitmap;
}
/*
- 功能:从内存中的字节数据创建一个
HBITMAP。
- 参数:
const std::vector<uint8_t>& data 是包含位图数据的字节向量。
- 操作:
- 初始化
GDI+ 库。
- 使用
SHCreateMemStream 函数从字节数据创建一个内存流 pStream。
- 如果内存流
pStream 有效:
- 使用
Gdiplus::Bitmap::FromStream 函数从内存流创建一个 Gdiplus::Bitmap 对象 pBitmap。
- 如果
pBitmap 有效:
- 使用
pBitmap->GetHBITMAP 函数获取 HBITMAP。
- 删除
pBitmap 对象。
- 释放内存流
pStream。
- 关闭
GDI+ 库。
- 返回创建的
HBITMAP。
*/