MFC RadioListBox 单选

本文介绍了一个自定义的CRadioListBox控件的实现细节,该控件继承自CListBox并实现了单选列表框的功能。文章详细展示了如何通过重写绘图函数和其他消息处理函数来定制列表框的外观和行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RadioListBox.cpp

#include "SF_RadioListBox.h"

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

/////////////////////////////////////////////////////////////////////////////
// CRadioListBox

#define ID_EDIT_BOX 1000

CRadioListBox::CRadioListBox()
{
    m_nEditId = -1;
}

CRadioListBox::~CRadioListBox()
{
}

BEGIN_MESSAGE_MAP( CRadioListBox, CListBox )
    //{{AFX_MSG_MAP(CRadioListBox)
    ON_WM_CTLCOLOR_REFLECT()
    //}}AFX_MSG_MAP
    ON_WM_LBUTTONDBLCLK()
    ON_WM_LBUTTONDOWN()
    ON_WM_CREATE()
    ON_EN_KILLFOCUS( ID_EDIT_BOX, OnEnKillfocusEdit )
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRadioListBox message handlers


void CRadioListBox::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
    CDC* pDC = CDC::FromHandle( lpDrawItemStruct->hDC );

    if ( lpDrawItemStruct->itemID == (UINT)-1 )
    {
        if ( lpDrawItemStruct->itemAction & ODA_FOCUS )
            pDC->DrawFocusRect( &lpDrawItemStruct->rcItem );
        return;
    }
    else
    {
        int selChange = lpDrawItemStruct->itemAction & ODA_SELECT;
        int focusChange = lpDrawItemStruct->itemAction & ODA_FOCUS;
        int drawEntire = lpDrawItemStruct->itemAction & ODA_DRAWENTIRE;

        if ( selChange || drawEntire )
        {
            BOOL sel = lpDrawItemStruct->itemState & ODS_SELECTED;

            pDC->FillSolidRect( &lpDrawItemStruct->rcItem,
                                ::GetSysColor( (GetExStyle()&WS_EX_TRANSPARENT) ? COLOR_BTNFACE : COLOR_WINDOW ) );

            int h = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top;
            CRect rect( lpDrawItemStruct->rcItem.left + 2, lpDrawItemStruct->rcItem.top + 2,
                        lpDrawItemStruct->rcItem.left + h - 3, lpDrawItemStruct->rcItem.top + h - 3 );
            pDC->DrawFrameControl( &rect, DFC_BUTTON, DFCS_BUTTONRADIO | (sel ? DFCS_CHECKED : 0) );

            {
                pDC->SetTextColor( COLOR_WINDOWTEXT );
                pDC->SetBkMode( TRANSPARENT );
                lpDrawItemStruct->rcItem.left += h;

                CString str;

                GetText( lpDrawItemStruct->itemID, str );

                pDC->DrawText( str, &lpDrawItemStruct->rcItem, DT_LEFT | DT_VCENTER );
            }
        }
        {
            if ( focusChange || (drawEntire && (lpDrawItemStruct->itemState & ODS_FOCUS)) )
                pDC->DrawFocusRect( &lpDrawItemStruct->rcItem );
        }
    }
}

HBRUSH CRadioListBox::CtlColor( CDC* pDC, UINT nCtlColor )
{
    if ( (GetExStyle()&WS_EX_TRANSPARENT) && nCtlColor == CTLCOLOR_LISTBOX )
        return (HBRUSH)::GetSysColorBrush( COLOR_BTNFACE );

    return NULL;
}


void CRadioListBox::OnLButtonDblClk( UINT nFlags, CPoint point )
{

    CListBox::OnLButtonDblClk( nFlags, point );
}


void CRadioListBox::OnLButtonDown( UINT nFlags, CPoint point )
{
    CListBox::OnLButtonDown( nFlags, point );

    int nCur = GetCurSel();

    if ( nCur == LB_ERR )
        return;

    CRect rcItem;

    GetItemRect( nCur, rcItem );

    int h = rcItem.bottom - rcItem.top;

    rcItem.left += h;

    if( rcItem.PtInRect( point ) )
        EditStarts( rcItem );
}

