(MFC Combo Box)Switch between drop-list and drop-down mode
实现源码(经过少量修改,原版本请参考上贴)
// 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); }