ListCombo.h
上传用户:sztopon
上传日期:2014-01-21
资源大小:55k
文件大小:12k
- #pragma once
- #include <atltheme.h>
- #include "ListTypes.h"
- class CListCombo : public CWindowImpl< CListCombo, CComboBox >
- {
- public:
- CListCombo() : m_wndEditCtrl( this, 1 )
- {
- m_nItem = NULL_ITEM;
- m_nSubItem = NULL_SUBITEM;
- m_nFlags = ITEM_FLAGS_NONE;
- m_nExitChar = 0;
- m_bMouseOver = FALSE;
- m_bActivate = FALSE;
- m_bShowThemed = TRUE;
- }
-
- ~CListCombo()
- {
- }
- protected:
- int m_nItem;
- int m_nSubItem;
- UINT m_nFlags;
- TCHAR m_nExitChar;
- BOOL m_bShowThemed;
- BOOL m_bMouseOver;
- BOOL m_bActivate;
- BOOL m_bSwappedButtons;
- CRect m_rcStatic;
- CRect m_rcButton;
- COLORREF m_rgbStaticBackground;
- COLORREF m_rgbStaticText;
-
- CTheme m_thmCombo;
- CFont m_fntComboFont;
- CContainedWindowT< CEdit > m_wndEditCtrl;
-
- public:
- BOOL Create( HWND hWndParent, int nItem, int nSubItem, CRect& rcRect, UINT nFlags, LPCTSTR lpszItemText, BOOL bShowThemed, CListArray < CString >& aComboList )
- {
- m_nItem = nItem;
- m_nSubItem = nSubItem;
- m_nFlags = nFlags;
- m_nExitChar = 0;
- m_bActivate = FALSE;
- m_bShowThemed = bShowThemed;
-
- m_bSwappedButtons = GetSystemMetrics( SM_SWAPBUTTON );
- m_rgbStaticBackground = GetSysColor( COLOR_HIGHLIGHT );
- m_rgbStaticText = GetSysColor( COLOR_HIGHLIGHTTEXT );
-
- // destroy old combo control...
- if ( IsWindow() )
- DestroyWindow();
-
- DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_SORT;
-
- if ( nFlags & ITEM_FLAGS_COMBO_EDIT )
- dwStyle |= CBS_DROPDOWN;
- else
- dwStyle |= CBS_DROPDOWNLIST;
-
- if ( nFlags & ITEM_FLAGS_EDIT_UPPER )
- dwStyle |= CBS_UPPERCASE;
-
- // create combo control
- if ( CWindowImpl< CListCombo, CComboBox >::Create( hWndParent, CRect( ( ( dwStyle & CBS_DROPDOWNLIST ) == CBS_DROPDOWNLIST ) ? rcRect.left + 3 : rcRect.left + 1, rcRect.top, rcRect.right, rcRect.bottom + ( 6 * rcRect.Height() ) ), NULL, dwStyle ) == NULL )
- return FALSE;
-
- // open combo theme
- if ( m_thmCombo.IsThemeNull() )
- m_thmCombo.OpenThemeData( m_hWnd, L"COMBOBOX" );
-
- // get system message font
- CLogFont logFont;
- logFont.SetMessageBoxFont();
- if ( !m_fntComboFont.IsNull() )
- m_fntComboFont.DeleteObject();
- if ( m_fntComboFont.CreateFontIndirect( &logFont ) == NULL )
- return FALSE;
- SetFont( m_fntComboFont, FALSE );
-
- // subclass edit control to capture keyboard input
- HWND hEditControl = GetWindow( GW_CHILD );
- if ( hEditControl != NULL )
- m_wndEditCtrl.SubclassWindow( hEditControl );
-
- for ( int nComboItem = 0; nComboItem < aComboList.GetSize(); nComboItem++ )
- AddString( aComboList[ nComboItem ] );
-
- if ( ( dwStyle & CBS_DROPDOWNLIST ) == CBS_DROPDOWNLIST )
- {
- int nIndex = FindStringExact( -1, lpszItemText );
- if ( nIndex != CB_ERR )
- SetCurSel( nIndex );
- }
- else
- {
- SetWindowText( lpszItemText );
- SetEditSel( 0, -1 );
- }
-
- // set static edit height
- SetItemHeight( -1, rcRect.Height() - 6 );
-
- COMBOBOXINFO infoComboBox = { sizeof( COMBOBOXINFO ) };
- if ( !::GetComboBoxInfo( m_hWnd, &infoComboBox ) )
- return FALSE;
-
- // store combobox details for painting
- m_rcStatic = infoComboBox.rcItem;
- m_rcButton = infoComboBox.rcButton;
- m_rcButton.DeflateRect( 0, 1 );
- m_rcButton.OffsetRect( -2, 0 );
-
- // show combo control
- ShowWindow( SW_SHOW );
- SetFocus();
-
- // force redraw now
- RedrawWindow();
-
- return TRUE;
- }
-
- BOOL IsValid( TCHAR nChar )
- {
- // validate number and float input
- if ( !( m_nFlags & ( ITEM_FLAGS_EDIT_NUMBER | ITEM_FLAGS_EDIT_FLOAT ) ) || nChar == VK_BACK )
- return TRUE;
-
- CString strValue;
- int nValueLength = GetWindowTextLength() + 1;
- GetWindowText( strValue.GetBuffer( nValueLength ), nValueLength );
- strValue.ReleaseBuffer();
-
- // get selected positions
- DWORD dwSelection = GetEditSel();
- int nStartChar = LOWORD( dwSelection );
- int nEndChar = HIWORD( dwSelection );
-
- // are we changing the sign?
- if ( ( m_nFlags & ITEM_FLAGS_EDIT_NEGATIVE ) && nChar == _T( '-' ) )
- {
- BOOL bNegative = FALSE;
- if ( m_nFlags & ITEM_FLAGS_EDIT_FLOAT )
- {
- double dblValue = _tstof( strValue );
- bNegative = ( dblValue < 0 );
- strValue.Format( _T( "%lf" ), -dblValue );
- }
- else
- {
- long lValue = _ttol( strValue );
- bNegative = ( lValue < 0 );
- strValue.Format( _T( "%ld" ), -lValue );
- }
-
- SetWindowText( strValue );
-
- // restore select position
- SetEditSel( bNegative ? nStartChar - 1 : nStartChar + 1, bNegative ? nEndChar - 1 : nEndChar + 1 );
- return FALSE;
- }
-
- // construct new value string using entered character
- CString strNewValue = strValue.Left( nStartChar ) + nChar + strValue.Right( strValue.GetLength() - nEndChar );
-
- int nGreaterThan = 0;
- int nLessThan = 0;
- int nEquals = 0;
- int nDecimalPoint = 0;
-
- int nNegativeIndex = -1;
- int nGreaterIndex = -1;
- int nLessIndex = -1;
- int nEqualIndex = -1;
- int nDecimalIndex = -1;
- int nDigitIndex = -1;
-
- for ( int nCharIndex = 0; nCharIndex < strNewValue.GetLength(); nCharIndex++ )
- {
- TCHAR nCharValue = strNewValue[ nCharIndex ];
- switch ( nCharValue )
- {
- case _T( '-' ): nNegativeIndex = nCharIndex;
- break;
- case _T( '>' ): if ( !( m_nFlags & ITEM_FLAGS_EDIT_OPERATOR ) )
- return FALSE;
- nGreaterIndex = nCharIndex;
- nGreaterThan++;
- break;
- case _T( '<' ): if ( !( m_nFlags & ITEM_FLAGS_EDIT_OPERATOR ) )
- return FALSE;
- nLessIndex = nCharIndex;
- nLessThan++;
- break;
- case _T( '=' ): if ( !( m_nFlags & ITEM_FLAGS_EDIT_OPERATOR ) )
- return FALSE;
- nEqualIndex = nCharIndex;
- nEquals++;
- break;
- case _T( '.' ): if ( !( m_nFlags & ITEM_FLAGS_EDIT_FLOAT ) )
- return FALSE;
- nDecimalIndex = nCharIndex;
- nDecimalPoint++;
- break;
- default: if ( !_istdigit( nCharValue ) )
- return FALSE;
- if ( nDigitIndex < 0 )
- nDigitIndex = nCharIndex;
- break;
- }
- // invalid if text contains more than one '>', '<', '=' or '.'
- if ( nGreaterThan > 1 || nLessThan > 1 || nEquals > 1 || nDecimalPoint > 1 )
- return FALSE;
- }
- // invalid if text contains '=>' or '=<'
- if ( nGreaterIndex != -1 && nEqualIndex != -1 && nGreaterIndex > nEqualIndex )
- return FALSE;
- if ( nLessIndex != -1 && nEqualIndex != -1 && nLessIndex > nEqualIndex )
- return FALSE;
- // invalid if digits exist before operator
- if ( nDigitIndex != -1 && nGreaterIndex != -1 && nGreaterIndex > nDigitIndex )
- return FALSE;
- if ( nDigitIndex != -1 && nLessIndex != -1 && nLessIndex > nDigitIndex )
- return FALSE;
- if ( nDigitIndex != -1 && nEqualIndex != -1 && nEqualIndex > nDigitIndex )
- return FALSE;
- if ( nDigitIndex != -1 && nNegativeIndex != -1 && nNegativeIndex > nDigitIndex )
- return FALSE;
-
- return TRUE;
- }
-
- BEGIN_MSG_MAP_EX(CListCombo)
- MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST,WM_MOUSELAST,OnMouseRange)
- MSG_WM_MOUSELEAVE(OnMouseLeave)
- MSG_WM_ERASEBKGND(OnEraseBkgnd)
- MSG_WM_PAINT(OnPaint)
- REFLECTED_COMMAND_CODE_HANDLER_EX(CBN_KILLFOCUS, OnKillFocus)
- MSG_WM_GETDLGCODE(OnGetDlgCode)
- MSG_WM_CHAR(OnChar)
- DEFAULT_REFLECTION_HANDLER()
- ALT_MSG_MAP(1)
- MSG_WM_GETDLGCODE(OnGetDlgCode)
- MSG_WM_CHAR(OnChar)
- END_MSG_MAP_EX()
-
- LRESULT OnMouseRange( UINT nMessage, WPARAM wParam, LPARAM lParam )
- {
- SetMsgHandled( FALSE );
-
- if ( nMessage == WM_MOUSEMOVE && !m_bMouseOver )
- {
- m_bMouseOver = TRUE;
-
- TRACKMOUSEEVENT trkMouse;
- trkMouse.cbSize = sizeof( TRACKMOUSEEVENT );
- trkMouse.dwFlags = TME_LEAVE;
- trkMouse.hwndTrack = m_hWnd;
-
- // notify when the mouse leaves button
- _TrackMouseEvent( &trkMouse );
- }
-
- // do not show button as pressed when first created
- m_bActivate = TRUE;
-
- InvalidateRect( m_rcButton );
-
- return 0;
- }
-
- void OnMouseLeave()
- {
- m_bMouseOver = FALSE;
- InvalidateRect( m_rcButton );
- }
-
- BOOL OnEraseBkgnd( CDCHandle dcErase )
- {
- return TRUE;
- }
-
- void OnPaint( HDC )
- {
- CPaintDC dcPaint( m_hWnd );
-
- CRect rcClient;
- GetClientRect( rcClient );
-
- CMemoryDC dcMemory( dcPaint.m_hDC, rcClient );
-
- CRect rcClip;
- if ( dcPaint.GetClipBox( rcClip ) == ERROR )
- return;
-
- int nContextState = dcMemory.SaveDC();
-
- // do not repaint background if drawing button only
- if ( !rcClip.EqualRect( m_rcButton ) )
- {
- CWindow wndParent( GetParent() );
- if ( wndParent.IsWindow() )
- {
- // draw background from parent
- CPoint ptOrigin( 0 );
- MapWindowPoints( wndParent, &ptOrigin, 1 );
- dcMemory.OffsetWindowOrg( ptOrigin.x, ptOrigin.y, &ptOrigin );
- wndParent.SendMessage( WM_PAINT, (WPARAM)dcMemory.m_hDC );
- dcMemory.SetWindowOrg( ptOrigin );
- }
- }
-
- DWORD dwPoint = GetMessagePos();
- CPoint ptMouse( GET_X_LPARAM( dwPoint ), GET_Y_LPARAM( dwPoint ) );
- ScreenToClient( &ptMouse );
-
- DWORD dwStyle = GetStyle();
- BOOL bHotButton = m_bActivate && ( ( ( dwStyle & CBS_DROPDOWNLIST ) == CBS_DROPDOWNLIST ) ? rcClient.PtInRect( ptMouse ) : m_rcButton.PtInRect( ptMouse ) );
- BOOL bPressed = bHotButton && ( GetAsyncKeyState( m_bSwappedButtons ? VK_RBUTTON : VK_LBUTTON ) < 0 );
-
- if ( ( dwStyle & CBS_DROPDOWNLIST ) == CBS_DROPDOWNLIST && !rcClip.EqualRect( m_rcButton ) )
- {
- dcMemory.SetBkColor( m_rgbStaticBackground );
- dcMemory.ExtTextOut( m_rcStatic.left, m_rcStatic.top, ETO_OPAQUE, m_rcStatic, _T( "" ), 0, NULL );
-
- // draw static text
- int nIndex = GetCurSel();
- if ( nIndex != CB_ERR )
- {
- CString strText;
- GetLBText( nIndex, strText );
-
- if ( !strText.IsEmpty() )
- {
- CRect rcText( m_rcStatic );
- rcText.OffsetRect( 1, 1 );
- dcMemory.SelectFont( m_fntComboFont );
- dcMemory.SetTextColor( m_rgbStaticText );
- dcMemory.SetBkMode( TRANSPARENT );
- dcMemory.DrawText( strText, strText.GetLength(), rcText, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER );
- }
- }
- }
-
- // draw drop down button
- if ( m_bShowThemed && !m_thmCombo.IsThemeNull() )
- m_thmCombo.DrawThemeBackground( dcMemory, CP_DROPDOWNBUTTON, bPressed ? CBXS_PRESSED : ( bHotButton ? CBXS_HOT : CBXS_NORMAL ), m_rcButton );
- else
- dcMemory.DrawFrameControl( m_rcButton, DFC_SCROLL, DFCS_SCROLLDOWN | ( bPressed ? DFCS_FLAT | DFCS_PUSHED : 0 ) );
- dcMemory.RestoreDC( nContextState );
- }
-
- void OnKillFocus( UINT uCode, int nCtrlID, HWND hwndCtrl )
- {
- SetMsgHandled( FALSE );
-
- CWindow wndParent( GetParent() );
- if ( wndParent.IsWindow() )
- {
- CString strValue;
-
- if ( ( GetStyle() & CBS_DROPDOWNLIST ) == CBS_DROPDOWNLIST )
- {
- int nIndex = GetCurSel();
- if ( nIndex != CB_ERR )
- GetLBText( nIndex, strValue );
- }
- else
- {
- int nValueLength = GetWindowTextLength() + 1;
- GetWindowText( strValue.GetBuffer( nValueLength ), nValueLength );
- strValue.ReleaseBuffer();
- }
-
- CListNotify listNotify;
- listNotify.m_hdrNotify.hwndFrom = m_hWnd;
- listNotify.m_hdrNotify.idFrom = GetDlgCtrlID();
- listNotify.m_hdrNotify.code = LCN_ENDEDIT;
- listNotify.m_nItem = m_nItem;
- listNotify.m_nSubItem = m_nSubItem;
- listNotify.m_nExitChar = m_nExitChar;
- listNotify.m_lpszItemText = strValue;
- listNotify.m_lpItemDate = NULL;
- // forward notification to parent
- FORWARD_WM_NOTIFY( wndParent, listNotify.m_hdrNotify.idFrom, &listNotify.m_hdrNotify, ::SendMessage );
- }
-
- ShowWindow( SW_HIDE );
- }
-
- UINT OnGetDlgCode( LPMSG lpMessage )
- {
- return DLGC_WANTALLKEYS;
- }
-
- void OnChar( TCHAR nChar, UINT nRepCnt, UINT nFlags )
- {
- switch ( nChar )
- {
- case VK_TAB:
- case VK_RETURN:
- case VK_ESCAPE: {
- m_nExitChar = nChar;
- CWindow wndParent( GetParent() );
- if ( wndParent.IsWindow() )
- wndParent.SetFocus();
- }
- break;
- default: SetMsgHandled( !IsValid( nChar ) );
- break;
- }
- }
- };