📄 listboxex.cpp
字号:
//*-
//
// MODULE NAME: ListBoxEx.cpp
//
// DESCRIPTION: CListBoxEx class declaration
//
// AUTHOR : Copyright (C) Stefano Passiglia, December 1999
// passig@geocities.com
// You can reuse and redistribute this code, provided this header is
// kept as is.
//+*/
//
// Include Files
//
#include "stdafx.h"
#include <stdio.h>
#include "InPlaceCtrls.h"
#include "ListboxEx.h"
//#include "BmpData.h" // for bitmap definition
//
// Global variables.
//
static unsigned int const g_DragListMsg = RegisterWindowMessage( DRAGLISTMSGSTRING );
static unsigned int const g_IPCEndEditMsg = RegisterWindowMessage( IPCMSGSTRING );
//
// Local constant definitions.
//
#ifdef _DEBUG
# define new DEBUG_NEW
# undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// Local type definitions.
//
// None.
//
// Local defines
//
#define ALT_KEY_PRESSED( uFlag ) ( (uFlag)&KF_ALTDOWN)
#define LBEX_ID_EDITCONTROL 1
#define LBEX_ID_BUTTONCONTROL 2
#define LBEX_LASTITEM_MAGIC 0x45424558 // 'LBEX'
//////////////////////////////////////////////////////////////////////////////
// //
// CListBoxEx class //
// //
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////
// Message map //
///////////////////////////////////////////////
BEGIN_MESSAGE_MAP( CListBoxEx, CDragListBox )
//{{AFX_MSG_MAP(CListBoxEx)
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_LBUTTONUP()
ON_WM_SYSKEYDOWN()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
ON_REGISTERED_MESSAGE( g_IPCEndEditMsg, OnEndEditMessage )
END_MESSAGE_MAP()
IMPLEMENT_DYNCREATE( CListBoxEx, CDragListBox )
///////////////////////////////////////////////
// Constructor/Destructor //
///////////////////////////////////////////////
///*-
// FUNCTION NAME: CListBoxEx::CListBoxEx()
//
// DESCRIPTION: CListBoxEx class constructor
//
// PARAMETER(S): None.
//
// RETURN: None
//
// NOTES: None
//+*/
CListBoxEx::CListBoxEx()
{
m_pBuddy = NULL;
m_dwEditStyle = LBEX_EDITBUTTON;
m_pEdit = NULL;
m_iSelected = -1;
m_iEdited = -1;
m_bAllowEditing = TRUE;
m_bAllowDrag = TRUE;
m_bAddedNullString = FALSE;
m_nActiveIndex = -1;
this->m_nNewlyAdded = -1;
this->m_nNewlyDeleted = -1;
} // CListBoxEx::CListBoxEx
///*-
// FUNCTION NAME: CListBoxEx::~CListBoxEx()
//
// DESCRIPTION: CListBoxEx class destructor
//
// PARAMETER(S): None.
//
// RETURN: None
//
// NOTES: None
//+*/
CListBoxEx::~CListBoxEx()
{
if(m_pEdit != NULL&&m_pBrowseButton != NULL)
{
delete m_pEdit;
delete m_pBrowseButton;
}
} // CListBoxEx::~CListBoxEx
///////////////////////////////////////////////
// Initialization //
///////////////////////////////////////////////
///*-
// FUNCTION NAME: CListBoxEx::PreCreateWindow
//
// DESCRIPTION: Called before the window handle is created
//
// PARAMETER(S):
// cs:
// TYPE: CREATESTRUCT structure
// MODE: In
// MECHANISM: By reference
// DESCRIPTION: Allows to change window features
//
// RETURN: Inherited value.
//
// NOTES: None
//+*/
BOOL CListBoxEx::PreCreateWindow( CREATESTRUCT & cs )
{
// Make sure it has the correct styles
cs.style |= LBEX_STYLE;
cs.dwExStyle |= LBEX_EXSTYLE;
return CWnd::PreCreateWindow(cs);
} // CListBoxEx::PreCreateWindow
///*-
// FUNCTION NAME: CListBoxEx::PreSubclassWindow
//
// DESCRIPTION: Called before the window handle is attached to a dialog item.
//
// PARAMETER(S): None.
//
// RETURN: Inherited value.
//
// NOTES: None
//+*/
void CListBoxEx::PreSubclassWindow()
{
// Make sure it has the correct styles
ModifyStyle( 0, LBEX_STYLE, SWP_SHOWWINDOW );
ModifyStyleEx( 0, LBEX_EXSTYLE, SWP_SHOWWINDOW );
CDragListBox::PreSubclassWindow();
CreateEdit();
} // CListBoxEx::PreSubclassWindow
///*-
// FUNCTION NAME: CListBoxEx::OnCreate
//
// DESCRIPTION: Called when the window handle is created
//
// PARAMETER(S):
// lpCreateStruct:
// TYPE: CREATESTRUCT structure
// MODE: In
// MECHANISM: By reference
// DESCRIPTION: Allows to change window features
//
// RETURN: Inherited value.
//
// NOTES: None
//+*/
int CListBoxEx::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
if ( CDragListBox::OnCreate(lpCreateStruct) == -1 )
{
return -1;
}
CreateEdit();
return 0;
} // CListBoxEx::OnCreate
///*-
// FUNCTION NAME: CListBoxEx::CreateEdit
//
// DESCRIPTION: Creates the edit box
//
// PARAMETER(S): None.
//
// RETURN: Inherited value.
//
// NOTES: None
//+*/
void CListBoxEx::CreateEdit()
{
// Create an in-place edit box
if ( m_pEdit == NULL )
{
m_pEdit = new CInPlaceEdit;
m_pEdit->Create( WS_CHILD | WS_BORDER | m_dwEditStyle,
CRect( 0, 0, 0, 0 ),
this,
LBEX_ID_EDITCONTROL );
m_pEdit->SetFont( GetFont() );
// Create the browse button
m_pBrowseButton = new CInPlaceButton;
m_pBrowseButton->Create( _T("..."),
WS_CHILD | BS_PUSHBUTTON,
CRect( 0, 0, 0, 0 ),
this,
LBEX_ID_BUTTONCONTROL );
}
} // CListBoxEx::CreateEdit()
///////////////////////////////////////////////
// Draw functions //
///////////////////////////////////////////////
///*-
// FUNCTION NAME: CListBoxEx::MeasureItem
//
// DESCRIPTION: Called by the framework when a list box
// with an owner-draw style is created.
//
// PARAMETER(S):
// lpMeasureItemStruct:
// TYPE: MEASUREITEMSTRUCT structure.
// MODE: In
// MECHANISM: By reference
// DESCRIPTION: Used to inform Windows of the list-box dimensions.
//
// RETURN: None.
//
// NOTES: None
//+*/
void CListBoxEx::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct )
{
// Get current font metrics
TEXTMETRIC metrics;
HDC dc = ::GetDC( m_hWnd );
GetTextMetrics( dc, &metrics );
::ReleaseDC( m_hWnd, dc );
// Set the height
lpMeasureItemStruct->itemHeight = metrics.tmHeight + metrics.tmExternalLeading;
} // CListBoxEx::MeasureItem
///*-
// FUNCTION NAME: CListBoxEx::DrawItem
//
// DESCRIPTION: Called by the framework when a
// visual aspect of an owner-draw list box changes.
//
// PARAMETER(S):
// lpDrawItemStruct:
// TYPE: DRAWITEMSTRUCT structure.
// MODE: In
// MECHANISM: By reference
// DESCRIPTION: Contains information about the type of drawing required.
//
// RETURN: None.
//
// NOTES: None
//+*/
void CListBoxEx::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
// If there are no list box items, skip this message.
if ( lpDrawItemStruct->itemID == -1 )
{
return;
}
CString strItemText;
CRect rcText( lpDrawItemStruct->rcItem );
COLORREF clrItemText,
clrOldTextColor;
// Put a bit of room to the left of the text
rcText.left += 8;
// Act upon the item state
switch ( lpDrawItemStruct->itemAction )
{
case ODA_SELECT:
case ODA_DRAWENTIRE:
// Is the item selected?
if ( lpDrawItemStruct->itemState & ODS_SELECTED )
{
clrItemText = GetSysColor( COLOR_HIGHLIGHTTEXT );
// Clear the rectangle
FillRect( lpDrawItemStruct->hDC,
&lpDrawItemStruct->rcItem,
(HBRUSH)(COLOR_ACTIVECAPTION+1) );
}
else
{
clrItemText = GetSysColor( COLOR_WINDOWTEXT );
// Clear the rectangle
FillRect( lpDrawItemStruct->hDC,
&lpDrawItemStruct->rcItem,
(HBRUSH)(COLOR_WINDOW+1) );
}
clrOldTextColor = SetTextColor( lpDrawItemStruct->hDC,
clrItemText );
SetBkMode( lpDrawItemStruct->hDC,
TRANSPARENT );
// Display the text associated with the item.
if ( lpDrawItemStruct->itemData != LBEX_LASTITEM_MAGIC )
{
GetText( lpDrawItemStruct->itemID,
strItemText );
DrawText( lpDrawItemStruct->hDC,
LPCTSTR( strItemText ),
strItemText.GetLength(),
&rcText,
DT_SINGLELINE | DT_VCENTER );
}
else
{
DrawText( lpDrawItemStruct->hDC,
"--- Last Item",
strItemText.GetLength(),
&rcText,
DT_SINGLELINE | DT_VCENTER );
}
// Is the item selected?
if ( lpDrawItemStruct->itemState & ODS_SELECTED )
{
SetTextColor( lpDrawItemStruct->hDC,
clrOldTextColor );
DrawFocusRect( lpDrawItemStruct->hDC,
&lpDrawItemStruct->rcItem );
}
break;
}
} // CListBoxEx::DrawItem
///*-
// FUNCTION NAME: CListBoxEx::DrawSeparator
//
// DESCRIPTION: Draws the insertion guide before the
// item with the indicated index.
//
// PARAMETER(S):
// nIndex:
// TYPE: int.
// MODE: In
// MECHANISM: By value
// DESCRIPTION: Zero-based index of the insertion point.
//
// RETURN: None.
//
// NOTES: Copied from the MFC implementation, with some changes.
//+*/
void CListBoxEx::DrawSeparator( int nIndex )
{
if ( nIndex == -1 )
{
return;
}
CBrush* pBrush = CDC::GetHalftoneBrush();
CRect rect;
GetClientRect(&rect);
CRgn rgn;
rgn.CreateRectRgnIndirect( &rect );
CDC* pDC = GetDC();
// Prevent drawing outside of listbox
// This can happen at the top of the listbox since the listbox's DC is the
// parent's DC
pDC->SelectClipRgn( &rgn );
GetItemRect( nIndex, &rect );
rect.bottom = rect.top+2;
rect.top -= 2;
rect.left += 5;
rect.right -= 5;
CBrush* pBrushOld = pDC->SelectObject(pBrush);
// Draw main line
pDC->PatBlt( rect.left, rect.top, rect.Width(), rect.Height(), PATINVERT );
// Draw vertical lines
pDC->PatBlt( rect.left-3, rect.top-4, 3, rect.Height()+8, PATINVERT );
pDC->PatBlt( rect.right, rect.top-4, 3, rect.Height()+8, PATINVERT );
pDC->SelectObject( pBrushOld );
ReleaseDC( pDC );
} // CListBoxEx::DrawSeparator
///*-
// FUNCTION NAME: CListBoxEx::DrawInsert
//
// DESCRIPTION: Called to draw the insertion guide before the
// item with the indicated index.
//
// PARAMETER(S):
// nIndex:
// TYPE: int.
// MODE: In
// MECHANISM: By value
// DESCRIPTION: Zero-based index of the insertion point.
//
// RETURN: None.
//
// NOTES: Copied from the MFC implementation.
//+*/
void CListBoxEx::DrawInsert( int nIndex )
{
if ( m_nLast != nIndex )
{
DrawSeparator( m_nLast );
DrawSeparator( nIndex );
}
// Set last selected
m_nLast = nIndex;
} // CDragListBox::DrawInsert
///////////////////////////////////////////////
// Messages //
///////////////////////////////////////////////
///*-
// FUNCTION NAME: CListBoxEx::OnChildNotify
//
// DESCRIPTION: Called by this window抯 parent window when it receives a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -