(MFC Combo Box)Switch between drop-list and drop-down mode

参考此贴:http://www.codeguru.com/cpp/controls/combobox/article.php/c1823/Switch-between-droplist-and-dropdown-mode.htm

实现源码(经过少量修改,原版本请参考上贴)

// FineCombo.h : header file
//
// Copyright (c) 1999 Bruno Vais
//
// Distribute and use freely, except:
// a) Don't alter or remove this notice.
// b) Mark the changes you make.
//
// This file is provided "as is" with no expressed or implied warranty.
// Use at your own risk. Expect bugs.
//
// Send bug reports, bug fixes, enhancements, request, etc. to:
//
//  bvais@usa.net
//
//  v1.0  21.06.1999  Initial release

//
//  v1.1  19.03.2013  Modified by zhuyf
//
//  GetEditText()功能修改如下:
//  当Combo Box为Dropdown时,返回m_edit文本;当Combo Box为Drop List时,返回Combo Box文本
//  

#pragma once

class CFineEdit : public CEdit
{
// Construction
public:
    CFineEdit();
    
// Attributes
public:
    CComboBox *m_combo;
// Operations
public:
    
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CFineEdit)
    //}}AFX_VIRTUAL

// Implementation
public:
    void Create(CRect, CWnd *);
    virtual ~CFineEdit();

    // Generated message map functions
protected:
    //{{AFX_MSG(CFineEdit)
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnDestroy();
    afx_msg void OnKillFocus(CWnd *pNewWnd);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
private:
    CFont m_font;
    
};

class CFineCombo : public CComboBox
{
// Construction
public:
    CFineCombo();

// Attributes
public:
    CFineEdit m_edit;
// Operations
public:
    CString GetEditText();
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CFineCombo)
    //}}AFX_VIRTUAL

// Implementation
public:
    void SwitchToDrop(BOOL);
    virtual ~CFineCombo();

    // Generated message map functions
protected:
    //{{AFX_MSG(CFineCombo)
    afx_msg void OnDropdown();
    afx_msg void OnCloseup();
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
private:
    
};
// FineCombo.cpp : implementation file
//
// Copyright (c) 1999 Bruno Vais
//
// Distribute and use freely, except:
// a) Don't alter or remove this notice.
// b) Mark the changes you make.
//
// This file is provided "as is" with no expressed or implied warranty.
// Use at your own risk. Expect bugs.
//
// Send bug reports, bug fixes, enhancements, request, etc. to:
//
//  bvais@usa.net
//
//  v1.0  21.06.1999  Initial release

//
//  v1.1  19.03.2013  Modified by zhuyf
//
//  GetEditText()功能修改如下:
//  当Combo Box为Dropdown时,返回m_edit文本;当Combo Box为Drop List时,返回Combo Box文本
//  

#include "stdafx.h"
#include "FineCombo.h"

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

/////////////////////////////////////////////////////////////////////////////
// CFineCombo

CFineCombo::CFineCombo()
{
}

CFineCombo::~CFineCombo()
{
}


BEGIN_MESSAGE_MAP(CFineCombo, CComboBox)
    //{{AFX_MSG_MAP(CFineCombo)
    ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown)
    ON_CONTROL_REFLECT(CBN_CLOSEUP, OnCloseup)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFineCombo message handlers

void CFineCombo::SwitchToDrop(BOOL id)
{
    CEdit *edit=(CEdit *)GetWindow(GW_CHILD); 
    if (edit)    // if the combo already has the dropdown style
        return; // return

    if (id && !m_edit.m_hWnd)
    {
        CRect thisRect, dadRect;

        GetWindowRect(&thisRect);
        GetParent()->GetWindowRect(&dadRect);

        int left = thisRect.left - dadRect.left;
        int top = thisRect.top - dadRect.top;

        CRect editRect(left+3, top+2, left+thisRect.Width()-15, top+19);

        m_edit.Create(editRect, GetParent());
        m_edit.m_combo = this;
        
        // I have to put the edit in front of the combo in the Z-order
        // because otherwise when you click on it it will drop down the combo
        ::SetWindowPos(m_hWnd, m_edit.m_hWnd, 0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);

        CString str;
        int index = GetCurSel();
        if (index != -1)
        {
            GetLBText(GetCurSel(), str);
            m_edit.SetWindowText(str);
        }
        else
            m_edit.SetWindowText(_T(""));

        ModifyStyle(WS_TABSTOP, 0); // taking out the combo from the tablist
        m_edit.SetFocus();

    }
    else
    {
        // if empty edit box
        CString txt;
        m_edit.GetWindowText(txt);

        int sel = FindString(-1, txt);
        if (sel != -1)
        {
            SetCurSel(sel);
            GetLBText(sel, txt);
        }

        if (m_edit.m_hWnd)
            m_edit.DestroyWindow();

        ModifyStyle(0, WS_TABSTOP); // adding the combo to the tablist
        SetFocus();
    }

}

void CFineCombo::OnDropdown() 
{
    if (m_edit.m_hWnd)
    {    
        CString txt;
        m_edit.GetWindowText(txt);

        int sel = FindString(-1, txt);
        if (sel != -1)
        {
            SetCurSel(sel);
            GetLBText(sel, txt);
            m_edit.SetWindowText(txt);
        }
    }
}

void CFineCombo::OnCloseup() 
{
    if (m_edit.m_hWnd)
    {    
        CString str;
        int sel = GetCurSel();

        if (sel != -1)
        {
            GetLBText(sel, str);
            m_edit.SetWindowText(str);
            m_edit.SetFocus();
        }
    }
}

CString CFineCombo::GetEditText() 
{
    CString txt;

    if (m_edit.m_hWnd)
        m_edit.GetWindowText(txt);
    else
        // txt = _""; 
        GetWindowText(txt); // Modified by zhuyf

    return txt;
}


/////////////////////////////////////////////////////////////////////////////
// CFineEdit

CFineEdit::CFineEdit()
{

}

CFineEdit::~CFineEdit()
{
}


BEGIN_MESSAGE_MAP(CFineEdit, CEdit)
    //{{AFX_MSG_MAP(CFineEdit)
    ON_WM_KEYDOWN()
    ON_WM_DESTROY()
    ON_WM_KILLFOCUS()
    ON_WM_LBUTTONDOWN()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFineEdit message handlers

void CFineEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
    CString txt, wtxt;
    int sel;

    Invalidate();    

    switch (nChar)
    {
    case 40: // DOWNARROW
        GetWindowText(wtxt);
        sel = m_combo->FindStringExact(-1, wtxt);
        if (sel != -1)
        {
            if (m_combo->SetCurSel(sel+1) != -1)
            {
                m_combo->GetLBText(sel+1, txt);
                SetWindowText(txt);
            }
        }
        else
        {
            sel = m_combo->FindString(-1, wtxt);
            if (sel != -1)
            {
                m_combo->SetCurSel(sel);
                m_combo->GetLBText(sel,txt);
                SetWindowText(txt);
            }
            else // empty edit box
            {
                m_combo->SetCurSel(0);
                m_combo->GetLBText(0, txt);
                SetWindowText(txt);
            }
        }
        break;

    case 38: // UPARROW
        GetWindowText(wtxt);
        sel = m_combo->FindStringExact(-1, wtxt);
        if (sel != -1)
        {
            if (m_combo->SetCurSel(sel-1) != -1)
            {
                m_combo->GetLBText(sel-1, txt);
                SetWindowText(txt);
            }
        }
        else
        {
            sel = m_combo->FindString(-1, wtxt);
            if (sel != -1)
            {
                m_combo->SetCurSel(sel);
                m_combo->GetLBText(sel, txt);
                SetWindowText(txt);
            }
            else // empty edit box
            {
                m_combo->SetCurSel(0);
                m_combo->GetLBText(0, txt);
                SetWindowText(txt);
            }
        }
        break;
        
    default:
        CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
    }
}

void CFineEdit::Create(CRect rect, CWnd *father)
{
    CEdit::Create(WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL|WS_TABSTOP, rect, father, 5000);

    /*
    NONCLIENTMETRICS nonc;
    nonc.cbSize= sizeof(NONCLIENTMETRICS);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nonc, 0);
    m_font.CreateFontIndirect(&nonc.lfMessageFont);
    SetFont(&m_font,FALSE);
    */
}

void CFineEdit::OnDestroy() 
{
    CEdit::OnDestroy();
    //m_font.Detach();    
}

void CFineEdit::OnKillFocus(CWnd* pNewWnd) 
{
    CEdit::OnKillFocus(pNewWnd);
    Invalidate(); // because the caret remains somewhere in the left side    
}

void CFineEdit::OnLButtonDown(UINT nFlags, CPoint point) 
{
    Invalidate(); // same as above
    CEdit::OnLButtonDown(nFlags, point);
}

 

posted on 2013-03-19 19:29  zhuyf87  阅读(1419)  评论(0编辑  收藏  举报

导航