⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skin.cpp

📁 菜单下加小图标示例,详细源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// VxSkinButton.cpp : implementation file
//

#include "stdafx.h"
#include "Skin.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif 

/////////////////////////////////////////////////////////////////////////////
// Skin
CSkin::CSkin()
{
	m_DrawMode = 1; // normal drawing mode
	m_FocusRectMargin = 0; // disable focus dotted rect
	hClipRgn = NULL; // no clipping region
	m_TextColor = GetSysColor(COLOR_BTNTEXT); // default button text color
	m_button_down = m_tracking = m_Checked = false;
	m_bMask = FALSE;
}

CSkin::~CSkin()
{
	if (hClipRgn)
		DeleteObject(hClipRgn);
	// free clip region
}

BEGIN_MESSAGE_MAP(CSkin, CButton)
	//{{AFX_MSG_MAP(CSkin)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_KILLFOCUS()
	ON_WM_KEYDOWN()
	//}}AFX_MSG_MAP
	//ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
	//ON_MESSAGE(WM_CXSHADE_RADIO, OnRadioInfo)
	ON_MESSAGE(BM_SETCHECK, OnBMSetCheck)
	//ON_MESSAGE(BM_GETCHECK, OnBMGetCheck)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSkin message handlers
void CSkin::PreSubclassWindow()
{
	m_Style = GetButtonStyle(); // get specific BS_ styles
	if ((m_Style & BS_AUTOCHECKBOX) == BS_AUTOCHECKBOX)
		//||((m_Style & BS_CHECKBOX) == BS_CHECKBOX))
	{
		m_Style = BS_CHECKBOX;
	}
	else if ((m_Style & BS_AUTORADIOBUTTON) == BS_AUTORADIOBUTTON)
		//||((m_Style & BS_RADIOBUTTON) == BS_RADIOBUTTON))
	{
		m_Style = BS_RADIOBUTTON;
	}
	else
	{
		m_Style = BS_PUSHBUTTON;
	}

	CButton::PreSubclassWindow();
	ModifyStyle(0, BS_OWNERDRAW);
}

/////////////////////////////////////////////////////////////////////////////
// doesn't erase the button background
BOOL CSkin::OnEraseBkgnd(CDC *pDC)
{
	return 0;
}

/////////////////////////////////////////////////////////////////////////////
void CSkin::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	ASSERT(lpDrawItemStruct);
	//TRACE("* Captured: %08X\n", ::GetCapture());

	// Check if the button state in not in inconsistent mode...
	POINT mouse_position;

	if ((m_button_down) && (::GetCapture() == m_hWnd) && (::GetCursorPos
		(&mouse_position)))
	{
		if (::WindowFromPoint(mouse_position) == m_hWnd)
		{
			if ((GetState() &BST_PUSHED) != BST_PUSHED)
			{
				//TRACE("* Inconsistency up detected! Fixing.\n");
				SetState(TRUE);
				return;
			}
		}
		else
		{
			if ((GetState() & BST_PUSHED) == BST_PUSHED)
			{	
				//TRACE("* Inconsistency up detected! Fixing.\n");
				SetState(FALSE);
				return;
			}
		}
	}

	//TRACE("* Drawing: %08x\n", lpDrawItemStruct->itemState);
	CString sCaption;
	CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); // get device context
	RECT r = lpDrawItemStruct->rcItem; // context rectangle
	int cx = r.right - r.left; // get width
	int cy = r.bottom - r.top; // get height
	// get text box position
	RECT tr = 
	{
		r.left + m_FocusRectMargin + 2, r.top, r.right - m_FocusRectMargin - 2,
		r.bottom
	};

	GetWindowText(sCaption); // get button text
	pDC->SetBkMode(TRANSPARENT);

	// Select the correct skin 
	if (lpDrawItemStruct->itemState & ODS_DISABLED)
	{
		// DISABLED BUTTON
		DrawBitmap(pDC, 3, r, m_DrawMode);
		// if needed, draw the standard 3D rectangular border
		if (m_Border)
			pDC->DrawEdge(&r, EDGE_RAISED, BF_RECT);
		// paint the etched button text
		pDC->SetTextColor(GetSysColor(COLOR_3DHILIGHT));
		pDC->DrawText(sCaption, &tr, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
		pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
		OffsetRect(&tr, -1, -1);
		pDC->DrawText(sCaption, &tr, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
	}
	else
	{
		// SELECTED (DOWN) BUTTON
		if ((lpDrawItemStruct->itemState &ODS_SELECTED) || m_Checked)
		{
			DrawBitmap(pDC, 2, r, m_DrawMode);
			OffsetRect(&tr, 2, 1); // shift text
			// if needed, draw the standard 3D rectangular border
			if (m_Border)
				pDC->DrawEdge(&r, EDGE_SUNKEN, BF_RECT);
		}
		else
		{
			// DEFAULT BUTTON
			if (m_tracking)
			{
				DrawBitmap(pDC, 1, r, m_DrawMode);
			}
			else
			{
				if ((lpDrawItemStruct->itemState &ODS_FOCUS))
				{
					DrawBitmap(pDC, 0, r, m_DrawMode);
				}
				else
				{
					DrawBitmap(pDC, 0, r, m_DrawMode);
				}
			}
			// if needed, draw the standard 3D rectangular border
			if (m_Border)
			{
				pDC->DrawEdge(&r, EDGE_RAISED, BF_RECT);
			}
		}
		// paint the focus rect
		if ((lpDrawItemStruct->itemState & ODS_FOCUS) && (m_FocusRectMargin > 0))
		{
			r.left += m_FocusRectMargin;
			r.top += m_FocusRectMargin;
			r.right -= m_FocusRectMargin;
			r.bottom -= m_FocusRectMargin;
			DrawFocusRect(lpDrawItemStruct->hDC, &r);
		}
		// paint the enabled button text
		pDC->SetTextColor(m_TextColor);
		pDC->DrawText(sCaption, &tr, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
	}
}

/////////////////////////////////////////////////////////////////////////////
int CSkin::GetBitmapWidth(HBITMAP hBitmap)
{
	BITMAP bm;

	GetObject(hBitmap, sizeof(BITMAP), (PSTR)&bm);

	return bm.bmWidth;
}

/////////////////////////////////////////////////////////////////////////////
int CSkin::GetBitmapHeight(HBITMAP hBitmap)
{
	BITMAP bm;

	GetObject(hBitmap, sizeof(BITMAP), (PSTR)&bm);

	return bm.bmHeight;
}

/////////////////////////////////////////////////////////////////////////////
void CSkin::DrawBitmap(CDC *dc, int nState, RECT r, int DrawMode)
{
	int cx = r.right - r.left;
	int cy = r.bottom - r.top;

	cx = m_ButtonSize.cx;
	cy = m_ButtonSize.cy;

	if (m_bMask)
	{
		CDC dcBmp;
		dcBmp.CreateCompatibleDC(dc);
		dcBmp.SelectObject(m_bImage);
		CDC hdcMem;
		hdcMem.CreateCompatibleDC(dc);
		CBitmap hBitmap;
		hBitmap.CreateCompatibleBitmap(dc, cx, cy);
		hdcMem.SelectObject(hBitmap);

		hdcMem.BitBlt(r.left, r.top, cx, cy, dc, 0, 0, SRCCOPY);   //将源位图复制到目标位图
		if (!DrawMode)
		{
			hdcMem.BitBlt(r.left, r.top, cx, cy, &dcBmp, m_ButtonSize.cx
				*nState, 0, SRCINVERT);//将目标位图与源位图进行“异或”操作后输出
			hdcMem.BitBlt(r.left, r.top, cx, cy, &dcBmp, m_ButtonSize.cx *4, 0,
				SRCAND);//将目标位图与源位图使用“与”操作合并
			hdcMem.BitBlt(r.left, r.top, cx, cy, &dcBmp, m_ButtonSize.cx
				*nState, 0, SRCINVERT);
		}
		else
		{
			hdcMem.StretchBlt(r.left, r.top, cx, cy, &dcBmp, m_ButtonSize.cx
				*nState, 0, m_ButtonSize.cx, m_ButtonSize.cy, SRCINVERT);
			hdcMem.StretchBlt(r.left, r.top, cx, cy, &dcBmp, m_ButtonSize.cx *4,
				0, m_ButtonSize.cx, m_ButtonSize.cy, SRCAND);
			hdcMem.StretchBlt(r.left, r.top, cx, cy, &dcBmp, m_ButtonSize.cx
				*nState, 0, m_ButtonSize.cx, m_ButtonSize.cy, SRCINVERT);
		}
		dc->BitBlt(r.left, r.top, cx, cy, &hdcMem, 0, 0, SRCCOPY); //将源位图复制到目标位图

		hdcMem.DeleteDC();
		hBitmap.DeleteObject();
	}
	else
	{
		CDC dcBmp;
		dcBmp.CreateCompatibleDC(dc);
		dcBmp.SelectObject(m_bImage);

		if (!DrawMode)
		{
			dc->BitBlt(r.left, r.top, cx, cy, &dcBmp, m_ButtonSize.cx *nState,
				0, SRCCOPY);
		}
		else
		{
			dc->StretchBlt(r.left, r.top, cx, cy, &dcBmp, m_ButtonSize.cx
				*nState, 0, m_ButtonSize.cx, m_ButtonSize.cy, SRCCOPY);
		}
		DeleteDC(dcBmp);
	}
}

/////////////////////////////////////////////////////////////////////////////
void CSkin::FillWithBitmap(CDC *dc, HBITMAP hbmp, RECT r)
{
	if (!hbmp)
		return;
	CDC memdc;

	memdc.CreateCompatibleDC(dc);
	memdc.SelectObject(hbmp);

	int w = r.right - r.left;
	int h = r.bottom - r.top;
	int x, y, z;
	int bx = GetBitmapWidth(hbmp);
	int by = GetBitmapHeight(hbmp);

	for (y = r.top; y < h; y += by)
	{
		if ((y + by) > h)
		{
			by = h - y;
		}

		z = bx;

		for (x = r.left; x < w; x += z)
		{
			if ((x + z) > w)
			{
				z = w - x;
			}

			dc->BitBlt(x, y, z, by, &memdc, 0, 0, SRCCOPY);
		}
	}
	DeleteDC(memdc);
}

/////////////////////////////////////////////////////////////////////////////
void CSkin::SetSkin(UINT nBitmap, short drawmode, short border, short
							margin, BOOL bMask)
{
	m_bImage.DeleteObject(); // free previous allocated bitmap
	m_bImage.LoadBitmap(nBitmap);
	m_DrawMode = max(0, min(drawmode, 2));
	m_Border = border;
	m_FocusRectMargin = max(0, margin);
	m_bMask = bMask;

	if (!m_bMask)
	{
		m_ButtonSize.cx = GetBitmapWidth(m_bImage) / 4;
		//m_ButtonSize.cx = GetBitmapWidth(m_bImage);
		m_ButtonSize.cy = GetBitmapHeight(m_bImage);
	}
	else
	{
		m_ButtonSize.cx = GetBitmapWidth(m_bImage) / 5;
		m_ButtonSize.cy = GetBitmapHeight(m_bImage);
	}
	SetWindowPos(&wndTop, 0, 0, m_ButtonSize.cx, m_ButtonSize.cy, SWP_NOMOVE |
		SWP_NOZORDER);
}

/////////////////////////////////////////////////////////////////////////////
HRGN CSkin::CreateRgnFromBitmap(HBITMAP hBmp, COLORREF color)
{
	if (!hBmp)
		return NULL;

	BITMAP bm;
	GetObject(hBmp, sizeof(BITMAP), &bm); // get bitmap attributes

	CDC dcBmp;
	dcBmp.CreateCompatibleDC(GetDC()); 
	// Creates a memory device context for the bitmap
	dcBmp.SelectObject(hBmp); // selects the bitmap in the device context

	const DWORD RDHDR = sizeof(RGNDATAHEADER);
	const DWORD MAXBUF = 40; // size of one block in RECTs
	// (i.e. MAXBUF * sizeof(RECT) in bytes)
	LPRECT pRects;
	DWORD cBlocks = 0; // number of allocated blocks

	INT i, j; // current position in mask image
	INT first = 0; // left position of current scan line
	// where mask was found
	bool wasfirst = false; // set when if mask was found in current scan line
	bool ismask; // set when current color is mask color

	// allocate memory for region data
	RGNDATAHEADER *pRgnData = (RGNDATAHEADER*)new BYTE[RDHDR + ++cBlocks
		*MAXBUF * sizeof(RECT)];
	memset(pRgnData, 0, RDHDR + cBlocks * MAXBUF * sizeof(RECT));
	// fill it by default
	pRgnData->dwSize = RDHDR;
	pRgnData->iType = RDH_RECTANGLES;
	pRgnData->nCount = 0;
	for (i = 0; i < bm.bmHeight; i++)
	{
		for (j = 0; j < bm.bmWidth; j++)
		{
			// get color
			ismask = (dcBmp.GetPixel(j, bm.bmHeight - i - 1) != color);
			// place part of scan line as RECT region if transparent color found after mask color or
			// mask color found at the end of mask image
			if (wasfirst && ((ismask && (j == (bm.bmWidth - 1))) || (ismask ^ 
				(j < bm.bmWidth))))
			{
				// get offset to RECT array if RGNDATA buffer
				pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR);
				// save current RECT
				pRects[pRgnData->nCount++] = CRect(first, bm.bmHeight - i - 1,
					j + (j == (bm.bmWidth - 1)), bm.bmHeight - i);
				// if buffer full reallocate it
				if (pRgnData->nCount >= cBlocks *MAXBUF)
				{
					LPBYTE pRgnDataNew = new BYTE[RDHDR + ++cBlocks *MAXBUF *
						sizeof(RECT)];
					memcpy(pRgnDataNew, pRgnData, RDHDR + (cBlocks - 1) *MAXBUF
						* sizeof(RECT));
					delete pRgnData;
					pRgnData = (RGNDATAHEADER*)pRgnDataNew;
				}
				wasfirst = false;
			}
			else if (!wasfirst && ismask)
				// set wasfirst when mask is found
			{
				first = j;
				wasfirst = true;
			}
		}
	}
	dcBmp.DeleteDC(); //release the bitmap
	// create region
	/* Under WinNT the ExtCreateRegion returns NULL (by Fable@aramszu.net) */
	//HRGN hRgn = ExtCreateRegion(NULL, RDHDR + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData);
	/* ExtCreateRegion replacement { */
	HRGN hRgn = CreateRectRgn(0, 0, 0, 0);
	ASSERT(hRgn != NULL);
	pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR);
	for (i = 0; i < (int)pRgnData->nCount; i++)
	{
		HRGN hr = CreateRectRgn(pRects[i].left, pRects[i].top, pRects[i].right,
			pRects[i].bottom);
		VERIFY(CombineRgn(hRgn, hRgn, hr, RGN_OR) != ERROR);
		if (hr)
			DeleteObject(hr);
	}
	ASSERT(hRgn != NULL);
	/* } ExtCreateRegion replacement */

	delete pRgnData;
	return hRgn;
}

/////////////////////////////////////////////////////////////////////////////
COLORREF CSkin::SetTextColor(COLORREF new_color)
{
	COLORREF tmp_color = m_TextColor;

	m_TextColor = new_color;

	return tmp_color; //returns the previous color
}

/////////////////////////////////////////////////////////////////////////////
/*void CSkin::SetToolTipText(CString s)
{
if (m_tooltip.m_hWnd == NULL) 
{
if (m_tooltip.Create(this))     // first assignment
{
if (m_tooltip.AddTool(this, (LPCTSTR)s))
{
m_tooltip.Activate(1);
}
}
} 
else 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -