CustomDrawn listbox in a OwnerDrawn combobox

"Jean-Yves" <[email protected]>
Newsgroups gmane.comp.windows.wtl
Message-ID <[email protected]>
Hi,

I'm having a hard time understanding how to use a custom-drawn listbox in place of the native combobox listbox. You can read the whole source code below, made as short as possible (no asserts, dummy values). The first part implements a custom-drawn CListViewCtrl, with only one overriden method: OnPrePaint(). The second part implements an owner-drawn CComboBox, based on the "Tree Combo" source code from "Various ComboBox controls" article by Bjarke Viksoe (http://www.viksoe.dk/code/combos.htm). When the native combobox list is about to be displayed, OnDropDown() should prevent it from being used and display the custom-drawn list instead. And there comes my problem: the custom-drawn list method OnPrePaint() is never called so the custom-drawn listbox is never displayed. Instead, a normal lis
 tbox is used by the frawework as usual. Sure I have misunderstood something, but what ?...

Any help would be greatly appreciated !
Best regards.
Jean-Yves Chasle


---------- SOURCE CODE -----------
// Custom drawn listbox control
template< class T, class TBase = CListViewCtrl, class TWinTraits = CControlWinTraits >
class ATL_NO_VTABLE MyListBoxImpl
:   public CWindowImpl< T, TBase, TWinTraits >,
    public CCustomDraw< T >
{
public:
    typedef MyListBoxImpl< T, TBase, TWinTraits > TThisClass;

public:
    DECLARE_WND_SUPERCLASS( NULL, TBase::GetWndClassName() )

    // Never called when the control is part of the combobox...
    DWORD OnPrePaint( int /*iIdCtrl*/, LPNMCUSTOMDRAW poNMCD ) {
        return CDRF_SKIPDEFAULT;
    }

private:
    BEGIN_MSG_MAP( TThisClass )
        CHAIN_MSG_MAP_ALT( CCustomDraw< T >, 1 )
        MESSAGE_HANDLER( WM_CREATE, OnCreate )
    END_MSG_MAP()

    LRESULT OnCreate( UINT uiMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/ ) {
        LRESULT lRes = DefWindowProc( uiMsg, wParam, lParam );
        ModifyStyle( 0, (LVS_SINGLESEL | LVS_SHOWSELALWAYS) );
        return lRes;
    }
};

class MyListBox: public MyListBoxImpl< MyListBox > {
public:
    DECLARE_WND_SUPERCLASS( _T( "MyListBox" ), GetWndClassName() )
};


// Owner drawn combobox
template< class T, class TBase = CComboBox, class TWinTraits = CControlWinTraits >
class ATL_NO_VTABLE MyComboBoxImpl: public CWindowImpl< T, TBase, TWinTraits >
{
public:
    typedef MyComboBoxImpl< T, TBase, TWinTraits > TThisClass;

private:
    // Works fine with CListViewCtrl, not with MyListBox (which behaves like CListViewCtrl).
    CContainedWindowT< MyListBox > m_wndListbox;

public:
    DECLARE_WND_SUPERCLASS( NULL, TBase::GetWndClassName() )

    int InsertString( int nIndex, LPCTSTR szString ) {
        return m_wndListbox.InsertItem( nIndex, szString );
	}

private:
    BEGIN_MSG_MAP( TThisClass )
        MESSAGE_HANDLER( WM_CREATE, OnCreate )
        MESSAGE_HANDLER( WM_DESTROY, OnDestroy )
        MESSAGE_HANDLER( OCM_DRAWITEM, OnDrawItem )
        REFLECTED_COMMAND_CODE_HANDLER( CBN_DROPDOWN, OnDropDown )
        MESSAGE_HANDLER( WM_APP + 1, OnListHandleInput )
    ALT_MSG_MAP( 1 )
        MESSAGE_HANDLER( WM_LBUTTONDOWN, OnListButtonUp )
        MESSAGE_HANDLER( WM_KILLFOCUS, OnListKillFocus )
    END_MSG_MAP()

    LRESULT OnCreate( UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL &/*rbHandled*/ ) {      
        LRESULT lRes = DefWindowProc();
        ModifyStyle( 0, (CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS) );
        m_wndListbox.Create( this, 1, NULL, &rcDefault, NULL, (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | LVS_SINGLESEL | LVS_SHOWSELALWAYS), 0 );
        return lRes;
    }
    LRESULT OnDestroy( UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL &rbHandled ) {
        m_wndListbox.DestroyWindow();
        rbHandled = FALSE;
        return 0;
    }
    LRESULT OnDrawItem( UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL &/*rbHandled*/ ) {
        return TRUE;
    }
    LRESULT OnDropDown( WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL &rbHandled ) {
        PostMessage( WM_APP + 1 ); // Calls OnListHandleInput().
        rbHandled = FALSE;
        return 0;
    }
    LRESULT OnListHandleInput( UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL &/*rbHandled*/ ) {
        ReleaseCapture(); // (Original comment by Bjarke Viksoe:) Force list to close prematurely!

        // Set our list control rect from the native combobox list rect.
        COMBOBOXINFO oCBInfo;
        oCBInfo.cbSize = sizeof( oCBInfo );
        GetComboBoxInfo( &oCBInfo );
        RECT rcList;
        ::GetWindowRect( oCBInfo.hwndList, &rcList );
        rcList.bottom = rcList.top + 100; //-- Dummy value

        // Make our list control show in place of the native combobox list.
        ::ShowWindow( oCBInfo.hwndList, SW_HIDE );
        m_wndListbox.SetWindowPos( HWND_TOP, &rcList, SWP_SHOWWINDOW );
        m_wndListbox.SetFocus();
        return 0;
    }
    LRESULT OnListButtonUp( UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL &/*rbHandled*/ ) {
        LRESULT lRes = m_wndListbox.DefWindowProc();
        SetFocus(); // Calls OnListKillFocus().
        return lRes;
    }
    LRESULT OnListKillFocus( UINT /*uiMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL &rbHandled ) {
        m_wndListbox.ShowWindow( SW_HIDE );
        rbHandled = FALSE;
        return 0;
    }
};

class MyComboBox: public MyComboBoxImpl< MyComboBox > {
public:
    DECLARE_WND_SUPERCLASS( _T( "MyComboBox" ), GetWndClassName() )
};


---------- Excerpt from CMainDlg::OnInitDialog() -----------
MyComboBox m_wndCombobox.Create( m_hWnd, CRect( CPoint( 400, 0 ), CSize( 100, 20 ) ), NULL, (WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_GROUP | CBS_DROPDOWNLIST | CBS_HASSTRINGS) );
// Use m_wndCombobox.InsertString() to populate it.




------------------------------------

Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/wtl/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://groups.yahoo.com/group/wtl/join
    (Yahoo! ID required)

<*> To change settings via email:
    [email protected] 
    [email protected]

<*> To unsubscribe from this group, send an email to:
    [email protected]

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.