📄 advcombobox.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// AdvComboBox.cpp : implementation file
//
// CAdvComboBox Control
// Version: 2.1
// Date: September 2002
// Author: Mathias Tunared
// Email: Mathias@inorbit.com
// Copyright (c) 2002. All Rights Reserved.
//
// This code, in compiled form or as source code, may be redistributed
// unmodified PROVIDING it is not sold for profit without the authors
// written consent, and providing that this notice and the authors name
// and all copyright notices remains intact.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "AdvComboBox.h"
#include "VisualStylesXP.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define IDC_COMBOEDIT 108
/////////////////////////////////////////////////////////////////////////////
// CAdvComboBox
IMPLEMENT_DYNAMIC(CAdvComboBox, CWnd)
CAdvComboBox::CAdvComboBox( BOOL bInst, CWnd * pParent ) :
m_pDropWnd(0),
m_bDropListVisible(0),
m_bInst( bInst ),
m_pParent(pParent)
{
//XLISTCTRL_TRACE(_T("in CAdvComboBox::CAdvComboBox\n"));
RegisterWindowClass();
m_pEdit = NULL;
m_zDelta = 0;
m_nCurSel = -1;
m_bDropRectStored= false;
m_bHasFocus = false;
m_bHasSentFocus = false;
m_bSelItem = false;
m_bFirstPaint = true;
m_nMinVisItems = 5;
m_bCodeCreate = false;
m_bAutoAppend = TRUE;
m_bDropButtonHot = false;
m_bTrackMouseLeave = false;
m_nDefaultDropItems = -1;
m_dwACBStyle = 0;
m_dwACBStyle |= ACBS_STANDARD;
m_pFont = NULL;
}
CAdvComboBox::~CAdvComboBox()
{
// XLISTCTRL_TRACE(_T("in CAdvComboBox::~CAdvComboBox\n"));
delete m_pFont;
if( m_pDropWnd )
{
m_pDropWnd->ShowWindow( SW_HIDE );
m_bDropListVisible = FALSE;
m_pDropWnd->DestroyWindow();
delete m_pDropWnd;
m_pDropWnd = NULL;
}
if( m_pEdit )
{
m_pEdit->DestroyWindow();
delete m_pEdit;
}
}
BEGIN_MESSAGE_MAP(CAdvComboBox, CWnd)
//{{AFX_MSG_MAP(CAdvComboBox)
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEWHEEL()
ON_WM_SIZE()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_SHOWWINDOW()
ON_WM_ENABLE()
ON_WM_CHILDACTIVATE()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_CHAR()
ON_WM_KEYDOWN()
//ON_WM_ACTIVATEAPP()
//}}AFX_MSG_MAP
ON_MESSAGE( WM_SELECTED_ITEM, OnSelectedItem )
ON_MESSAGE( WM_ON_DROPDOWN_BUTTON, OnDropdownButton )
ON_MESSAGE( WM_DESTROY_DROPLIST, OnDestroyDropdownList )
ON_EN_KILLFOCUS(IDC_COMBOEDIT, OnKillfocusEdit)
ON_EN_SETFOCUS(IDC_COMBOEDIT, OnSetfocusEdit)
ON_EN_CHANGE(IDC_COMBOEDIT, OnChangeEdit)
ON_EN_UPDATE(IDC_COMBOEDIT, OnUpdateEdit)
ON_MESSAGE( CB_ADDSTRING, OnAddString )
ON_MESSAGE( CB_SETCURSEL, OnSetCurSel )
ON_MESSAGE( CB_GETCURSEL, OnGetCurSel )
ON_MESSAGE( CB_SELECTSTRING, OnSelectString )
ON_MESSAGE( CB_GETCOUNT, OnGetCount )
ON_MESSAGE( CB_RESETCONTENT, OnResetContent )
ON_MESSAGE( CB_GETLBTEXT, OnGetLBText )
ON_MESSAGE( CB_GETLBTEXTLEN, OnGetLBTextLen )
ON_MESSAGE( CB_GETTOPINDEX, OnGetTopIndex )
ON_MESSAGE( CB_SETTOPINDEX, OnSetTopIndex )
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAdvComboBox message handlers
LONG CAdvComboBox::OnAddString( WPARAM /*wParam*/, LPARAM lString )
{
TCHAR* pStr = (TCHAR*)lString;
return AddString( pStr );
}
LONG CAdvComboBox::OnSetCurSel( WPARAM wIndex, LPARAM /*lParam*/ )
{
int nIndex = (int)wIndex;
return SetCurSel( nIndex );
}
LONG CAdvComboBox::OnGetCurSel( WPARAM /*wParam*/, LPARAM /*lParam*/ )
{
return GetCurSel();
}
LONG CAdvComboBox::OnSelectString( WPARAM wItemStart, LPARAM lString )
{
int nItem = (int)wItemStart;
TCHAR* pStr = (TCHAR*)lString;
int nIndex = FindStringExact( nItem, pStr );
return SetCurSel( nIndex );
}
LONG CAdvComboBox::OnGetCount( WPARAM /*wParam*/, LPARAM /*lParam*/ )
{
return GetCount();
}
LONG CAdvComboBox::OnResetContent( WPARAM /*wParam*/, LPARAM /*lParam*/ )
{
m_list.clear();
m_strEdit = _T("");
m_nCurSel = -1;
SetWindowText( _T("") );
if( m_pEdit )
{
m_pEdit->SetWindowText( _T("") );
}
Invalidate();
return CB_OKAY;
}
LONG CAdvComboBox::OnGetLBText( WPARAM wIndex, LPARAM lString )
{
int nIndex = (int)wIndex;
TCHAR* pOutStr = (TCHAR*)lString;
return GetLBText( nIndex, pOutStr );
}
LONG CAdvComboBox::OnGetLBTextLen( WPARAM wIndex, LPARAM /*lParam*/ )
{
int nIndex = (int)wIndex;
return GetLBTextLen( nIndex );
}
LONG CAdvComboBox::OnGetTopIndex( WPARAM /*wParam*/, LPARAM /*lParam*/ )
{
return GetTopIndex();
}
LONG CAdvComboBox::OnSetTopIndex( WPARAM wIndex, LPARAM /*lParam*/ )
{
return SetTopIndex(wIndex);
}
BOOL CAdvComboBox::RegisterWindowClass()
{
WNDCLASS wndcls;
HINSTANCE hInst;
hInst = AfxGetInstanceHandle();
ASSERT( hInst != 0 );
if( !(::GetClassInfo(hInst, ADVCOMBOBOXCTRL_CLASSNAME, &wndcls)) )
{
wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = ADVCOMBOBOXCTRL_CLASSNAME;
if( !AfxRegisterClass(&wndcls) )
{
AfxThrowResourceException();
return FALSE;
}
}
return TRUE;
}
BOOL CAdvComboBox::Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID )
{
// XLISTCTRL_TRACE(_T("in CAdvComboBox::Create\n"));
m_rcCombo = rect;
m_bCodeCreate = true;
m_dwACBStyle |= ACBS_STANDARD;
m_dwStyle = dwStyle;
LoadString( nID );
BOOL bRet = CWnd::Create(NULL, _T(""), dwStyle, m_rcCombo, pParentWnd, nID );
return bRet;
}
void CAdvComboBox::LoadString( UINT nStringID )
{
UINT nIDS;
if( nStringID )
nIDS = nStringID;
else
{
nIDS = GetWindowLong( GetSafeHwnd(), GWL_ID );
}
//
// Load string from resources
CString strItems;
if( !strItems.LoadString( nIDS ) )
{
return;
}
//
// Clear the list
m_list.clear();
//
// Go through the string and look after '\n'.
TCHAR seps[] = _T("\n");
TCHAR *token;
int nLen = strItems.GetLength();
TCHAR* szTok = new TCHAR[nLen+5];
memset( szTok, 0, (nLen+5)*sizeof(TCHAR) );
_tcscpy( szTok, (LPCTSTR)strItems );
token = _tcstok( szTok, seps );
while( token != NULL )
{
AddString( token );
token = _tcstok( NULL, seps );
}
//
// Add item to list
//+++
delete [] szTok;
}
int CAdvComboBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// XLISTCTRL_TRACE(_T("in CAdvComboBox::OnCreate\n"));
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if( !m_pFont )
{
LOGFONT logFont;
memset( &logFont, 0, sizeof(LOGFONT) );
CFont* pF = m_pParent->GetFont();
ASSERT(pF);
pF->GetLogFont( &logFont );
m_pFont = new CFont;
m_pFont->CreateFontIndirect(&logFont);
SetFont( m_pFont );
}
return 0;
}
void CAdvComboBox::PreSubclassWindow()
{
// XLISTCTRL_TRACE(_T("in CAdvComboBox::PreSubclassWindow\n"));
if (m_pParent == NULL)
m_pParent = GetParent();
ASSERT(m_pParent);
// TODO: Add your specialized code here and/or call the base class
LoadString();
if( !m_pFont )
{
LOGFONT logFont;
memset( &logFont, 0, sizeof(LOGFONT) );
CFont* pF = m_pParent->GetFont();
ASSERT(pF);
pF->GetLogFont( &logFont );
m_pFont = new CFont;
m_pFont->CreateFontIndirect(&logFont);
SetFont( m_pFont );
}
if( !m_bCodeCreate )
{
//
// Do we need to show an edit control. (CBS_DROPDOWN)
if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
{
if( !m_pEdit )
{
CRect rect;
GetClientRect(rect);
rect.right = rect.right - ::GetSystemMetrics(SM_CXHSCROLL);
if( m_dwACBStyle & ACBS_STANDARD )
{
rect.DeflateRect( 2, 2 );
rect.left += 1;
rect.top += 2;
//rect.bottom += 2;
}
// XLISTCTRL_TRACE(_T("creating edit\n"));
m_pEdit = new CAdvComboEdit; //+++
ASSERT(m_pEdit);
DWORD dwStyle = 0;
dwStyle = WS_VISIBLE | WS_CHILD;
if( GetStyle() & CBS_AUTOHSCROLL )
{
dwStyle |= ES_AUTOHSCROLL;
}
VERIFY(m_pEdit->Create( dwStyle, rect, this, IDC_COMBOEDIT ));
m_pEdit->SetFont( m_pFont );
m_pEdit->SetWindowText( m_strEdit.c_str() );
}
}
}
CWnd::PreSubclassWindow();
}
void CAdvComboBox::OnChildActivate()
{
CWnd::OnChildActivate();
// TODO: Add your message handler code here
if( !m_pFont )
{
LOGFONT logFont;
memset( &logFont, 0, sizeof(LOGFONT) );
CFont* pF = m_pParent->GetFont();
pF->GetLogFont( &logFont );
m_pFont = new CFont;
m_pFont->CreateFontIndirect(&logFont);
SetFont( m_pFont );
}
if( m_bCodeCreate )
{
//
// Do we need to show an edit control. (CBS_DROPDOWN)
if( (GetStyle() & CBS_DROPDOWN) && !(GetStyle() & CBS_SIMPLE) ) // == CBS_DROPDOWN
{
if( !m_pEdit )
{
CRect rect;
GetClientRect(rect);
rect.right = rect.right - ::GetSystemMetrics(SM_CXHSCROLL);
if( m_dwACBStyle & ACBS_STANDARD )
{
rect.DeflateRect( 2, 2 );
rect.left += 1;
rect.top += 2;
//rect.bottom += 2;
}
m_pEdit = new CAdvComboEdit; //+++
DWORD dwStyle = 0;
dwStyle = WS_VISIBLE | WS_CHILD;
if( GetStyle() & CBS_AUTOHSCROLL )
{
dwStyle |= ES_AUTOHSCROLL;
}
m_pEdit->Create( dwStyle, rect, this, IDC_COMBOEDIT );
m_pEdit->SetFont( m_pFont );
m_pEdit->SetWindowText( m_strEdit.c_str() );
}
}
}
}
void CAdvComboBox::OnPaint()
{
CPaintDC dc(this); // device context for painting
if( m_nCurSel != -1 )
{
m_iter = m_list.begin();
advance( m_iter, m_nCurSel );
if( m_iter != m_list.end() )
{
m_strEdit = m_iter->strText;
}
if( m_bFirstPaint )
{
if( m_pEdit )
{
m_pEdit->SetWindowText( m_strEdit.c_str() );
m_bFirstPaint = false;
m_pEdit->EnableWindow( IsWindowEnabled() );
}
}
}
CRect rect;
CRect rcText;
GetClientRect(rect);
rcText = rect;
rect.left = rect.right - ::GetSystemMetrics(SM_CXHSCROLL);
rcText.right = rect.left-1;
m_rcDropButton = rect;
GetClientRect(rect);
BOOL bWndEnabled = IsWindowEnabled();
COLORREF clrDisabledBkg = ::GetSysColor(COLOR_BTNFACE);
COLORREF clrDisabledBorder = ::GetSysColor(COLOR_3DDKSHADOW);
COLORREF clrDisabledText = ::GetSysColor(COLOR_GRAYTEXT);
if( !bWndEnabled )
{
if( 1 ) // Draw disabled flat control with border? Change to '0'.
{
dc.FillSolidRect( rect, clrDisabledBkg );
}
else
{
CBrush brDisabled(clrDisabledBkg);
CBrush* pOldBrush = dc.SelectObject(&brDisabled);
CPen penDisabled( PS_SOLID, 0, clrDisabledBorder);
CPen* pOldPen = dc.SelectObject(&penDisabled);
dc.Rectangle(rect);
dc.SelectObject(pOldBrush);
dc.SelectObject(pOldPen);
}
}
else
{
COLORREF clrEnabledBkg = ::GetSysColor(COLOR_WINDOW);
dc.FillSolidRect( rect, clrEnabledBkg );
}
DWORD dwBtnStyle = 0;
if( !bWndEnabled )
{
dwBtnStyle |= DFCS_INACTIVE;
}
dwBtnStyle |= m_bDropListVisible ? (DFCS_SCROLLDOWN|DFCS_PUSHED|DFCS_FLAT) : DFCS_SCROLLDOWN;
BOOL bThemeActive = FALSE;
HRESULT hr;
bThemeActive = g_xpStyle.UseVisualStyles();
HTHEME hTheme = NULL;
if( bThemeActive )
hTheme = g_xpStyle.OpenThemeData( m_hWnd, _T("COMBOBOX") );
// Theme drop btn style
int nDropBtnThemeStyle = 0;
if( m_bDropListVisible )
{
nDropBtnThemeStyle = CBXS_PRESSED;
}
else
{
nDropBtnThemeStyle = CBXS_NORMAL;
if( m_bDropButtonHot )
nDropBtnThemeStyle = CBXS_HOT;
if( !bWndEnabled )
nDropBtnThemeStyle = CBXS_DISABLED;
}
#if 0 // -----------------------------------------------------------
if( m_dwACBStyle & ACBS_FLAT )
{
if( bThemeActive )
{
hr = g_xpStyle.DrawThemeBackground( hTheme, dc.m_hDC, CP_DROPDOWNBUTTON, nDropBtnThemeStyle, &m_rcDropButton, NULL);
}
else
{
dc.DrawFrameControl(m_rcDropButton, DFC_SCROLL, dwBtnStyle );
}
}
else
if( m_dwACBStyle & ACBS_STANDARD )
#endif // -----------------------------------------------------------
{
if( bThemeActive )
{
COLORREF clrBorder;
hr = g_xpStyle.GetThemeColor( hTheme, BP_PUSHBUTTON, bWndEnabled ? PBS_NORMAL : PBS_DISABLED, TMT_BORDERCOLOR, &clrBorder );
if( FAILED( hr ) )
{
clrBorder = RGB(0,0,0);
}
CPen penBorder( PS_SOLID, 0, clrBorder );
CPen* oldBorderPen = dc.SelectObject( &penBorder );
dc.Rectangle( &rect );
m_rcDropButton.DeflateRect(0,1,0,1);
m_rcDropButton.left -= 1;
m_rcDropButton.right -= 1;
if( !bWndEnabled )
{
COLORREF clrDisabledLightBorder;
COLORREF clrDisabledFill;
hr = g_xpStyle.GetThemeColor( hTheme, BP_PUSHBUTTON, bWndEnabled ? PBS_NORMAL : PBS_DISABLED, TMT_FILLCOLOR, &clrDisabledLightBorder );
if( FAILED( hr ) )
{
clrDisabledLightBorder = RGB(255,255,255);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -