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

📄 skinbutton.cpp

📁 机械手IPC控制器伺服运动程序
💻 CPP
字号:
#include "stdafx.h"
#include "SkinButton.h"
#include "Resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define GET_X_LPARAM(lp)                        ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp)                        ((int)(short)HIWORD(lp))

LRESULT CALLBACK SkinButtonSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	WNDPROC		OldWndProc=NULL;
	CSkinButton	*pSkinButton=NULL;

	// 首先获取以前保存的原始的WndProc的地址。
	OldWndProc=(WNDPROC)GetProp(hwnd,"OldWndProc");
	ASSERT(OldWndProc != NULL);

	// 然后是这个控件的SkinButton对象。
	pSkinButton=(CSkinButton*)GetProp(hwnd,"SkinButtonObj");
	ASSERT(pSkinButton != NULL);

	// 然后开始处理消息。
	
	if (uMsg == WM_DRAWITEM)
	{
		pSkinButton->DrawItem((LPDRAWITEMSTRUCT)lParam);
		return TRUE;
	}
	else if (uMsg == WM_ERASEBKGND)
	{
		// NOTE: 处理这些消息的时候,必须特别注意hDC的选用,如果参数中传递了HDC,
		// 那么就必须用参数中的。不能再使用GetDC返回的。否则就会出现绘画错误的现象。
		TRACE("SkinButton receive WM_ERASEBKGND message.\n");
		CDC			DC;
		DC.Attach((HDC)wParam);
		pSkinButton->OnEraseBkgnd(&DC);
		DC.Detach();	// 不是我们创建的DC,我们不能销毁它。
		return 1;
	}
	else if (uMsg == WM_PAINT)
	{
		TRACE("SkinButton receive WM_PAINT message.\n");
		pSkinButton->OnPaint();
	}
	else if (uMsg == WM_DESTROY)
	{
		// 窗体注销,我们把我们所增加的Prop去掉。
		RemoveProp(hwnd,"OldWndProc");
		RemoveProp(hwnd,"SkinButtonObj");
		
		// 还原以前的WNDPROC
		SetWindowLong(hwnd,GWL_WNDPROC,(LONG)OldWndProc);

		// 删除CSkinButton对象。
		pSkinButton->m_hWnd=NULL;
		delete pSkinButton;
		
		return CallWindowProc(OldWndProc,hwnd,uMsg,wParam,lParam);
	}
	else if (uMsg == WM_MOUSEMOVE)
	{
		CPoint			Point;
		Point.x=GET_X_LPARAM(lParam);
		Point.y=GET_Y_LPARAM(lParam);

		pSkinButton->OnMouseMove((UINT)wParam,Point);
	}
	else if (uMsg == WM_MOUSEHOVER)
	{
		pSkinButton->OnMouseHover(wParam,lParam);
	}
	else if (uMsg == WM_MOUSELEAVE)
	{
		pSkinButton->OnMouseLeave(wParam,lParam);
	}

	return CallWindowProc(OldWndProc,hwnd,uMsg,wParam,lParam);
}




/////////////////////////////////////////////////////////////////////////////
// CSkinButton

CSkinButton::CSkinButton()
{
	m_nXPos=10;
	m_nYPos=6;

	m_nNormalBitmapResID=IDB_BITMAP_NORMAL;
	m_nFocusBitmapResID=IDB_BITMAP_FOCUS;
	m_nHoverBitmapResID=0;
	m_nPressedBitmapResID=IDB_BITMAP_DOWN;

	m_bOverControl=FALSE;
	m_bSelected=FALSE;
	m_bTracking=FALSE;

	m_bEnableStretch=TRUE;

//#ifndef SKIN_BUTTON_INIT_MACRO
//#error SKIN_BUTTON_INIT_MACRO not defined. CSkinButton can not work correctly without a SKIN_BUTTON_INIT_MACRO macro. 
//#error see the document at the top of SkinButton.cpp for more information.
//#endif
	
//	SKIN_BUTTON_INIT_MACRO

}

CSkinButton::~CSkinButton()
{
}


BEGIN_MESSAGE_MAP(CSkinButton, CButton)
	//{{AFX_MSG_MAP(CSkinButton)
	//ON_WM_ERASEBKGND()								// 在通过MFC调用时,我们不用自己处理这两个消息,MFC
	//ON_WM_PAINT()										// 会给我们处理好的.如果多次一举,会造成死循环的.
	//}}AFX_MSG_MAP
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
	ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSkinButton message handlers
void CSkinButton::DrawContent(CMemDC &pDC,UINT state,CRect rect,BOOL Focus,CString &strText)
{
	CBitmap			MyBitMap;
	CDC				MyBitmapDC;

	MyBitmapDC.CreateCompatibleDC(NULL);

	if (Focus)
	{
		if (state & ODS_SELECTED)
		{
			MyBitMap.LoadBitmap(m_nPressedBitmapResID);
		}
		else
		{
			MyBitMap.LoadBitmap(m_nFocusBitmapResID);
		}
	}
	else if ((!m_bOverControl) || (m_nHoverBitmapResID == 0))
	{
		MyBitMap.LoadBitmap(m_nNormalBitmapResID);
	}
	else if (m_bOverControl)
	{
		MyBitMap.LoadBitmap(m_nHoverBitmapResID);
	}
	
	CBitmap* pOldBitmap=NULL;
	VERIFY((pOldBitmap=MyBitmapDC.SelectObject(&MyBitMap)) != NULL);


	// 这部分代码把图片进行切割后复制到目标区域。
	CSize    sizeBitMap;
	BITMAP	 BitMapStruct={NULL};
	MyBitMap.GetBitmap(&BitMapStruct);
	sizeBitMap.cx=BitMapStruct.bmWidth;
	sizeBitMap.cy=BitMapStruct.bmHeight;


	// 下面是侧面条。
	PAINTINFO		PaintInfo[5]={NULL};

	// 上边的侧边条
	PaintInfo[0].sizeBlock.cx=sizeBitMap.cx-m_nXPos*2;
	PaintInfo[0].sizeBlock.cy=m_nYPos;
	PaintInfo[0].rectBlockSrc.left=m_nXPos;
	PaintInfo[0].rectBlockSrc.top=0;
	PaintInfo[0].rectBlockSrc.right=sizeBitMap.cx-m_nXPos;
	PaintInfo[0].rectBlockSrc.bottom=m_nYPos;
	PaintInfo[0].rectBlockDest.left=m_nXPos;
	PaintInfo[0].rectBlockDest.top=0;
	PaintInfo[0].rectBlockDest.right=rect.right-m_nXPos;
	PaintInfo[0].rectBlockDest.bottom=m_nYPos;


	// 下边的条
	PaintInfo[1].sizeBlock.cx=sizeBitMap.cx-m_nXPos*2;
	PaintInfo[1].sizeBlock.cy=m_nYPos;
	PaintInfo[1].rectBlockSrc.left=m_nXPos;
	PaintInfo[1].rectBlockSrc.top=sizeBitMap.cy-m_nYPos;
	PaintInfo[1].rectBlockSrc.right=sizeBitMap.cx-m_nXPos;
	PaintInfo[1].rectBlockSrc.bottom=sizeBitMap.cy;
	PaintInfo[1].rectBlockDest.left=m_nXPos;
	PaintInfo[1].rectBlockDest.top=rect.bottom-m_nYPos;
	PaintInfo[1].rectBlockDest.right=rect.right-m_nXPos;
	PaintInfo[1].rectBlockDest.bottom=rect.bottom;

	// 左边的条
	PaintInfo[2].sizeBlock.cx=m_nXPos;
	PaintInfo[2].sizeBlock.cy=sizeBitMap.cy-m_nYPos*2;
	PaintInfo[2].rectBlockSrc.left=0;
	PaintInfo[2].rectBlockSrc.top=m_nYPos;
	PaintInfo[2].rectBlockSrc.right=m_nXPos;
	PaintInfo[2].rectBlockSrc.bottom=sizeBitMap.cy-m_nYPos;
	PaintInfo[2].rectBlockDest.left=0;
	PaintInfo[2].rectBlockDest.top=m_nYPos;
	PaintInfo[2].rectBlockDest.right=m_nXPos;
	PaintInfo[2].rectBlockDest.bottom=rect.bottom-m_nYPos;

	// 右边的条
	PaintInfo[3].sizeBlock.cx=m_nXPos;
	PaintInfo[3].sizeBlock.cy=sizeBitMap.cy-m_nYPos*2;
	PaintInfo[3].rectBlockSrc.left=sizeBitMap.cx-m_nXPos;
	PaintInfo[3].rectBlockSrc.top=m_nYPos;
	PaintInfo[3].rectBlockSrc.right=sizeBitMap.cx;
	PaintInfo[3].rectBlockSrc.bottom=sizeBitMap.cy-m_nYPos;
	PaintInfo[3].rectBlockDest.left=rect.right-m_nXPos;
	PaintInfo[3].rectBlockDest.top=m_nYPos;
	PaintInfo[3].rectBlockDest.right=rect.right;
	PaintInfo[3].rectBlockDest.bottom=rect.bottom-m_nYPos;

	// 中间的部分。
	PaintInfo[4].sizeBlock.cx=sizeBitMap.cx-m_nXPos*2;
	PaintInfo[4].sizeBlock.cy=sizeBitMap.cy-m_nYPos*2;
	PaintInfo[4].rectBlockSrc.left=m_nXPos;
	PaintInfo[4].rectBlockSrc.top=m_nYPos;
	PaintInfo[4].rectBlockSrc.right=sizeBitMap.cx-m_nXPos;
	PaintInfo[4].rectBlockSrc.bottom=sizeBitMap.cy-m_nYPos;
	PaintInfo[4].rectBlockDest.left=m_nXPos;
	PaintInfo[4].rectBlockDest.top=m_nYPos;
	PaintInfo[4].rectBlockDest.right=rect.right-m_nXPos;
	PaintInfo[4].rectBlockDest.bottom=rect.bottom-m_nYPos;


	for (int i=0;i<5;i++)
	{
		PAINTINFO		OnePaintInfo=PaintInfo[i];
		
		if (!m_bEnableStretch)
		{
			if ((i == 0) || (i == 1))
			{
				int			xPos=OnePaintInfo.rectBlockDest.left;
				while (xPos <= OnePaintInfo.rectBlockDest.right)
				{
					pDC->BitBlt(xPos,OnePaintInfo.rectBlockDest.top,
								OnePaintInfo.sizeBlock.cx,
								OnePaintInfo.sizeBlock.cy,
								&MyBitmapDC,OnePaintInfo.rectBlockSrc.left,OnePaintInfo.rectBlockSrc.top,
								SRCCOPY);
					xPos+=OnePaintInfo.sizeBlock.cx;
				}
			}
			else if ((i == 2) || (i == 3))
			{
				int			yPos=OnePaintInfo.rectBlockDest.top;
				while (yPos <= OnePaintInfo.rectBlockDest.bottom)
				{
					pDC->BitBlt(OnePaintInfo.rectBlockDest.left,yPos,
								OnePaintInfo.sizeBlock.cx,
								OnePaintInfo.sizeBlock.cy,
								&MyBitmapDC,OnePaintInfo.rectBlockSrc.left,OnePaintInfo.rectBlockSrc.top,
								SRCCOPY);
					yPos+=OnePaintInfo.sizeBlock.cy;
				}
			}
			else
			{
				pDC->StretchBlt(OnePaintInfo.rectBlockDest.left,OnePaintInfo.rectBlockDest.top,
						OnePaintInfo.rectBlockDest.right-OnePaintInfo.rectBlockDest.left,
						OnePaintInfo.rectBlockDest.bottom-OnePaintInfo.rectBlockDest.top,
					    &MyBitmapDC,OnePaintInfo.rectBlockSrc.left,OnePaintInfo.rectBlockSrc.top,
						OnePaintInfo.sizeBlock.cx,OnePaintInfo.sizeBlock.cy,
					    SRCCOPY);
			}
		}
		else 
		{
			pDC->StretchBlt(OnePaintInfo.rectBlockDest.left,OnePaintInfo.rectBlockDest.top,
						OnePaintInfo.rectBlockDest.right-OnePaintInfo.rectBlockDest.left,
						OnePaintInfo.rectBlockDest.bottom-OnePaintInfo.rectBlockDest.top,
					    &MyBitmapDC,OnePaintInfo.rectBlockSrc.left,OnePaintInfo.rectBlockSrc.top,
						OnePaintInfo.sizeBlock.cx,OnePaintInfo.sizeBlock.cy,
					    SRCCOPY);
		}
	}


	// 首先是左上角。
	pDC->BitBlt(0,0,m_nXPos,m_nYPos,&MyBitmapDC,0,0,SRCCOPY);
	
	// 然后是右上角
	pDC->BitBlt(rect.right-m_nXPos,0,m_nXPos,m_nYPos,&MyBitmapDC,sizeBitMap.cx-m_nXPos,0,SRCCOPY);

	// 左下角
	pDC->BitBlt(0,rect.bottom-m_nYPos,m_nXPos,m_nYPos,&MyBitmapDC,0,sizeBitMap.cy-m_nYPos,SRCCOPY);
	
	// 右下角
	pDC->BitBlt(rect.right-m_nXPos,rect.bottom-m_nYPos,m_nXPos,m_nYPos,&MyBitmapDC,sizeBitMap.cx-m_nXPos,sizeBitMap.cy-m_nYPos,SRCCOPY);

	MyBitmapDC.SelectObject(pOldBitmap);

	// 显示标题
	CFont		Font;
	Font.Attach((HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0));
	CFont *oldFont=(CFont*)pDC->SelectObject(&Font);
    if (strText != "")
    {
        CSize Extent = pDC->GetTextExtent(strText);
        CPoint pt( rect.CenterPoint().x - Extent.cx/2, 
			rect.CenterPoint().y - Extent.cy/2 );
		
        if (state & ODS_SELECTED) 
        {
			pt.Offset(1,1);
		}
        int nMode = pDC->SetBkMode(TRANSPARENT);
		
        if (state & ODS_DISABLED)
        {
			pDC->DrawState(pt, Extent, strText/*strCaption*/, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
		}
        else
		{
			pDC->DrawState(pt, Extent, strText/*strCaption*/, DSS_NORMAL, TRUE, 0, (HBRUSH)NULL);
		}
        pDC->SetBkMode(nMode);
    }
	pDC->SelectObject(oldFont);
	Font.Detach();
}

void CSkinButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	ASSERT(m_nNormalBitmapResID != 0);
	ASSERT(m_nFocusBitmapResID != 0);
	ASSERT(m_nPressedBitmapResID != 0);

	// TODO: Add your code to draw the specified item
	CDC*		ppDC   = CDC::FromHandle(lpDrawItemStruct->hDC);
    CMemDC		pDC(ppDC);
	CRect		rect = lpDrawItemStruct->rcItem;
    UINT		state = lpDrawItemStruct->itemState;
	CString		strText;
	TCHAR		szBuffer[1024]={NULL};
	
	::GetWindowText(lpDrawItemStruct->hwndItem,szBuffer,1024);
	strText=szBuffer;


	if(state & ODS_FOCUS)
	{
		m_bFocus = TRUE;
		m_bSelected = TRUE;
	}
	else
	{
		m_bSelected = FALSE;
		m_bFocus = FALSE;
	}

	DrawContent(pDC,state,rect,m_bFocus,strText);

	return;
	
}

void CSkinButton::PreSubclassWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	ModifyStyle(0, BS_OWNERDRAW);
	SetProp(m_hWnd,"SkinButtonHandled",(HANDLE)1);
	
	CButton::PreSubclassWindow();
}

void CSkinButton::OnMouseMove(UINT nFlags, CPoint point)
{
	if (!m_bTracking)
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_hWnd;
		tme.dwFlags = TME_LEAVE|TME_HOVER;
		tme.dwHoverTime = 1;
		m_bTracking = _TrackMouseEvent(&tme);		
	}	
	CButton::OnMouseMove(nFlags, point);
	
}

LRESULT CSkinButton::OnMouseHover(WPARAM wparam, LPARAM lparam)
{
	m_bOverControl=TRUE;
	Invalidate();
	return 1;
}

LRESULT CSkinButton::OnMouseLeave(WPARAM wparam, LPARAM lparam)
{
	m_bTracking = FALSE;
	m_bOverControl = FALSE;
	Invalidate(FALSE);
	return 0;
}

BOOL CSkinButton::SubClassWindow(HWND hWnd)
{
	// 首先看看这个hWnd是不是以前已经被SubClass过了。
	if (GetProp(hWnd,"SkinButtonObj") == NULL)
	{
		// 生成一个新的CSkinButton对象。
		CSkinButton		*pNewSkinButton=new CSkinButton;
		pNewSkinButton->m_hWnd=hWnd;						// 绕过Attach的检测。否则对于一个已经采用CButton控制的按钮会出现
															// ASSERT警告的.
		
		// 设置属性。
		pNewSkinButton->m_bEnableStretch=m_bEnableStretch;
		pNewSkinButton->m_nFocusBitmapResID=m_nFocusBitmapResID;
		pNewSkinButton->m_nHoverBitmapResID=m_nHoverBitmapResID;
		pNewSkinButton->m_nNormalBitmapResID=m_nNormalBitmapResID;
		pNewSkinButton->m_nPressedBitmapResID=m_nPressedBitmapResID;
		pNewSkinButton->m_nXPos=m_nXPos;
		pNewSkinButton->m_nYPos=m_nYPos;

		SetProp(hWnd,"SkinButtonObj",(HANDLE)pNewSkinButton);

		// 然后是WNDPROC;
		WNDPROC   OldProc=(WNDPROC)GetWindowLong(hWnd,GWL_WNDPROC);
		SetProp(hWnd,"OldWndProc",OldProc);

		SetWindowLong(hWnd,GWL_WNDPROC,(LONG)SkinButtonSubclassProc);
		
		return TRUE;
	}

	return FALSE;
}


