duilib 圆形头像控件

13 篇文章 0 订阅

原图,图片来源网络



效果图



#pragma once
#include "..\UiLib\UIlib.h"
using namespace DuiLib;
#include <gdiplus.h>
class CElipsePhotoUI :
	public CControlUI
{
public:
	CElipsePhotoUI();
	virtual ~CElipsePhotoUI();

	virtual void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);

	void SetBkImage(LPCTSTR pStrImage);

	virtual void PaintBkImage(HDC hDC);
private:
	Gdiplus::Bitmap*		m_bkGDIPimage;
};

#include "UIElipsePhoto.h"


CElipsePhotoUI::CElipsePhotoUI()
{
	m_bkGDIPimage = NULL; 
}


CElipsePhotoUI::~CElipsePhotoUI()
{
	if (m_bkGDIPimage)
	{
		delete m_bkGDIPimage;
		m_bkGDIPimage = NULL;
	}
}


using namespace Gdiplus;
Bitmap* CreateBitmapFromHBITMAP(IN HBITMAP hBitmap)
{
	BITMAP bmp = { 0 };
	if (0 == GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bmp))
	{
		return FALSE;
	}

	// Although we can get bitmap data address by bmp.bmBits member of BITMAP   
	// which is got by GetObject function sometime,  
	// we can determine the bitmap data in the HBITMAP is arranged bottom-up   
	// or top-down, so we should always use GetDIBits to get bitmap data.  
	BYTE *piexlsSrc = NULL;
	LONG cbSize = bmp.bmWidthBytes * bmp.bmHeight;
	piexlsSrc = new BYTE[cbSize];

	BITMAPINFO bmpInfo = { 0 };
	// We should initialize the first six members of BITMAPINFOHEADER structure.  
	// A bottom-up DIB is specified by setting the height to a positive number,   
	// while a top-down DIB is specified by setting the height to a negative number.  
	bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmpInfo.bmiHeader.biWidth = bmp.bmWidth;
	bmpInfo.bmiHeader.biHeight = bmp.bmHeight; // 正数,说明数据从下到上,如未负数,则从上到下  
	bmpInfo.bmiHeader.biPlanes = bmp.bmPlanes;
	bmpInfo.bmiHeader.biBitCount = bmp.bmBitsPixel;
	bmpInfo.bmiHeader.biCompression = BI_RGB;

	HDC hdcScreen = CreateDC(L"DISPLAY", NULL, NULL, NULL);
	LONG cbCopied = GetDIBits(hdcScreen, hBitmap, 0, bmp.bmHeight,
		piexlsSrc, &bmpInfo, DIB_RGB_COLORS);
	DeleteDC(hdcScreen);
	if (0 == cbCopied)
	{
		delete[] piexlsSrc;
		return FALSE;
	}

	// Create an GDI+ Bitmap has the same dimensions with hbitmap  
	Bitmap *pBitmap = new Bitmap(bmp.bmWidth, bmp.bmHeight, PixelFormat32bppPARGB);

	// Access to the Gdiplus::Bitmap's pixel data  
	BitmapData bitmapData;
	Rect rect(0, 0, bmp.bmWidth, bmp.bmHeight);
	if (Ok != pBitmap->LockBits(&rect, ImageLockModeRead,
		PixelFormat32bppPARGB, &bitmapData))
	{
		if (pBitmap)
		{
			delete pBitmap;
			pBitmap = NULL;
		}
		return NULL;
	}

	BYTE *pixelsDest = (BYTE*)bitmapData.Scan0;
	int nLinesize = bmp.bmWidth * sizeof(UINT);
	int nHeight = bmp.bmHeight;

	// Copy pixel data from HBITMAP by bottom-up.  
	for (int y = 0; y < nHeight; y++)
	{
		// 从下到上复制数据,因为前面设置高度时是正数。  
		memcpy_s(
			(pixelsDest + y * nLinesize),
			nLinesize,
			(piexlsSrc + (nHeight - y - 1) * nLinesize),
			nLinesize);
	}

	// Copy the data in temporary buffer to pBitmap  
	if (Ok != pBitmap->UnlockBits(&bitmapData))
	{
		delete pBitmap;
	}

	delete[] piexlsSrc;
	return pBitmap;
}

void CElipsePhotoUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
	if (_tcscmp(pstrName, _T("bkimage")) == 0) 
		SetBkImage(pstrValue);
	else
		return __super::SetAttribute(pstrName, pstrValue);
}

void CElipsePhotoUI::SetBkImage(LPCTSTR pStrImage)
{
	__super::SetBkImage(pStrImage);
	
	TImageInfo* data = NULL;
	DWORD mask = 0;
	data = CRenderEngine::LoadImage(pStrImage, NULL, mask);
	if (data)
	{
		m_bkGDIPimage = CreateBitmapFromHBITMAP(data->hBitmap);
	}
	delete data;
}

void CElipsePhotoUI::PaintBkImage(HDC hDC)
{
	if (m_bkGDIPimage)
	{
		// 实际的显示大小
		int nWidth = this->GetWidth();
		int nHeight = this->GetHeight();
		RECT rt = this->GetPos();
		// 内存位图画板,多留2个像素,避免被边框切掉
		Bitmap bitmapTmp(m_bkGDIPimage->GetWidth()+2,m_bkGDIPimage->GetHeight()+2);
		Graphics gBig(&bitmapTmp);
		Graphics g(hDC);
		gBig.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
		GraphicsPath path(FillModeAlternate);
		// 圆形大小
		path.AddEllipse(1,1,m_bkGDIPimage->GetWidth(),m_bkGDIPimage->GetHeight());
		// 已经将圆形图片画到了gBig上了
		gBig.FillPath(&TextureBrush(m_bkGDIPimage), &path);
		SmoothingMode mode = g.GetSmoothingMode();
		g.SetSmoothingMode(SmoothingMode::SmoothingModeHighQuality);
		g.DrawImage(&bitmapTmp, rt.left, rt.top, nWidth, nHeight);
		g.SetSmoothingMode(mode);

	}
}




资源下载

https://download.csdn.net/download/hizhanyue/10438176


记得在创建控件的回调创建哦!

virtual CControlUI* CreateControl(LPCTSTR pstrClass);






  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
nim duilib是一个基于Nim语言开发的UI框架,它提供了丰富的控件库,包括按钮、文本框、列表框等常见的控件。除了内置的控件,它还支持自定义控件的开发。 要开发自定义控件,首先需要理解nim duilib的架构和控件的生命周期。每个控件都有自己的类,通过继承Duilib中的Control类来创建自定义的控件。在这个类中需要重写一系列的方法,比如OnCreate、OnPaint等,来处理自定义控件的创建、绘制等事件。 在OnCreate方法中,可以定义自定义控件的属性和初始化。可以设置控件的尺寸、位置、背景颜色等样式属性。在OnPaint方法中,可以绘制自定义控件的外观。可以使用nim duilib提供的绘图接口来绘制自定义的图形、文本等,以实现想要的外观效果。 除了控件的外观,还需要处理控件的交互事件。可以重写鼠标按下、鼠标移动、鼠标释放等事件方法,来实现控件的拖拽、点击等交互效果。可以使用nim duilib提供的函数来获取鼠标的位置、键盘的状态等信息,以实现与用户交互的功能。 最后,在使用自定义控件时,需要创建一个对应的控件类的实例,并添加到父容器中。可以通过调用父容器的Add控件方法,将自定义控件添加到容器中,并设置控件的位置和尺寸。 总的来说,nim duilib的自定义控件开发提供了丰富的接口和方法,可以根据需求自由定制控件的外观和交互。通过理解框架的架构和控件的生命周期,加上nim语言的灵活性和易用性,可以方便地开发出符合自己需求的自定义控件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值