AutoCompl.cpp
上传用户:czfddz
上传日期:2013-03-20
资源大小:1517k
文件大小:5k
源码类别:

酒店行业

开发平台:

C/C++

  1. ////////////////////////////////////////////////////////////////
  2. // VCKBASE -- August 2000
  3. // Compiles with Visual C++ 6.0, runs on Windows 98 and probably NT too.
  4. //
  5. #include "stdafx.h"
  6. #include "autocompl.h"
  7. //////////////////
  8. // ctor: initialize stuff to zero
  9. //
  10. CAutoComplete::CAutoComplete()
  11. {
  12.    m_bIgnoreChangeMsg=0;
  13.    m_iType = 0;
  14.    m_idMyControl = 0;
  15.    m_iCurString = 0;
  16. }
  17. CAutoComplete::~CAutoComplete()
  18. {
  19. }
  20. //////////////////
  21. // Install hook. Initialize control ID and type of control based on
  22. // classname
  23. //
  24. void CAutoComplete::Init(CWnd* pWnd)
  25. {
  26.    CSubclassWnd::HookWindow(pWnd->GetParent());
  27. //   AfxMessageBox("正在初始化!!");
  28.    CString sClassName;
  29.    ::GetClassName(pWnd->GetSafeHwnd(), sClassName.GetBuffer(32), 32);
  30.    sClassName.ReleaseBuffer();
  31.    if (sClassName=="Edit") {
  32.       m_iType = Edit;
  33.    } else if (sClassName=="ComboBox") {
  34.       m_iType = ComboBox;
  35.    }
  36.    m_idMyControl = pWnd->GetDlgCtrlID();
  37. }
  38. //////////////////
  39. // Scan string array for strings that match text, and add the matches
  40. // to a new array. Returns number of matches. For edit controls, only
  41. // need to find the first match, so to be efficient BOOL arg tells me
  42. // that.
  43. //
  44. UINT CAutoComplete::GetMatches(LPCTSTR pszText, CStringArray& arMatches,
  45.    BOOL bFirstOnly)
  46. {
  47.    arMatches.RemoveAll();
  48.    int nMatch = 0;
  49.    CString s=pszText;
  50.    if (s.GetLength()>0) {
  51.       OnFirstString();
  52.       CString sMatch;
  53.       while (OnNextString(sMatch)) {
  54.          if (OnMatchString(s, sMatch)) {
  55.             TRACE("Add %sn",(LPCTSTR)sMatch);
  56.             arMatches.Add(sMatch);
  57.             nMatch++;
  58.             if (bFirstOnly)
  59.                break;
  60.          }
  61.       }
  62.    }
  63.    return nMatch;
  64. }
  65. //////////////////
  66. // This virtual function takes the string entered and a potential match
  67. // and returns TRUE if the strings match. Default implementation does a
  68. // normal prefix compare--but you could override, for example to ignore
  69. // 'www' at the start of either string.
  70. //
  71. BOOL CAutoComplete::OnMatchString( const CString& s, const CString& sMatch)
  72. {
  73.    return s==sMatch.Left(s.GetLength());
  74. }
  75. void CAutoComplete::OnFirstString()
  76. {
  77.    m_iCurString=0;
  78. }
  79. BOOL CAutoComplete::OnNextString(CString& sNext)
  80. {
  81.    if (m_iCurString < m_arStrings.GetSize()) {
  82.       sNext = m_arStrings[m_iCurString++];
  83.       return TRUE;
  84.    }
  85.    sNext = (LPCTSTR)NULL;
  86.    return FALSE;
  87. }
  88. //////////////////
  89. // "hook" function traps messages sent to edit control/combobox. I am
  90. // interested in EN_CHANGE or CBN_EDITCHANGE: contents of edit control
  91. // have changed.
  92. //
  93. LRESULT CAutoComplete::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
  94. {
  95.    if ((msg==WM_COMMAND && LOWORD(wp)==m_idMyControl) &&
  96.        ((m_iType==Edit   && HIWORD(wp)==EN_CHANGE) ||
  97.         (m_iType==ComboBox && HIWORD(wp)==CBN_EDITCHANGE))) {
  98.       // since I will be changing the contents of the control, which
  99.       // will trigger more EN_CHANGE messages, turn off processing
  100.       // while I have control, using m_bIgnoreChangeMsg.
  101.       if (!m_bIgnoreChangeMsg++) {
  102.          CString s;
  103.          CWnd* pWnd = CWnd::FromHandle((HWND)lp);
  104.          pWnd->GetWindowText(s);
  105.          OnComplete(pWnd, s);
  106.       }
  107.       m_bIgnoreChangeMsg--;
  108.    }
  109. //   AfxMessageBox("正在初始化!");
  110.    return CSubclassWnd::WindowProc(msg, wp, lp);
  111. }
  112. //////////////////
  113. // This is the main function that does the completion.
  114. //
  115. void CAutoComplete::OnComplete(CWnd* pWnd, CString s)
  116. {
  117.    CStringArray arMatches; // strings that match
  118.    if (s.GetLength()>0 && GetMatches(s, arMatches, m_iType==Edit)>0) {
  119.       DoCompletion(pWnd, s, arMatches);
  120.    }
  121.    m_sPrevious=s; // remember current string
  122. }
  123. void CAutoComplete::DoCompletion(CWnd* pWnd, CString s,
  124.    const CStringArray& arMatches)
  125. {
  126.    if (m_iType==ComboBox) {
  127.       // This cast is technically incorrect, but a standard MFC trick.
  128.       CComboBox* pComboBox = (CComboBox*)pWnd;
  129.       // update dropdown to reflect possible matches
  130.       pComboBox->ResetContent();
  131.       for (int i=0; i<arMatches.GetSize(); i++) {
  132.          pComboBox->AddString(arMatches[i]);
  133.       }
  134.       // user arrow cursor so user can select
  135.       ::SetCursor(LoadCursor(NULL,MAKEINTRESOURCE(IDC_ARROW))); 
  136.       // show dropdown
  137.       pComboBox->ShowDropDown();
  138.       pComboBox->SetWindowText(IgnoreCompletion(s) ? s : arMatches[0]);
  139.       pComboBox->SetEditSel(s.GetLength(),-1);
  140.    } else if (m_iType==Edit && !IgnoreCompletion(s)) {
  141.       // This cast is technically incorrect, but a standard MFC trick. 
  142.       CEdit* pEdit = (CEdit*)pWnd;
  143.       pEdit->SetWindowText(arMatches[0]);
  144.       pEdit->SetSel(s.GetLength(),-1);
  145.    }
  146. }
  147. //////////////////
  148. // This function is used to turn off the completion feature when the
  149. // user presses Backspace to delete a character typed. In that case,
  150. // the current string (s) will match the last (previously) entered
  151. // string. If this is the case, don't do the completion. For example,
  152. // if user types 'foo' and this causes me to complete to 'foobar', with
  153. // 'bar' highlighted, I don't want to complete to foobar again if the
  154. // user presses Backspace or Delete to delete 'bar'. Instead, 'foo'
  155. // should remain--and likewise if the user keeps pressing backspace.
  156. // This is one of the only functions I have ever written where the
  157. // explanation is longer than the code itself!
  158. //
  159. BOOL CAutoComplete::IgnoreCompletion(CString s)
  160. {
  161.    return s==m_sPrevious.Left(s.GetLength());
  162. }