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

📄 agentbutton.cpp

📁 vc编写的精灵显示源码
💻 CPP
字号:
// AgentButton.cpp : implementation file
//

#include "stdafx.h"
#include "AgentButton.h"

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

#pragma warning ( disable : 4244 )

#define WM_UNCHECK ( WM_APP + 1 )
#define WM_SENDNOTIFY ( WM_APP + 2 )
/////////////////////////////////////////////////////////////////////////////
// CAgentButton

CAgentButton::CAgentButton()
{
	m_crBackground = GetSysColor( COLOR_INFOBK );
	m_crText= GetSysColor ( COLOR_BTNTEXT );

	m_bMouseDown = m_bTracking = m_bChecked = m_nImages = m_dwStyle = 0;
	m_lMargin = MAKELPARAM ( 2, 2 );
	m_lTextMargin = MAKELPARAM ( 2, 2 );
}

CAgentButton::~CAgentButton()
{
}


BEGIN_MESSAGE_MAP(CAgentButton, CButton)
	//{{AFX_MSG_MAP(CAgentButton)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_KILLFOCUS()
	ON_WM_KEYDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDBLCLK()
	//}}AFX_MSG_MAP
	ON_MESSAGE( WM_MOUSELEAVE, OnMouseLeave )
	ON_MESSAGE( WM_UNCHECK , OnUnCheck )		// Uncheck message
	ON_MESSAGE( BM_SETCHECK , OnBMSetCheck )
	ON_MESSAGE( BM_GETCHECK , OnBMGetCheck )
	ON_CONTROL_REFLECT(BN_CLICKED, OnClicked)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAgentButton message handlers


void CAgentButton::PreSubclassWindow() 
{
	m_dwStyle = GetButtonStyle();
	if ( ( m_dwStyle & BS_AUTOCHECKBOX ) == BS_AUTOCHECKBOX )
		m_dwStyle = BS_CHECKBOX;
	else if ( ( m_dwStyle & BS_AUTORADIOBUTTON ) == BS_AUTORADIOBUTTON )
		m_dwStyle = BS_RADIOBUTTON;
	else m_dwStyle = BS_PUSHBUTTON;

	SetWindowLong( m_hWnd, GWL_USERDATA, m_dwStyle );

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

void CAgentButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	//Check if the button state in not in inconsistent mode...
	POINT point;
	if ( m_bMouseDown && ::GetCapture() == m_hWnd && ::GetCursorPos( &point ) )
	{
		if ( ::WindowFromPoint( point ) == 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;
		}
	}

	// Obtain main info
	CString strCaption;
	CDC *pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
	CRect rectClient = lpDrawItemStruct->rcItem;

	GetWindowText(strCaption);
	pDC->SetBkMode( TRANSPARENT );
	pDC->FillSolidRect( rectClient, m_crBackground );
	
	long x = ( m_dwStyle == BS_PUSHBUTTON ? 0 : HIWORD ( m_lMargin ) );
	long y = ( m_dwStyle == BS_PUSHBUTTON ? 0 : LOWORD ( m_lMargin ) );
	
	// Calc text rect
	CRect rectText;
	if ( m_dwStyle == BS_PUSHBUTTON )
		rectText = rectClient;
	else
	{
		rectText.left = m_bitmapInfo.bmWidth + HIWORD( m_lMargin ) + HIWORD( m_lTextMargin );
		rectText.top = LOWORD ( m_lTextMargin );
		rectText.right = rectClient.Width() - rectText.left - HIWORD ( m_lTextMargin );
		rectText.bottom = rectText.top + 10000;
	}

	if (lpDrawItemStruct->itemState & ODS_DISABLED) // DISABLED BUTTON
	{
		
	}
	else
	{
		if ( lpDrawItemStruct->itemState & ODS_SELECTED ) // SELECTED (DOWN) BUTTON
		{
			if ( m_dwStyle == BS_PUSHBUTTON ) rectText.OffsetRect( 1, 1 ); // Move text rect
			DrawState( pDC, x, y, 2 );
		}
		else if ( m_bChecked )
		{
			DrawState( pDC, x, y, 3 );
		}
		else
		{											
			if ( m_bTracking ) // TRACKING
			{
				//rectText.OffsetRect( -1, -1 );
				DrawState( pDC, x, y, 1 );
			}
			else
			{
				if ( (lpDrawItemStruct->itemState & ODS_FOCUS) ) // FOCUS BUTTON
				{
					DrawState( pDC, x, y, 1 );
					
				}
				else // DEFAULT BUTTON
				{
					DrawState( pDC, x, y, 0 );
				}
			}
		}
		// Draw text
		/*int nHeight = */pDC->DrawText( strCaption, rectText, m_dwStyle == BS_PUSHBUTTON ?
			DT_VCENTER | DT_CENTER | DT_SINGLELINE : DT_WORDBREAK );

		//if ( m_bAutoSize && nHeight != rectClient.Height() )
		//	SetWindowPos ( NULL, 0, 0, rectClient.Width(), nHeight + LOWORD (m_lTextMargin) * 2, SWP_NOMOVE | SWP_NOZORDER );

		// Draw frame
		/*if ( ::GetFocus() == m_hWnd )
		{
			CPen pen(PS_INSIDEFRAME, 1, RGB(128,128,0));
			CPen* pOld =  pDC->SelectObject( &pen );
			pDC->MoveTo( rectText.TopLeft() );
			pDC->LineTo( rectText.right, rectText.top );
			pDC->MoveTo( rectText.right, rectText.top );
			pDC->LineTo( rectText.BottomRight() );
			pDC->MoveTo( rectText.BottomRight() );
			pDC->LineTo( rectText.left, rectText.bottom );
			pDC->MoveTo( rectText.left, rectText.bottom  );
			pDC->LineTo( rectText.TopLeft() );
						
			pDC->SelectObject( pOld );
		}*/

	}
}

void CAgentButton::AutoSize()
{
	if (m_dwStyle == BS_PUSHBUTTON )
		SetWindowPos ( NULL, 0, 0, m_bitmapInfo.bmWidth, m_bitmapInfo.bmHeight / m_nImages , SWP_NOMOVE | SWP_NOZORDER );
	else
	{
		CPaintDC dc(this);
		CRect rectText, rectClient;
		CString strCaption;
		GetWindowText( strCaption );
		GetClientRect( &rectClient );

		rectText.left = m_bitmapInfo.bmWidth + HIWORD( m_lMargin ) + HIWORD( m_lTextMargin );
		rectText.top = LOWORD ( m_lTextMargin );
		rectText.right = rectClient.Width() - rectText.left - HIWORD ( m_lTextMargin );
		rectText.bottom = rectText.top + 10000;
		
		int nHeight = dc.DrawText( strCaption, rectText, DT_WORDBREAK );

		if ( nHeight != rectClient.Height() )
			SetWindowPos ( NULL, 0, 0, rectClient.Width(), nHeight + LOWORD (m_lTextMargin) * 2, SWP_NOMOVE | SWP_NOZORDER );
		
	}
	
}

void CAgentButton::DrawState( CDC* pDC, long x, long y, int nState )
{
	pDC->BitBlt( x, y, m_bitmapInfo.bmWidth, m_bitmapInfo.bmHeight / m_nImages, &m_dcBitmap,
		0, nState * (m_bitmapInfo.bmHeight / m_nImages), SRCCOPY );
}

// Init control, load bitmaps and resize control
void CAgentButton::Init( UINT nIDResource, int nImages, BOOL bAutoSize )
{
	m_dcBitmap.CreateCompatibleDC( NULL );
	m_cBitmap.LoadBitmap( nIDResource );
	m_dcBitmap.SelectObject ( & m_cBitmap );
	m_cBitmap.GetBitmap( &m_bitmapInfo );
	m_nImages = nImages;
	
	// Auto size
	if ( bAutoSize )
		AutoSize();	
}

void CAgentButton::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
}

void CAgentButton::OnLButtonDown(UINT nFlags, CPoint point) 
{
	//If we are tracking this button, cancel it
    if ( m_bTracking)
	{
		TRACKMOUSEEVENT t = { sizeof(TRACKMOUSEEVENT), TME_CANCEL | TME_LEAVE, m_hWnd, 0 };
        if ( ::_TrackMouseEvent( &t ) )
            m_bTracking = FALSE;
    }

	m_bMouseDown = TRUE;

    //Default-process the message
	CButton::OnLButtonDown(nFlags, point);
}

void CAgentButton::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if ( m_dwStyle )  //track mouse for radio & check buttons
	{
		POINT point2 = point;
		::ClientToScreen( m_hWnd, &point2 );
		HWND hWndMouse = ::WindowFromPoint( point2 );
		if (hWndMouse == m_hWnd ) // mouse is in button
		{
			if ( m_dwStyle == BS_CHECKBOX ) SetCheck( m_bChecked ? 0 : 1);
			if ( m_dwStyle == BS_RADIOBUTTON ) SetCheck(1);

			//SendNotify( BN_CLICKED, GetWindowLong( m_hWnd, GWL_ID ) );
		}
	}

    //Default-process the message
    m_bMouseDown = FALSE;

	CButton::OnLButtonUp(nFlags, point);
}

void CAgentButton::OnMouseMove(UINT nFlags, CPoint point) 
{
	//TRACE0("MouseMove");
    //If we are in capture mode, button has been pressed down
    //recently and not yet released - therefore check is we are
    //actually over the button or somewhere else. If the mouse
    //position changed considerably (e.g. we moved mouse pointer
    //from the button to some other place outside button area)
    //force the control to redraw
    //
    if ( m_bMouseDown && ::GetCapture() == m_hWnd )
	{
	    POINT point2 = point;
        ::ClientToScreen( m_hWnd, &point2 );
        HWND mouse_wnd = ::WindowFromPoint( point2 );

        BOOL bPressed = ( ( GetState() & BST_PUSHED ) == BST_PUSHED );
        BOOL bNeedPressed = (mouse_wnd == m_hWnd);
        if ( bPressed != bNeedPressed )
		{
            SetState( bNeedPressed ? TRUE : FALSE);
            Invalidate();
        }
    }
	else 
	{
		//Otherwise the button is released. That means we should
		//know when we leave its area - and so if we are not tracking
		//this mouse leave event yet, start now!
		//
        if ( !m_bTracking )
		{
            TRACKMOUSEEVENT t = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, 0 };
            if (::_TrackMouseEvent(&t))
			{
                m_bTracking = TRUE;
                Invalidate();
            }
        }
    }

    //Forward this event to superclass
    CButton::OnMouseMove(nFlags, point);
}

LRESULT CAgentButton::OnMouseLeave( WPARAM wParam, LPARAM lParam )
{
	ASSERT (m_bTracking);
    m_bTracking = FALSE;
    Invalidate();
	return 0;
}

void CAgentButton::OnKillFocus(CWnd* pNewWnd) 
{
	if ( ::GetCapture() == m_hWnd )
	{
        ::ReleaseCapture();
        ASSERT ( !m_bTracking );
    }
	
	m_bMouseDown = FALSE;
    CButton::OnKillFocus(pNewWnd);
	
}

LRESULT CAgentButton::OnUnCheck(WPARAM wparam, LPARAM lParam)
{
	if ( m_bChecked && m_dwStyle != BS_CHECKBOX )
	{
		m_bChecked = FALSE;
		Invalidate();
	}
	return 0;
}

void CAgentButton::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if ( m_dwStyle && nChar == ' ' )
	{
		if ( m_dwStyle == BS_CHECKBOX) SetCheck( m_bChecked ? 0 : 1 );
		if ( m_dwStyle == BS_RADIOBUTTON) SetCheck ( 1 );
	}
	CButton::OnKeyDown(nChar, nRepCnt, nFlags);	
}

LRESULT CAgentButton::OnBMSetCheck(WPARAM wParam, LPARAM lParam)
{
	m_bChecked = wParam != 0;

	switch ( m_dwStyle )
	{
	case BS_RADIOBUTTON:
		if (m_bChecked)
		{
			//uncheck the other radio buttons (in the same group)
			HWND hthis, hwnd2, hpwnd;
			hpwnd = GetParent()->GetSafeHwnd();	//get button parent handle
			hwnd2 = hthis = GetSafeHwnd();			//get this button handle
			if (hthis && hpwnd)
			{				//consistency check
				for( ; ; )
				{	//scan the buttons within the group
					hwnd2=::GetNextDlgGroupItem(hpwnd,hwnd2,0);
					//until we reach again this button
					if ( hwnd2==hthis || hwnd2 == NULL ) break;
					
					//post the uncheck message
					::PostMessage(hwnd2, WM_UNCHECK, 0, 0);
				}
			}
		}
		break;
	case BS_PUSHBUTTON:
		m_bChecked = FALSE;
		ASSERT(false); // Must be a Check or Radio button to use this function
	}

	Invalidate();
	return 0;
}

LRESULT CAgentButton::OnBMGetCheck(WPARAM wparam, LPARAM lParam)
{
	return m_bChecked;
}

void CAgentButton::SendNotify( WPARAM wParam, LPARAM lParam )
{
	HWND hParent = ::GetParent( m_hWnd );
	::SendMessage( hParent, WM_SENDNOTIFY, wParam, lParam );
}

void CAgentButton::OnClicked()
{
	SendNotify( BN_CLICKED, (LPARAM)m_hWnd );
}

⌨️ 快捷键说明

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