• 多列自动完成组合框


    介绍 一个组合框,具

      

    有自动完成功能,也允许多个 列。它来源于Chris Maunder的CComboCompletion。 版本1.2修复了以下问题: 尺寸问题,由马格努斯·埃格伯格和他的同事提供 AddRow()例程现在被重载,以便更容易添加 行。不再需要SetColCount(UINT)。的重载 一个CComboBox例程,已被DeleteRow()取代。通过删除额外的特写镜头,对子字符串的奇反转也得到了解决 收到“Enter”键。 这个组合框 处理以相同字符开头且仅表示匹配的文本字符串 当它是独一无二的。即. .假设盒子里装满了字符串: 隐藏,复制Code

    0
    1
    100
    1234
    

    在键入“1”时,这是第二个项目的唯一匹配,因此组合框 就会打开并突出那个。如果你继续“0”,那么 combobox将再次打开并显示100,但最后一个0将是 突出显示,因为这是下一个字符将去的地方。键入一个 “1”后的“2”将选择“1234”,“34”将高亮显示。多个 支持列,因此combobox必须是所有者绘制,变量,与 字符串。可以为combobox提供下拉菜单或下拉菜单的属性 列表。在后者中,输入的字符不匹配 第一列字符串将发出哔哔声并被拒绝。通过对话框中的一行创建combobox 这通常是由MS类向导为相关的类提供的 当combobox被插入对话框时: 隐藏,复制Code

    class CMyDialog : CDialog {
        ...
        CAutoCombobox m_myAutoCombobox;
        ...
    };
    CMyDialog::CMyDialog(...)
     : m_myAutoCombobox(ACB_DROP_LIST) { }

    或者使用ACB_DROP_DOWN。在下面的文章中有以下内容 定义。 隐藏,复制Code

    typedef vector<CString> CStringsVec;
    typedef vector<int> IntVec;
    

    特殊目的成员功能如下: 隐藏,复制Code

    CAutoComboBox::AddRow(const TCHAR* pString);
    CAutoComboBox::AddRow(const CStringsVec& allCols);
    CAutoCombobox::AddRow(const TCHAR* pString, CStringsVec& extraCols);

    这些例程被重载以在每一行中添加字符串。第一个 如果需要单列自动补全,只需为一列添加文本。 第二个允许在向量中插入所有列的字符串 字符串。向量中的第一个字符串将被添加到实际 combobox本身和其他部分将被保存在一个内部成员字符串向量中。 第三个是向后兼容性,需要分离 字符串中的第一列用于额外的列。第一次一排 ,列的数量将被记住,而所有随后的添加必须 具有完全相同数量的列字符串。如果列为空,则使用 空字符串填充空格(_T(""))。 隐藏,复制Code

    CAutoCombobox::DeleteRow(int iRow) 

    这将从内部删除行和相应的额外文本 向量。 隐藏,复制Code

    CAutoCombobox::GetSelectedRow() const 

    可以通过此函数检索所选的行。如果没有行已被 唯一标识,返回值为-1。 隐藏,复制Code

    CAutoCombobox::ResetSelection() 

    当前选择被取消,我们可以从头开始比赛 再一次 隐藏,复制Code

    CAutoCombobox::ResetContent() 

    所有的行都从组合框和内部数组中删除,这样您就可以这样做了 重新开始填充。 隐藏,复制Code

    CAutoCombobox::SetReverseEntry(bool bReverse = true) 

    在我的例子中,我需要允许输入来自的字符串 从右到左,而不是从左到右。对于一个数字列表,它的可变性是 通常更多的是低阶数字,所以1一般不需要输入a 许多字符得到唯一的匹配。把100写成a很奇怪 "0"后面跟着"0",然后是"1"。 隐藏,复制Code

    CAutoCombobox::DeleteString(UINT uRow) 

    这将从内部删除行和相应的额外文本 向量。这个例程不赞成,应该由DeleteRow(int)替换。 隐藏,复制Code

    CAutoCombobox::SetColCount(int iCols) 

    这个例程不再需要了,因此不建议使用它。列 count是从第一个AddRow(…)调用开始建立的。如果使用此例程,则必须在添加任何行之前调用,因为它有效 额外字符串向量的大小。 示例项目加载具有两列和一组数值的combobox 字符串。它是一个MDI应用程序,并已通过MS Visual Studio .NET 2003和MDI测试 Windows XP。在VS6.0实现中有一个剩下的.dsw文件 似乎也起作用了!)选择菜单项Test(^快捷方式)将打开 已被字符串填充的对话框。输入一个3将打开盒子和 显示选中“3”的行。现在继续输入453,盒子就会 再次打开,现在将选择显示为包含345337的行。指定从 这样就可以把345337保存在盒子里了。点击OK, MDI应用程序显示 通过项目:nnnn在主窗口中选择。 我需要一个不区分大小写的匹配,所以使用了CString::CompareNoCase(…)。 如果需要区分大小写的匹配,则将两个引用更改为比较 函数只需使用CString::Compare(…)。 我删除了下拉列表w的关闭母鸡的 “Enter”键出现了。这样做的目的是允许一次击键 关闭下拉列表,并触发的默认按钮 包含对话框。对话框中的组合框的正常行为是 第一个“Enter”关闭列表,第二个“Enter”触发默认值 动作,总共两个按键。如果这个额外的特写实现在a Win95/98/ME操作系统,然后一个问题出现了。有时字符串会恢复 到先前匹配的子字符串。这是由于在 ComboBox对象的Microsoft实现。没有问题 NT或XP。反转只在字符串发生的时候发生 首先匹配一个短字符串,然后匹配一个长字符串。在 在上面的列列表中,输入“1”将选择“1”行。现在进入 一个“0”,将选择“100”行。点击组合框外将关闭 下拉菜单,但是选择会因为一些未知的原因返回到“1”。 有趣的是,如果“1”后面跟着“0”来突出显示“100”和 然后向上箭头/向下箭头用于选择下一行并返回 “100”,焦点的改变将使“100”留在原位而不回调 “1”。它不会发生在选择的“3”后面跟着“2”的时候 “323513”如图所示。将焦点从选中的“323513”移开 即使列表中有一个“3”,它还是保留了这个。 记录这个的微软事件编号 错误是SRX020705601306。根据微软的说法,没有这样的工作 这就是在这个新版本中关闭的原因! 控件的主要部分在OnEditUpdate()例程中,如下所示。当一个 找到唯一匹配时,combobox将被放下,而所涉及的项目是 高亮显示。 PreTranslateMsg(…)必须测试退格或删除和取消 自动完成下一个字符。如果不这样做,这是不可能的 在系统继续输入下一个字符时纠正错误。这 在Chris Maunder的CComboCompletion示例中有更好的描述。 清单需要头文件来显示列出的变量定义 接下来,然后 下面是OnEditUpdate()代码。获取用户输入的文本行 通过GetWindowText()函数,并在找到匹配项时进行修改 SetWindowText()和SetEditSel()。 清单取自autocbox.h 隐藏,收缩,复制Code

    using std::vector;
    typedef vector<Int> IntVec;
    typedef vector<CString> CStringsVec;
    
    ////////////////////////////////////////////////////////////////////////
    //
    // CAutoComboBox window
    //
    class CAutoComboBox : public CComboBox {
    
    public:
        // define the two types to emulate
        enum AutoComboBoxType {
            ACB_DROP_DOWN,
            ACB_DROP_LIST
        };
        CAutoComboBox(AutoComboBoxType acbt = ACB_DROP_LIST);
        virtual ~CAutoComboBox();
    
        // ClassWizard generated virtual function overrides
    private:
        virtual BOOL PreTranslateMessage(MSG* pMsg);
        virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
        virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
    
    public:
        int GetSelectedRow();
        int AddRow(const TCHAR* pString, const CStringsVec& extraCols);
        int AddRow(const CStringsVec& cols);
        int AddRow(const TCHAR* pString);
        int DeleteRow(int iRow);
        void SetReverseEntry(bool bReverse) { m_bReverseEntry = bReverse; }
        void GetLBText(int nIndex, CString& rString) const;
        void ResetSelection();
        void ResetContent();
        // the following routines are deprecated!!
        int DeleteString(UINT uRow);        // use DeleteRow(...)
        void SetColCount(int iCols);        // not needed any more
    
    protected:
        afx_msg void OnEditUpdate();
        afx_msg void OnSelChange();
        afx_msg void OnCbnDropdown();
    
        DECLARE_MESSAGE_MAP()
    private:
        int FindUniqueMatchedItem(const CString& line, CString& matchedLine);
        int SetDroppedWidthForTextLengths();
        bool LineInString(const CString& rsLine, const CString& rsString) const;
        int m_iSelectedRow;
        int m_iHorizontalExtent;    // list box width for all columns
        bool m_bAutoComplete;       // false after delete or backspace
        bool m_bReverseEntry;       // enter characters in reverse
        bool m_bEditHeightSet;      // true when we've set the height of the box
        bool m_bClosing;            // stops error in selection on enter
        AutoComboBoxType m_autoComboBoxType;
        IntVec m_vecEndPixels;      // ending positions for each column
        vector<CStringsVec> m_vecRows;// row text for each col after the first
    };

    清单取自autocbox.cpp 隐藏,收缩,复制Code

    ...
    void
    CAutoComboBox::OnEditUpdate() 
    {
        CString line;               // partial line entered by user
        CString sMatchedText;       // holds full line from list
    
        // get the text from the user input
        GetWindowText(line);
        int iHiLightStart = line.GetLength();
    
        // ?? remove
        // TRACEFN(_T("Entering OnEditUpdate line:%s\n"), (LPCTSTR) line);
    
        // if the line is empty
        if(line.GetLength() == 0) {
            // make sure the dropdown list is closed when back to
            // zero characters in the edit box
            ShowDropDown(FALSE);
    
            // empty the selection
            SetWindowText(_T(""));
    
            // cancel any previous selection
            m_iSelectedRow = -1;
    
            // turn on autocomplete again turned off by deletes
            m_bAutoComplete = true;
            return;
        }
        // if we have seen a delete or back key we leave the text alone so
        // that the user can continue to go backwards to correct an entry
        if(!m_bAutoComplete) {
            // but only for one character
            m_bAutoComplete = true;
    
            // if reversing entry, must keep insertion point on right
            if(m_bReverseEntry) {
                SetEditSel(0, 0);
            }
            return;
        }
        // if a single match, we can display that and identify the mismatch
        m_iSelectedRow = FindUniqueMatchedItem(line, sMatchedText);
    
        // if we found a unique matching row
        if(m_iSelectedRow >= 0) {
    
            // drop down the list part of the combo box
            ShowDropDown(TRUE);
    
            // ?? remove
            // TRACE(_T("OnEditUpdate: ShowDropDown(true)\n"));
    
            // set the dropdown to show the item as well
            // ?? int iCurSel = SetCurSel(m_iSelectedRow);
            // assert(iCurSel >= 0);
            // we try this so that the selection occurs AFTER the dropdown
            // box has been filled
            PostMessage(CB_SETCURSEL, m_iSelectedRow, 0);
    
            // ?? remove
            // TRACE(_T("OnEditUpdate-Post: SetCurSel(%d)\n"), m_iSelectedRow);
    
            // now we have to also remove the selection from the edit box
            // since we may want to continue to add to the string and
            // set out own highlight on the text we have added from the match
            //
            int iStartChar = 0;
            int iEndChar = -1;
    
            if(!m_bReverseEntry) {
                // straight entry, we want to highlight the added text from
                // the end of the input line text to the end of the field
                iStartChar = line.GetLength();
            }
            else {
                // reverse entry, we want to highlight the added text
                // on the left - from char 0 to match less line length
                iEndChar = sMatchedText.GetLength() - line.GetLength();
            }
            PostMessage(CB_SETEDITSEL, 0, MAKELPARAM(iStartChar, iEndChar));
    
            // ?? remove
            // TRACE(_T("OnEditUpdate-Post: SetEditSel(%d, %d)\n")
            //  , iStartChar, iEndChar);
    
            // set the window text to the match
            line = sMatchedText;
        }
        // if this text won't match any string and we are emulating
        // a drop list so the selection is forced
        else if(sMatchedText.IsEmpty() && m_autoComboBoxType == ACB_DROP_LIST) {
    
            // alert the user to no match
            MessageBeep(MB_ICONEXCLAMATION);
    
            // if we are not entering text backwards
            if(!m_bReverseEntry) {
                // remove the last character typed in error. at the end
                line.Delete(line.GetLength() - 1);
            }
            else {
                // remove the last character typed in error (at the beginning)
                // which will be in the firt position
                line.Delete(0);
            }
            assert(iHiLightStart > 0);
            iHiLightStart -= 1;
    
            // restore the line since the closeup cleared the edit box
            SetWindowText(line);
    
            // ?? remove
            // TRACE(_T("OnEditUpdate: SetWindowText(%s)\n"), (LPCSTR) line);
        }
        else {
            // the list box will be closed to show that there is no match
            ShowDropDown(FALSE);
    
            // ?? remove
            // TRACE(_T("OnEditUpdate: ShowDropDown(false)\n"));
    
            // restore the line since the closeup cleared the edit box
            SetWindowText(line);
    
            // ?? remove
            // TRACE(_T("OnEditUpdate: SetWindowText(%s)\n"), (LPCSTR) line);
        }
        // if we are not entering text backwards
        if(!m_bReverseEntry) {
            // now set the selection to beyond the last character which
            // moves the caret to the end
            SetEditSel(iHiLightStart, -1);
    
            // ?? remove
            // TRACE(_T("OnEditUpdate: SetEditSel(%d, -1)\n"), iHiLightStart);
        }
        else {
            // now set the insertion caret to the beginning so we
            // build up the text from the right
            SetEditSel(0, 0);
    
            // ?? remove
            // TRACE(_T("OnEditUpdate: SetEditSel(0, 0)\n"));
        }
        // ?? remove
        // TRACE(_T("EditUpdate SelectedRow: %d Line: %s Matched Text: %s\n")
        // , m_iSelectedRow, (LPCTSTR) line, (LPCTSTR) sMatchedText);
    }

    本文转载于:http://www.diyabc.com/frontweb/news347.html

  • 相关阅读:
    UVa LA 2965
    UVa LA 3695
    UVa LA 3029 City Game 状态拆分,最大子矩阵O(n2) 难度:2
    Uva LA 3177
    Uva LA 3902
    Uva 11520
    UVa Live 3635
    python学习笔记-day05 字典
    python学习笔记-day04 元组
    python学习笔记 day04 列表增删改查
  • 原文地址:https://www.cnblogs.com/Dincat/p/13438178.html
Copyright © 2020-2023  润新知