void CRadioListBox::EditStarts(const CRect& rc)
{
    int nCur = GetCurSel();

    if ( nCur == LB_ERR )
        return;

    m_edit.MoveWindow( CRect( rc.left, rc.top, rc.right, rc.bottom + 2 ) );

    CString str;

    GetText( nCur, str );

    m_edit.SetWindowText( str );

    m_edit.SetFocus();

    m_edit.SetSel( 0, -1, TRUE );
    m_edit.ShowWindow( TRUE );

    m_nEditId = nCur;

}


int CRadioListBox::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
    if ( CListBox::OnCreate( lpCreateStruct ) == -1 )
        return -1;

    Init();


    return 0;
}

void CRadioListBox::OnEnKillfocusEdit()
{
    if ( m_edit.IsWindowVisible() == FALSE )
    {
        m_nEditId = -1;
        return;
    }

    CString str;
    m_edit.GetWindowText( str );

    m_edit.ShowWindow( FALSE );

    if ( str.GetLength() )
    {
        DeleteString( m_nEditId );
        InsertString( m_nEditId, str );
        SetCurSel( m_nEditId );
    }

    m_nEditId = -1;
}

BOOL CRadioListBox::SubclassDlgItem( UINT nID, CWnd* pParent )
{
    BOOL bRet = CListBox::SubclassDlgItem( nID, pParent );

    Init();

    return bRet;
}

void CRadioListBox::Init(UINT nId /*= -1*/, CWnd* pParentWnd /*= NULL*/)
{
    if ( m_hWnd == NULL )
    {
        Create(
            WS_CHILD | WS_VISIBLE | WS_BORDER | LBS_HASSTRINGS | WS_HSCROLL | WS_VSCROLL | LBS_OWNERDRAWVARIABLE | LBS_WANTKEYBOARDINPUT,
            CRect(), pParentWnd, nId );
    }
    if ( m_edit.m_hWnd == NULL )
    {
        m_edit.Create( WS_VISIBLE | WS_CHILD | ES_LEFT | ES_AUTOHSCROLL, CRect(), this, 1000 );
        m_edit.ModifyStyleEx( 0, WS_EX_CLIENTEDGE );

        m_edit.ShowWindow( FALSE );

        m_edit.SetFont( this->GetFont() );
    }
}

int CRadioListBox::InsertString( int nIndex, LPCTSTR lpszItem )
{
    int nRet = CListBox::InsertString( nIndex, lpszItem );

    if ( nRet != LB_ERR )
    {
        SetItemHeight( nRet, (UINT)(GetItemHeight( nRet ) * 1.06) );
    }


    return nRet;
}

int CRadioListBox::AddString( LPCTSTR lpszItem )
{
    int nRet = CListBox::AddString( lpszItem );

    if ( nRet != LB_ERR )
    {
        SetItemHeight( nRet, (UINT)(GetItemHeight( nRet ) * 1.06) );
    }


    return nRet;
}


BOOL CRadioListBox::PreTranslateMessage( MSG* pMsg )
{
    if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN )
    {
        if ( ::GetFocus() == m_edit.GetSafeHwnd() )
        {
            SetFocus();
            return TRUE;
        }
    }


    return CListBox::PreTranslateMessage( pMsg );
}

RadioListBox.h


#ifndef _RADIOLIST_BOX_H_
#define _RADIOLIST_BOX_H_


class CRadioListBox : public CListBox
{
// Construction
public:
    CRadioListBox();
    virtual ~CRadioListBox();
    void Init(UINT nId = -1, CWnd* pParentWnd = NULL);
// Attributes
public:
    int InsertString( int nIndex, LPCTSTR lpszItem );
    int AddString( LPCTSTR lpszItem );
public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
public:
    void EditStarts( const CRect& rc );
    BOOL SubclassDlgItem( UINT nID, CWnd* pParent );
protected:
    //{{AFX_MSG(CRadioListBox)
    afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    afx_msg void OnLButtonDown( UINT nFlags, CPoint point );
    afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
    afx_msg void OnEnKillfocusEdit();
protected:
    CEdit m_edit;
    UINT m_nEditId;
public:
    virtual BOOL PreTranslateMessage( MSG* pMsg );
};


#endif

这里写图片描述

这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值