BOOL CSkinButton::OnEraseBkgnd(CDC* pDC) 
{
	// 我们自己绘制按钮状态。
	// 根据当前按钮的信息。

	// TODO: Add your code to draw the specified item
    CRect		rect;
    GetClientRect(rect);
	
	CMemDC		DC(pDC,&rect);					// 由于传递近来的pDC不一定就是这个按钮的DC,
												// 所以绘画的区域必须手动指定。
												// pDC->GetClipBox != GetClientRect
	UINT		state = GetState();
	CString		strText;
	TCHAR		szBuffer[1024]={NULL};
	
	::GetWindowText(m_hWnd,szBuffer,1024);
	strText=szBuffer;

	DrawContent(DC,state,rect,m_bFocus,strText);
	
	return TRUE;//CButton::OnEraseBkgnd(pDC);
}

void CSkinButton::OnPaint() 
{
	CDC			*pDc=GetDC(); // device context for painting
	CRect		rect;
	GetClientRect(rect);

    CMemDC		DC(pDc,&rect);
	
    UINT		state = GetState();
	CString		strText;
	TCHAR		szBuffer[1024]={NULL};
	
	::GetWindowText(m_hWnd,szBuffer,1024);
	strText=szBuffer;

	DrawContent(DC,state,rect,m_bFocus,strText);	
}

⌨️ 快捷键说明

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