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

📄 buttonst.cpp

📁 这是一本学习 window编程的很好的参考教材
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
//	Class:		CButtonST
//
//	Compiler:	Visual C++
//	Tested on:	Visual C++ 5.0
//				Visual C++ 6.0
//
//	Version:	See GetVersionC() or GetVersionI()
//
//	Created:	xx/xxxx/1998
//	Updated:	12/May/2001
//
//	Author:		Davide Calabro'		davide_calabro@yahoo.com
//

// --------------------------------------------------------------------------
// Description : Port of CButtonST to WTL (http://www.codeproject.com/buttonctrl/cbuttonst.asp)
// Author	   : Serge Weinstock
//
//	You are free to use, distribute or modify this code
//	as long as this header is not removed or modified.
// --------------------------------------------------------------------------

#include "stdafx.h"
#include "ButtonST.h"

CButtonST::CButtonST()
{
	m_bMouseOnButton = false;
	FreeResources(false);
	// Default type is "flat" button
	m_bIsFlat = true; 
	// By default draw border in "flat" button 
	m_bDrawBorder = true; 
	// By default icon is aligned horizontally
	m_nAlign = ST_ALIGN_HORIZ; 
	// By default, for "flat" button, don't draw the focus rect
	m_bDrawFlatFocus = false;
	// By default the button is not the default button
	m_bIsDefault = false;
	// By default the button is not a checkbox
	m_bIsCheckBox = false;
	m_nCheck = false;
	// Set default colors
	SetDefaultColors(false);
	// No tooltip created
	m_ToolTip.m_hWnd = 0;
	// Do not draw as a transparent button
	m_bDrawTransparent = false;
	m_pbmpOldBk = 0;
	// No URL defined
	::ZeroMemory(&m_szURL, sizeof(m_szURL));
	// No cursor defined
	m_hCursor = 0;
	// No autorepeat
	m_bAutoRepeat = false;
	m_dwPeriodAutoRepeat = 100;
	m_bIsPressed = false;
	m_bIsFocused = false;
	m_bIsDisabled = false;
}

CButtonST::~CButtonST()
{
	// Restore old bitmap (if any)
	if (m_dcBk != 0 && m_pbmpOldBk != 0)
		{
		m_dcBk.SelectBitmap(m_pbmpOldBk);
		}
	FreeResources();
	// Destroy the cursor (if any)
	if (m_hCursor != 0) ::DestroyCursor(m_hCursor);
}

DWORD CButtonST::SetDefaultColors(bool bRepaint)
{
	m_crColors[BTNST_COLOR_BK_IN]	= ::GetSysColor(COLOR_BTNFACE);
	m_crColors[BTNST_COLOR_FG_IN]	= ::GetSysColor(COLOR_BTNTEXT);
	m_crColors[BTNST_COLOR_BK_OUT]	= ::GetSysColor(COLOR_BTNFACE);
	m_crColors[BTNST_COLOR_FG_OUT]	= ::GetSysColor(COLOR_BTNTEXT);
	if (bRepaint) { Invalidate(); }
	return BTNST_OK;
}

void CButtonST::FreeResources(bool bCheckFor0)
{
	if (bCheckFor0)
		{
		// Destroy icons
		// Note: the following two lines MUST be here! even if
		// BoundChecker says they are unnecessary!
		if (m_csIcons[0].hIcon != 0) { ::DeleteObject(m_csIcons[0].hIcon); }
		if (m_csIcons[1].hIcon != 0) { ::DeleteObject(m_csIcons[1].hIcon); }
		// Destroy bitmaps
		if (m_csBitmaps[0].hBitmap != 0) { m_csBitmaps[0].hBitmap.DeleteObject(); }
		if (m_csBitmaps[1].hBitmap != 0) { m_csBitmaps[1].hBitmap.DeleteObject(); }
		// Destroy mask bitmaps
		if (m_csBitmaps[0].hMask != 0) { m_csBitmaps[0].hMask.DeleteObject(); }
		if (m_csBitmaps[1].hMask != 0) { m_csBitmaps[1].hMask.DeleteObject(); }
		}
	::ZeroMemory(&m_csIcons, sizeof(m_csIcons));
	::ZeroMemory(&m_csBitmaps, sizeof(m_csBitmaps));
} // End of FreeResources


DWORD CButtonST::SetIcon(ATL::_U_STRINGorID nIconInId, ATL::_U_STRINGorID nIconOutId, HMODULE rsrcModule)
{
	HICON		hIconIn;
	HICON		hIconOut;
	HINSTANCE	hInstResource;

	// Find correct resource handle
	hInstResource = (rsrcModule != 0 ? rsrcModule : _Module.GetResourceInstance());
	// Set icon when the mouse is IN the button
	hIconIn = (HICON)::LoadImage(hInstResource, nIconInId.m_lpstr, IMAGE_ICON, 0, 0, 0);
  	// Set icon when the mouse is OUT the button
	hIconOut = (HICON)::LoadImage(hInstResource, nIconOutId.m_lpstr, IMAGE_ICON, 0, 0, 0);
	return SetIcon(hIconIn, hIconOut);
}

DWORD CButtonST::SetIcon(HIMAGELIST imagelist, int idxIn, int idxOut)
{
	HICON		hIconIn;
	HICON		hIconOut;
	CImageList	il(imagelist);

	// Set icon when the mouse is IN the button
	hIconIn = il.GetIcon(idxIn, ILD_TRANSPARENT);
  	// Set icon when the mouse is OUT the button
	hIconOut = il.GetIcon(idxOut, ILD_TRANSPARENT);
	return SetIcon(hIconIn, hIconOut);
}

DWORD CButtonST::SetIcon(HICON hIconIn, HICON hIconOut)
{
	bool		bRetValue;
	ICONINFO	ii;

	// Free any loaded resource
	FreeResources();

	if (hIconIn != 0)
		{
		m_csIcons[0].hIcon = hIconIn;
		// Get icon dimension
		ZeroMemory(&ii, sizeof(ICONINFO));
		bRetValue = (::GetIconInfo(hIconIn, &ii) != 0);
		if (!bRetValue)
			{
			FreeResources();
			return BTNST_INVALIDRESOURCE;
			}
		m_csIcons[0].dwWidth	= (DWORD)(ii.xHotspot * 2);
		m_csIcons[0].dwHeight	= (DWORD)(ii.yHotspot * 2);
		::DeleteObject(ii.hbmMask);
		::DeleteObject(ii.hbmColor);
		if (hIconOut != 0)
			{
			m_csIcons[1].hIcon = hIconOut;
			// Get icon dimension
			ZeroMemory(&ii, sizeof(ICONINFO));
			bRetValue = (::GetIconInfo(hIconOut, &ii) != 0);
			if (!bRetValue)
				{
				FreeResources();
				return BTNST_INVALIDRESOURCE;
				}
			m_csIcons[1].dwWidth	= (DWORD)(ii.xHotspot * 2);
			m_csIcons[1].dwHeight	= (DWORD)(ii.yHotspot * 2);
			::DeleteObject(ii.hbmMask);
			::DeleteObject(ii.hbmColor);
			}
		}
	if (IsWindow()) { RedrawWindow(); }
	return BTNST_OK;
}

bool CButtonST::SetBtnCursor(ATL::_U_STRINGorID nCursorId, HMODULE rsrcModule)
{
	HINSTANCE hInstResource;
	// Destroy any previous cursor
	if (m_hCursor != 0) { ::DestroyCursor(m_hCursor); }
	m_hCursor = 0;
	// If we want a cursor
	if (nCursorId.m_lpstr != MAKEINTRESOURCE(0))
		{
		hInstResource = (rsrcModule != 0 ? rsrcModule : _Module.GetResourceInstance());
		// Load icon resource
		m_hCursor = (HCURSOR)::LoadImage(hInstResource, nCursorId.m_lpstr, IMAGE_CURSOR, 0, 0, 0);
		// If something wrong then return FALSE
		if (m_hCursor == 0) { return false; }
		}
	return true;
}

void CButtonST::SetFlat(bool bState)
{
	m_bIsFlat = bState;
	if (IsWindow()) { Invalidate(); }
}

bool CButtonST::GetFlat()
{
	return m_bIsFlat;
}

void CButtonST::SetFlatFocus(bool bDrawFlatFocus, bool bRepaint)
{
	m_bDrawFlatFocus = bDrawFlatFocus;
	// Repaint the button
	if (bRepaint && IsWindow()) { Invalidate(); }
}


bool CButtonST::GetDefault()
{
	return m_bIsDefault;
}

void CButtonST::SetAlign(Alignment nAlign)
{
	switch (nAlign)
		{   
		case ST_ALIGN_HORIZ:
		case ST_ALIGN_HORIZ_RIGHT:
		case ST_ALIGN_VERT:
			m_nAlign = nAlign;
			break;
		}
	if (IsWindow()) { Invalidate(); }
}

CButtonST::Alignment CButtonST::GetAlign()
{
	return m_nAlign;
}

void CButtonST::DrawBorder(bool bEnable)
{
	m_bDrawBorder = bEnable;
}

LRESULT CButtonST::OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	if(m_ToolTip.IsWindow())
		{
		m_ToolTip.RelayEvent((LPMSG)m_pCurrentMsg);
		}
	bHandled = false;
	return 1;
}

LRESULT CButtonST::OnMouseMove(UINT nFlags, CPoint point)
{
	CWindow pWnd;		// Active window
	CWindow pParent;	// Window that owns the button

	DefWindowProc();
	// If the mouse enter the button with the left button pressed then do nothing
	if ((nFlags & MK_LBUTTON) != 0 && !m_bMouseOnButton) { return 0; }
	// If our button is not flat then do nothing
	if (!m_bIsFlat) { return 0; };
	pWnd = ::GetActiveWindow();
	pParent = GetParent();

	if ((::GetCapture() != m_hWnd) && 
		(
#ifndef ST_LIKEIE
		pWnd.IsWindow() && 
#endif
		pParent.IsWindow())) 
		{
		m_bMouseOnButton = true;
		SetCapture();
		Invalidate();
		}
	else
		{
		CPoint p2 = point;
		ClientToScreen(&p2);
		CWindow wndUnderMouse = ::WindowFromPoint(p2);
		if (wndUnderMouse && (wndUnderMouse.m_hWnd != m_hWnd))
			{
			// Redraw only if mouse goes out
			if (m_bMouseOnButton)
				{
				m_bMouseOnButton = false;
				Invalidate();
				}
			// If user is NOT pressing left button then release capture!
			if (!(nFlags & MK_LBUTTON))
				{
				ReleaseCapture();
				}
			}
		}
	return 0;
}

LRESULT CButtonST::OnKillFocus(HWND hWnd)
{
	DefWindowProc();
	CancelHover();
	return 0;
}

LRESULT CButtonST::OnLButtonDown(UINT nFlags, CPoint pt)
{
	DefWindowProc();
	if (m_bAutoRepeat)
		{
		MSG		csMsg;
		int		nButtonID;
		HWND	hWndParent;
		bool	initialState = true;

		nButtonID = GetDlgCtrlID();
		hWndParent = GetParent();
		SetCapture();
		while(::PeekMessage(&csMsg, m_hWnd, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE) == FALSE)
			{
			::SendMessage(hWndParent, WM_COMMAND, MAKEWPARAM((WORD)nButtonID, BN_CLICKED), (LPARAM)m_hWnd);
			::Sleep(m_dwPeriodAutoRepeat);
			initialState = !initialState;
			}
		if(!initialState)
			{
			::SendMessage(hWndParent, WM_COMMAND, MAKEWPARAM((WORD)nButtonID, BN_CLICKED), (LPARAM)m_hWnd);
			}
		ReleaseCapture();
		SendMessage(WM_LBUTTONUP);
		CPoint ptCursor;
		::GetCursorPos(&ptCursor);
		ScreenToClient(&ptCursor);
		SendMessage(WM_MOUSEMOVE, 0, MAKELPARAM(ptCursor.x, ptCursor.y));
		}
	return 0;
}

void CButtonST::CancelHover()
{
	// If our button is not flat then do nothing
	if (!m_bIsFlat) { return; }
	if (m_bMouseOnButton)
		{
		m_bMouseOnButton = false;
		Invalidate();
		}
}

void CButtonST::OnActivate(UINT nState, BOOL bMinimized, HWND pWndOther) 
{
	DefWindowProc();
	if (nState == WA_INACTIVE)	{ CancelHover(); }
}

void CButtonST::OnEnable(BOOL bEnable) 
{
	DefWindowProc();
	if (!bEnable)	CancelHover();
}

void CButtonST::OnCancelMode() 
{
	DefWindowProc();
	CancelHover();
}

void CButtonST::OnCaptureChanged(HWND pWnd) 
{
	if (m_bMouseOnButton)
		{
		static int i = 0;
		ReleaseCapture();
		Invalidate();
		}
	// Call base message handler
	SetMsgHandled(false);
}

BOOL CButtonST::OnSetCursor(HWND pWnd, UINT nHitTest, UINT message) 
{
	// If a cursor was specified then use it!
	if (m_hCursor != 0)
		{
		::SetCursor(m_hCursor);
		return true;
		}
	SetMsgHandled(false);
	return 0;
}

void CButtonST::PaintBk(CDCHandle pDC)
{
	CWindow		parent = GetParent();
	CClientDC	clDC(parent);
	CRect		rect;
	CRect		rect1;

	GetClientRect(rect);
	GetWindowRect(rect1);
	parent.ScreenToClient(rect1);
	if (m_dcBk == 0)
		{
		m_dcBk.CreateCompatibleDC(clDC);
		m_bmpBk.CreateCompatibleBitmap(clDC, rect.Width(), rect.Height());
		m_pbmpOldBk = m_dcBk.SelectBitmap(m_bmpBk);
		m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), clDC, rect1.left, rect1.top, SRCCOPY);
		}
	pDC.BitBlt(0, 0, rect.Width(), rect.Height(), m_dcBk, 0, 0, SRCCOPY);
}

//
// Parameters:
//		[IN]	bHasTitle
//				TRUE if the button has a text
//		[IN]	rpItem
//				A pointer to a RECT structure indicating the allowed paint area
//		[IN/OUT]rpTitle
//				A pointer to a CRect object indicating the paint area reserved for the
//				text. This structure will be modified if necessary.
//		[IN]	bIsPressed
//				TRUE if the button is currently pressed
//		[IN]	dwWidth
//				Width of the image (icon or bitmap)
//		[IN]	dwHeight
//				Height of the image (icon or bitmap)
//		[OUT]	rpImage
//				A pointer to a CRect object that will receive the area available to the image
//
void CButtonST::PrepareImageRect(bool bHasTitle, RECT &rpItem, CRect &rpTitle, bool bIsPressed, DWORD dwWidth, DWORD dwHeight, CRect &rpImage)
{
	CRect rBtn;

	rpImage = rpItem;

	switch (m_nAlign)
		{
		case ST_ALIGN_HORIZ:
			if (!bHasTitle)
				{
				// Center image horizontally
				rpImage.left += ((rpImage.Width() - dwWidth)/2);
				}
			else
				{
				// Image must be placed just inside the focus rect
				rpImage.left += 3;  
				rpTitle.left += dwWidth + 3;
				}
			// Center image vertically
			rpImage.top += ((rpImage.Height() - dwHeight)/2);
			break;
		case ST_ALIGN_HORIZ_RIGHT:
			GetClientRect(&rBtn);
			if (bHasTitle == FALSE /*spTitle->IsEmpty()*/)
				{
				// Center image horizontally
				rpImage.left += ((rpImage.Width() - dwWidth)/2);
				}
			else
				{
				// Image must be placed just inside the focus rect
				rpTitle.right = rpTitle.Width() - dwWidth - 3;
				rpTitle.left = 3;
				rpImage.left = rBtn.right - dwWidth - 3;
				// Center image vertically
				rpImage.top += ((rpImage.Height() - dwHeight)/2);
				}
			break;
		case ST_ALIGN_VERT:
			// Center image horizontally
			rpImage.left += ((rpImage.Width() - dwWidth)/2);
			if (bHasTitle == FALSE /*spTitle->IsEmpty()*/)
				{
				// Center image vertically
				rpImage.top += ((rpImage.Height() - dwHeight)/2);           
				}
			else
				{
				rpImage.top = 3;
				rpTitle.top += dwHeight;
				}
			break;
		}
    
	// If button is pressed then press image also
	if (bIsPressed && !m_bIsCheckBox)
		{
		rpImage.OffsetRect(1, 1);
		}
}

void CButtonST::DrawTheBitmap(CDCHandle pDC, bool bHasTitle, RECT &rItem, CRect &rCaption, bool bIsPressed, bool bIsDisabled)
{
	CDC				hdcBmpMem	= 0;
	CBitmapHandle	hbmOldBmp	= 0;
	CDC				hdcMem		= 0;
	CBitmapHandle	hbmT		= 0;
	BYTE			byIndex		= 0;

	// Select the bitmap to use
	if (m_bIsCheckBox)
		{
		if (bIsPressed)
			{
			byIndex = 0;
			}
		else
			{
			byIndex = (m_csBitmaps[1].hBitmap == NULL ? 0 : 1);
			}
		}
	else
		{
		if (m_bMouseOnButton || bIsPressed)
			{
			byIndex = 0;
			}
		else
			{
			byIndex = (m_csBitmaps[1].hBitmap == NULL ? 0 : 1);
			}
		}

	CRect	rImage;

	PrepareImageRect(bHasTitle, rItem, rCaption, bIsPressed, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, rImage);
	hdcBmpMem.CreateCompatibleDC(pDC);
	hbmOldBmp = hdcBmpMem.SelectBitmap(m_csBitmaps[byIndex].hBitmap);
	hdcMem.CreateCompatibleDC(0);
	hbmT = hdcMem.SelectBitmap(m_csBitmaps[byIndex].hMask);

	pDC.BitBlt(rImage.left, rImage.top, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcMem, 0, 0, SRCAND);
	pDC.BitBlt(rImage.left, rImage.top, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcBmpMem, 0, 0, SRCPAINT);

	hdcMem.SelectBitmap(hbmT);
	hdcBmpMem.SelectBitmap(hbmOldBmp);
}

void CButtonST::DrawTheIcon(CDCHandle pDC, bool bHasTitle, RECT &rpItem, CRect &rpTitle, bool bIsPressed, bool bIsDisabled)
{
	BYTE byIndex = 0;

	// Select the icon to use
	if (m_bIsCheckBox)
		{
		if (bIsPressed)
			{
			byIndex = 0;
			}
		else
			{
			byIndex = (m_csIcons[1].hIcon == NULL ? 0 : 1);
			}
		}
	else
		{
		if (m_bMouseOnButton || bIsPressed)
			{
			byIndex = 0;
			}
		else

⌨️ 快捷键说明

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