VC++自绘不太熟,搞了大半天终于实现了。
自己全部画控件又不能用VS的界面工具箱直接放弃,还是只能在MFC的基础上拓展吧。
使用简单的说明一下。首先要在stdafx.h中添加以下代码
然后在App里面添加以下代码
添加一个变量,类型为CBUTTONEX,也可以手动附加,里面有Attach函数,关联到界面的BUTTON
cpp文件
其它要绘制用到的函数
自己全部画控件又不能用VS的界面工具箱直接放弃,还是只能在MFC的基础上拓展吧。
使用简单的说明一下。首先要在stdafx.h中添加以下代码
#ifndef GDIPLUS #define GDIPLUS #includeusing namespace Gdiplus; #pragma comment(lib, "gdiplus.lib") #endif
然后在App里面添加以下代码
//不添加此代码对IMAGE创建返回一直为NULL
ULONG_PTR gdiplusToken;//构造函数完成
GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
//ExitInstance
Gdiplus::GdiplusShutdown(gdiplusToken);
添加一个变量,类型为CBUTTONEX,也可以手动附加,里面有Attach函数,关联到界面的BUTTON
#pragma once
#include "resource.h"
// CButtonEx
class CButtonEx : public CButton
{
public:
Image *m_pImage;
Image *m_pTemp;
CSize m_sizeImage;
char szTitle[MAX_PATH];
enumButtonState m_buttonState;
CRect m_rc;
UINT m_frameCount;
CButtonEx();
virtual ~CButtonEx();
void SetBitmap(UINT nResourceID=IDB_PNG_DEFAULT,UINT nFrameCount=4);
virtual void OnFinalRelease();
protected:
DECLARE_MESSAGE_MAP()
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
BOOL Attach(const UINT nID, CWnd* pParent);
void OnLButtonDown(UINT nFlags, CPoint point);
void OnLButtonUp(UINT nFlags, CPoint point);
void OnMouseMove(UINT nFlags, CPoint point);
void DrawContent(CDC &MemDC);
afx_msg void OnMouseLeave();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
virtual void PreSubclassWindow();
};
cpp文件
// ButtonEx.cpp : 实现文件
//
#include "stdafx.h"
#include "ButtonEx.h"
// CButtonEx
CButtonEx::CButtonEx()
{
m_pImage = NULL;
m_pTemp = NULL;
m_buttonState = bsNormal;
}
CButtonEx::~CButtonEx()
{
if(m_pImage != NULL)
delete m_pImage;
if(m_pTemp != NULL)
delete m_pTemp;
}
void CButtonEx::OnFinalRelease()
{
// 释放了对自动化对象的最后一个引用后,将调用
// OnFinalRelease。基类将自动
// 删除该对象。在调用该基类之前,请添加您的
// 对象所需的附加清理代码。
CWnd::OnFinalRelease();
}
BEGIN_MESSAGE_MAP(CButtonEx, CWnd)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_MOUSELEAVE()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
void CButtonEx::SetBitmap(UINT nResourceID,UINT nFrameCount)
{
ImageFromID(nResourceID,m_pImage);
this->m_frameCount = nFrameCount;
m_sizeImage.SetSize(m_pImage->GetWidth() / m_frameCount, m_pImage->GetHeight());
}
// CButtonEx 消息处理程序
void CButtonEx::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CWnd::OnLButtonDown(nFlags, point);
m_buttonState = bsDown;
Invalidate();
}
void CButtonEx::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CWnd::OnLButtonUp(nFlags, point);
if (m_buttonState == bsDown)
{
if(IsWindowEnabled())
m_buttonState = bsHover;
else
m_buttonState = bsDisable;
}
}
void CButtonEx::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CWnd::OnMouseMove(nFlags, point);
//TRACKMOUSEEVENT不加此结构体OnMouseLeave不会被调用
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.hwndTrack = this->m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
_TrackMouseEvent(&tme);
m_buttonState = bsHover;
Invalidate();
}
void CButtonEx::OnMouseLeave()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CButton::OnMouseLeave();
if(IsWindowEnabled())
m_buttonState = bsNormal;
else
m_buttonState = bsDisable;
Invalidate();
}
//手动附加到窗口控件
BOOL CButtonEx::Attach(const UINT nID, CWnd* pParent)
{
if (!SubclassDlgItem(nID, pParent))
return FALSE;
return TRUE;
}
void CButtonEx::DrawContent(CDC &MemDC)
{
Graphics g(MemDC);
g.DrawImage(m_pTemp,0,0);
if((UINT)m_buttonState < m_frameCount)
DrawImageFrame(g, m_pImage, m_rc, m_buttonState*(REAL)m_sizeImage.cx, 0, (REAL)m_sizeImage.cx, (REAL)m_sizeImage.cy, 3);
COLORREF clrOld = MemDC.SetTextColor(RGB(0, 28, 48));
CFont *pOldFont = MemDC.SelectObject(GetFont());
MemDC.DrawText(szTitle, &m_rc, DT_VCENTER | DT_CENTER | DT_SINGLELINE | DT_WORD_ELLIPSIS);
MemDC.SelectObject(pOldFont);
MemDC.SetTextColor(clrOld);
}
void CButtonEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC *pDc = GetDC();
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CButton::OnPaint()
pDc->SetBkMode(TRANSPARENT);
CRect rcClient;
GetClientRect(&rcClient);
CDC MemDC;
MemDC.CreateCompatibleDC(pDc);
MemDC.SetBkMode(TRANSPARENT);//不设置透明文字会有背景
CBitmap memBmp;
memBmp.CreateCompatibleBitmap(pDc, rcClient.Width(), rcClient.Height());
CBitmap *pOldmap = MemDC.SelectObject(&memBmp);
//先填充一下原先的背景
//MemDC.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), pDc, 0, 0, SRCCOPY);
DrawContent(MemDC);//直接画无背景
//复制到原来的CDC
pDc->BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &MemDC, 0, 0, SRCCOPY);
//MemDC.SelectObject(pOldmap);
//旧图应该是不存在的,直接删除
pOldmap->DeleteObject();
MemDC.DeleteDC();
memBmp.DeleteObject();
ReleaseDC(&MemDC);
ReleaseDC(pDc);
}
BOOL CButtonEx::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//不要背景
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CButton::OnPaint()
CDC MemDC;
CBitmap memBmp;
MemDC.CreateCompatibleDC(pDC);
memBmp.CreateCompatibleBitmap(pDC, m_rc.Width(), m_rc.Height());
CBitmap *pOldmap = MemDC.SelectObject(&memBmp);
//先填充一下原先的背景
MemDC.BitBlt(m_rc.left, m_rc.top, m_rc.Width(), m_rc.Height(), pDC, 0, 0, SRCCOPY);
//绘制内容
if(m_pTemp == NULL)
BitmapToImage(&memBmp,m_pTemp);
//旧图应该是黑的无用,直接删除
pOldmap->DeleteObject();
MemDC.DeleteDC();
memBmp.DeleteObject();
ReleaseDC(&MemDC);
return TRUE;
}
void CButtonEx::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
SetButtonStyle(GetButtonStyle()|BS_OWNERDRAW);//修改为自绘模式
GetClientRect(&m_rc);
GetWindowTextA(szTitle,sizeof(szTitle));//复制内容
SetBitmap();
CButton::PreSubclassWindow();
}
其它要绘制用到的函数
#pragma once
#include "stdafx.h"
#include "MDraw.h"
void BitmapToImage(CBitmap *pBitmap,Image* &img)
{
//拿到位图的句柄 Bitmap是Image的子类
HBITMAP hBmp = (HBITMAP)pBitmap->GetSafeHandle();
//创建一个从位图句柄的Bitmap位图
Bitmap *bmp = new Bitmap(hBmp,NULL);
//创建一个临时的位图
Bitmap *temp = new Bitmap(bmp->GetWidth(),bmp->GetHeight(),PixelFormat24bppRGB);
Graphics g(temp);//临时位图的画笔
g.DrawImage(bmp,0,0);//将数据画到临时位图上
img = temp;
//最后删除位图不然会内存泄漏
delete bmp;
}
void ImageFromID(int IDB_ID,Image* &_outImg)
{
LPCTSTR lpType = "PNG";
if(lpType == RT_BITMAP)
{
//GDI+ can not load RT_BITMAP resouce,
//because they are predefined resource,
//they don't contains the image file header.
return;
}
HINSTANCE hInst = AfxGetResourceHandle();
HRSRC hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(IDB_ID),lpType);
if (!hRsrc)
return;
DWORD len = SizeofResource(hInst, hRsrc);
BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
if (!lpRsrc)
return;
HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
memcpy(pmem,lpRsrc,len);
IStream* pstm;
if (CreateStreamOnHGlobal(m_hMem,FALSE,&pstm) == S_OK)
{
_outImg = new Image(pstm);
GlobalUnlock(m_hMem);
pstm->Release();
}
FreeResource(lpRsrc);
}
// 画图片边框
void DrawImageFrame(Graphics &graphics, Image *pIamge, const CRect &rcControl, REAL nX, REAL nY, REAL nW, REAL nH, REAL nFrameSide/* = 3*/)
{
// 左上角
graphics.DrawImage(pIamge, RectF((REAL)rcControl.left ,(REAL)rcControl.top, nFrameSide, nFrameSide),
nX, nY, nFrameSide, nFrameSide, UnitPixel);
// 左中边框
graphics.DrawImage(pIamge, RectF((REAL)rcControl.left ,(REAL)rcControl.top + nFrameSide, nFrameSide, (REAL)rcControl.Height() - 2 * nFrameSide),
nX, nY + nFrameSide, nFrameSide, nH - 2 * nFrameSide, UnitPixel);
// 左下角
graphics.DrawImage(pIamge, RectF((REAL)rcControl.left ,(REAL)rcControl.bottom - nFrameSide, nFrameSide, nFrameSide),
nX, nY + nH - nFrameSide, nFrameSide, nFrameSide, UnitPixel);
// 上中边框
graphics.DrawImage(pIamge, RectF((REAL)rcControl.left + nFrameSide ,(REAL)rcControl.top, (REAL)rcControl.Width() - 2 * nFrameSide, nFrameSide),
nX + nFrameSide, nY, nW - 2 * nFrameSide, nFrameSide, UnitPixel);
// 右上角
graphics.DrawImage(pIamge, RectF((REAL)rcControl.right - nFrameSide ,(REAL)rcControl.top, nFrameSide, nFrameSide),
nX + nW - nFrameSide, nY, nFrameSide, nFrameSide, UnitPixel);
// 右中边框
graphics.DrawImage(pIamge, RectF((REAL)rcControl.right - nFrameSide ,(REAL)rcControl.top + nFrameSide, nFrameSide, (REAL)rcControl.Height() - 2 * nFrameSide),
nX + nW - nFrameSide, nY + nFrameSide, nFrameSide, nH - 2 * nFrameSide, UnitPixel);
// 右下角
graphics.DrawImage(pIamge, RectF((REAL)rcControl.right - nFrameSide ,(REAL)rcControl.bottom - nFrameSide, nFrameSide, nFrameSide),
nX + nW - nFrameSide, nY + nH - nFrameSide, nFrameSide, nFrameSide, UnitPixel);
// 下中边框
graphics.DrawImage(pIamge, RectF((REAL)rcControl.left + nFrameSide ,(REAL)rcControl.bottom - nFrameSide, (REAL)rcControl.Width() - 2 * nFrameSide, nFrameSide),
nX + nFrameSide, nY + nH - nFrameSide, nW - 2 * nFrameSide, nFrameSide, UnitPixel);
// 中间
graphics.DrawImage(pIamge, RectF((REAL)rcControl.left + nFrameSide ,(REAL)rcControl.top + nFrameSide, (REAL)rcControl.Width() - 2 * nFrameSide, (REAL)rcControl.Height() - 2 * nFrameSide),
nX + nFrameSide, nY + nFrameSide, nW - 2 * nFrameSide,nH - 2 * nFrameSide, UnitPixel);
}
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2313
- 用户1336
- 访客11746629
每日一句
Climb high, see far, and feel young.
登高望远,心也年轻。
登高望远,心也年轻。
新会员