• WTL版本ACEdit控件,改写自MFC版,附带源码


      自动完成是个很酷也很实用的功能,比如在浏览器地址栏输入几个字母,相关的记录就会在下拉框中陈列出来。

      最近在做公司产品UI部分的改善,原版本是MFC做的,我决定用WTL,于是就遇到自动完成控件的问题。遍寻Internet,WTL版的只找到一个用IEnumString+IE组件实现的,但是其个性化修改比较困难。so我决定自己用WTL改写该控件,在此向原作者 Andreas Kapust 致谢!

      该控件包含四个文件:ACEdit.h, ACEdit.cpp, ACListWnd.h 和 ACListWnd.cpp。使用时用CACEdit 声明一个变量并将其与Edit控件或ComboBox控件建立关联(用DDX_CONTROL或者SubClassWindow)不可使用Attach,因为窗口过程函数必须要被替换。具体使用见代码。

      因为我本人也是个VC菜鸟,望有同学发现错误或不足之处能不吝指点。感谢!另外在WTL动态创建的窗口销毁上我还是不太明了,请大虾赐教!

      此为 _MODE_FIND_ALL_ 模式的效果

      

      此为 _MODE_FILESYSTEM_ 模式的效果

      

      原来不能发附件?贴下代码算了,要demo工程的邮件我 mforestlaw@163.com

    ACEdit.h

    /*************************************************************************
        Author : Andreas Kapust
        WTL Edition : Forest.Law
        Contact me at : mforestlaw@163.com
    **************************************************************************/
    #pragma once
    
    #include "ACListWnd.h"
    
    class CACEdit : public CWindowImpl<CACEdit, CEdit>,
                    public CWinDataExchange<CACEdit>,
                    public CMessageFilter {
    public:
        CACEdit();
        virtual ~CACEdit();
        virtual BOOL PreTranslateMessage(MSG* pMsg);
        
        void SetMode(int nMode = _MODE_STANDARD_);
        void SetSeparator(LPCTSTR lpszString, TCHAR lpszPrefixChar = 0);
        int  AddString(LPCTSTR lpszString);
        int  GetLBText(int nIndex, LPTSTR lpszText);
        void GetLBText(int nIndex, CString& rString);
        int  SetDroppedWidth(UINT nWidth);
        int  FindString(int nStartAfter, LPCTSTR lpszString);
        int  SelectString(int nStartAfter, LPCTSTR lpszString);
        void ShowDropDown(BOOL bShow = TRUE);
        void ResetContent();
        int  GetCurSel();
        void Init();
        void AddSearchString(LPCTSTR lpszString);
        void AddSearchStrings(LPCTSTR lpszStrings[]);
        void RemoveSearchAll();
        void SetStartDirectory(LPCTSTR lpszString);
        void SetFontHeight(long lHeight);
        void SetClearKillFocus();
    
        CACListWnd m_Liste;
    
    protected:
        BEGIN_MSG_MAP_EX(CACEdit)
            REFLECTED_COMMAND_CODE_HANDLER(EN_KILLFOCUS, OnKillFocus)
            REFLECTED_COMMAND_CODE_HANDLER(CBN_KILLFOCUS, OnKillFocus)
            MSG_WM_KEYDOWN(OnKeyDown)
            REFLECTED_COMMAND_CODE_HANDLER(EN_CHANGE, OnChange)
            REFLECTED_COMMAND_CODE_HANDLER(CBN_EDITCHANGE, OnChange)
            REFLECTED_COMMAND_CODE_HANDLER(CBN_DROPDOWN, OnCloseList)
            MSG_WM_ERASEBKGND(OnEraseBkgnd)
            MESSAGE_HANDLER(ENAC_UPDATE, OnUpdateFromList)
            MSG_WM_DESTROY(OnDestroy)
            DEFAULT_REFLECTION_HANDLER()
        END_MSG_MAP()
    
        LRESULT OnKillFocus(UINT wNotifyCode, UINT wID, HWND hWndCtl, BOOL& bHandled);
        void    OnKeyDown(TCHAR vkey, UINT repeats, UINT code);
        LRESULT OnChange(UINT wNotifyCode, UINT wID, HWND hWndCtl, BOOL& bHandled);
        LRESULT OnCloseList(UINT wNotifyCode, UINT wID, HWND hWndCtl, BOOL& bHandled);
        LRESULT OnEraseBkgnd(HDC hDC);
        LRESULT OnUpdateFromList(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
        void    OnDestroy();
            
        void    ReadDirectory(CString strDir);
        int        FindSepLeftPos(int nPos, bool bFindSepLeftPos = false);
        int        FindSepLeftPos2(int nPos);
        int        FindSepRightPos(int nPos);
        bool    HandleKey(UINT nChar, bool bFromChild);
    
        CString m_strEditText;
        CString m_strSeparator;
        CString m_strLastDirectory;
        TCHAR   m_prefixChar;
        int     m_nMode;
        bool    m_bCursorMode;
        int     m_nType;
        CEdit*  m_pEdit;
        TCHAR   m_szDrive[_MAX_DRIVE];
        TCHAR   m_szDir[_MAX_DIR];
        TCHAR   m_szFname[_MAX_FNAME];
        TCHAR   m_szExt[_MAX_EXT];
        CBitmap m_backBmp;
        BOOL    m_bClearTextKillFocus;
    };

    ACEdit.cpp

    #include "stdafx.h"
    #include "ACEdit.h"
    #include  <io.h>
    
    #define _EDIT_        1
    #define _COMBOBOX_    2
    
    CACEdit::CACEdit() {
        m_nMode = _MODE_STANDARD_;
        m_nType = -1;
        m_pEdit = NULL;
        m_bCursorMode = false;
        m_prefixChar = 0;
        m_bClearTextKillFocus = FALSE;
    }
    
    CACEdit::~CACEdit() {
    
    }
    
    BOOL CACEdit::PreTranslateMessage(MSG* pMsg) {
        if(pMsg->message == WM_KEYDOWN) {
            if(m_Liste.IsWindowVisible()) {
                if(m_nType == _COMBOBOX_) {
                    if(pMsg->wParam == VK_DOWN || pMsg->wParam == VK_UP) {
                        if(HandleKey(pMsg->wParam, false)) {
                            return TRUE;
                        }
                    }
                }
                if(pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN) {
                    if(HandleKey(pMsg->wParam, false)) {
                        return TRUE;
                    }
                }
            }
        }
        return FALSE;
    }
    
    void CACEdit::SetMode(int nMode) {
        if(m_nType == -1) {
            Init();
        }
        m_nMode = nMode;
    
        if(nMode == _MODE_CURSOR_O_LIST_) {
            m_nMode |= _MODE_STANDARD_;
        }
    
        if(nMode & _MODE_FILESYSTEM_) {
            m_strSeparator = _T("\");
        }
    
        if(nMode & _MODE_FIND_ALL_) {
            m_Liste.m_lMode |= _MODE_FIND_ALL_;
            SetSeparator(_T(" "));
        }
    }
    
    void CACEdit::SetSeparator(LPCTSTR lpszString,TCHAR lpszPrefixChar) {
        m_strSeparator = lpszString;
        m_Liste.m_prefixChar = m_prefixChar = lpszPrefixChar;
        SetMode(_MODE_SEPARATION_);
    }
    
    int CACEdit::AddString(LPCTSTR lpszString) {
        if(m_nType == _COMBOBOX_) {
            return ((CComboBox*)this)->AddString(lpszString);
        }
        return CB_ERR;
    }
    
    int CACEdit::GetLBText(int nIndex, LPTSTR lpszText) {
        if(m_nType == _COMBOBOX_) {
            return ((CComboBox*)this)->GetLBText(nIndex, lpszText);
        }
        return CB_ERR;
    }
    
    void CACEdit::GetLBText(int nIndex, CString& rString) {
        if(m_nType == _COMBOBOX_) {
            ((CComboBox*)this)->GetLBText(nIndex, rString);
        }
    }
    
    int CACEdit::SetDroppedWidth(UINT nWidth) {
        if(m_nType == _COMBOBOX_) {
            return ((CComboBox*)this)->SetDroppedWidth(nWidth);
        }
        return CB_ERR;
    }
    
    int CACEdit::FindString(int nStartAfter, LPCTSTR lpszString) {
        if(m_nType == _COMBOBOX_) {
            return ((CComboBox*)this)->FindString(nStartAfter, lpszString);
        }
        return CB_ERR;
    }
    
    int CACEdit::SelectString(int nStartAfter, LPCTSTR lpszString) {
        if(m_nType == _COMBOBOX_) {
            return ((CComboBox*)this)->SelectString(nStartAfter, lpszString);
        }
        return CB_ERR;
    }
    
    void CACEdit::ShowDropDown(BOOL bShow) {
        if(m_nType == _COMBOBOX_) {
            ((CComboBox*)this)->ShowDropDown(bShow);
        }
    }
    
    void CACEdit::ResetContent() {
        if(m_nType == _COMBOBOX_) {
            ((CComboBox*)this)->ResetContent();
        }
    }
    
    int CACEdit::GetCurSel() {
        if(m_nType == _COMBOBOX_) {
            return ((CComboBox*)this)->GetCurSel();
        }
        return CB_ERR;
    }
    
    void CACEdit::Init() {
    //    m_backBmp.LoadBitmap(IDB_QUREY);
        CMessageLoop* pLoop = _Module.GetMessageLoop();
        ATLASSERT(pLoop != NULL);
        pLoop->AddMessageFilter(this);
    
        WNDCLASS wndcls;
        wndcls.style = CS_CLASSDC | CS_SAVEBITS | CS_HREDRAW | CS_VREDRAW;
        wndcls.lpfnWndProc = ::DefWindowProc;
        wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
        wndcls.hInstance = _Module.GetModuleInstance();
        wndcls.hIcon = NULL;
        wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndcls.hbrBackground = (HBRUSH)COLOR_WINDOW;
        wndcls.lpszMenuName = NULL;
        wndcls.lpszClassName = _T("ACListWnd");
        RegisterClass(&wndcls);
    
        CRect rcWnd;
        CRect rcWnd1;
        GetWindowRect(rcWnd);
    
        HWND hListe = CreateWindowEx(WS_EX_TOOLWINDOW, 
                                     _T("ACListWnd"), 
                                     NULL,
                                     WS_CHILD | WS_BORDER | WS_CLIPSIBLINGS | WS_OVERLAPPED, 
                                     rcWnd.left, 
                                     rcWnd.top + rcWnd.Height(),
                                     rcWnd.Width(), 
                                     rcWnd.Height(),
                                     GetDesktopWindow(), 
                                     NULL, 
                                     _Module.GetModuleInstance(), 
                                     NULL);
        ::SetWindowPos(hListe, HWND_TOPMOST, rcWnd.left, rcWnd.top + rcWnd.Height(), 
                       rcWnd.Width(), rcWnd.Height(), NULL);
        m_Liste.SubclassWindow(hListe);
    
        CString strClassName;
        ::GetClassName(this->m_hWnd, strClassName.GetBuffer(32), 32);
        strClassName.ReleaseBuffer();
    
        if (strClassName.Compare(_T("Edit")) == 0) {
            m_nType = _EDIT_;
        } else {
            if (strClassName.Compare(_T("ComboBox")) == 0) {
                m_nType = _COMBOBOX_;
                m_pEdit = (CEdit*)&GetWindow(GW_CHILD);
                ATLASSERT(m_pEdit);
                ::GetClassName(m_pEdit->m_hWnd, strClassName.GetBuffer(32), 32);
                strClassName.ReleaseBuffer();
                ATLASSERT(strClassName.Compare(_T("Edit")) == 0);
            }
        }
    
        if(m_nType == -1) {
            ATLASSERT(0);
            return;
        }
    
        m_Liste.Init(this);
    }
    
    void CACEdit::AddSearchString(LPCTSTR lpszString) {
        if(m_nType == -1) {
            ATLASSERT(0); 
            return;
        } 
        m_Liste.AddSearchString(lpszString);
    }
    
    void CACEdit::AddSearchStrings(LPCTSTR lpszStrings[]) {
        int i = 0;
        LPCTSTR str = NULL;
        if(m_nType == -1) {
            ATLASSERT(0); 
            return;
        }
        m_Liste.RemoveAll();
        do {
            str = lpszStrings[i];
            if(str) {
                m_Liste.AddSearchString(str);
            }
            i++;
        } while(str);
        m_Liste.SortSearchList();
    }
    
    void CACEdit::RemoveSearchAll() {
        if(m_nType == -1) {
            ATLASSERT(0); 
            return;
        }
        m_Liste.RemoveAll();
    }
    
    void CACEdit::SetStartDirectory(LPCTSTR lpszString) {
        if(m_nType == -1) {
            ATLASSERT(0); 
            return;
        }
        if(m_nMode & _MODE_FS_START_DIR_) {
            ReadDirectory(lpszString);
        }
    }
    
    void CACEdit::SetFontHeight(long lHeight) {
        m_Liste.SetFontHeight(lHeight);
    }
    
    void CACEdit::SetClearKillFocus() {
        m_bClearTextKillFocus = TRUE;
    }
    
    LRESULT CACEdit::OnKillFocus(UINT wNotifyCode, UINT wID, HWND hWndCtl, BOOL& bHandled) {
        if(m_Liste.m_hWnd) {
            m_Liste.ShowWindow(false);
        }
        if (m_bClearTextKillFocus) {
            SetWindowText(_T(""));    
            Invalidate();
        }
        return 0;
    }
    
    void CACEdit::OnKeyDown(TCHAR vkey, UINT repeats, UINT code) {
        if(!HandleKey(vkey, false)) {
            DefWindowProc();
        }
    }
    
    
    LRESULT CACEdit::OnChange(UINT wNotifyCode, UINT wID, HWND hWndCtl, BOOL& bHandled) {
        CString strText;
        int nPos=0;
    
        if(m_nType == -1) {
            ATLASSERT(0); 
            return 0;
        }
    
        GetWindowText(m_strEditText);
        int nLen = m_strEditText.GetLength();
    
        if(m_nMode & _MODE_FILESYSTEM_ || m_nMode & _MODE_FS_START_DIR_) {
            if(!m_bCursorMode) {
                CPoint point;
                if(m_nType == _EDIT_) {
                    GetCaretPos(&point);
                    nPos = LOWORD(((CEdit*)this)->CharFromPos(point));
                }
    
                if(m_nType == _COMBOBOX_) {
                    GetCaretPos(&point);
                    nPos = m_pEdit->CharFromPos(point);
                }
    
                if(m_nMode & _MODE_FS_START_DIR_) {
                    if(nLen) {
                        m_Liste.FindString(-1, m_strEditText);
                    } else {
                        m_Liste.ShowWindow(false);
                    }
                } else {
                    if(nLen > 2 && nPos == nLen) {            
                        if(_taccess(m_strEditText, 0) == 0) {
                            ReadDirectory(m_strEditText);
                        }
                        m_Liste.FindString(-1, m_strEditText);
                    } else {
                        m_Liste.ShowWindow(false);
                    }
                }
            }
        }
        
        if(m_nMode & _MODE_SEPARATION_) {
            if(!m_bCursorMode) {
                CPoint point;
                if(m_nType == _EDIT_) {
                    GetCaretPos(&point);
                    nPos = LOWORD(((CEdit*)this)->CharFromPos(point));
                }
    
                if(m_nType == _COMBOBOX_) {
                    GetCaretPos(&point);
                    nPos = m_pEdit->CharFromPos(point);
                }
    
                int nLeft = FindSepLeftPos(nPos - 1);
                int nRight = FindSepRightPos(nPos);
                strText = m_strEditText.Mid(nLeft, nRight - nLeft);
                m_Liste.FindString(-1, strText);
            }
        }
    
        if(m_nMode & _MODE_STANDARD_) {
            if(!m_bCursorMode) {
                m_Liste.FindString(-1, m_strEditText);
            }
        }
    
        SendMessage(ENAC_UPDATE, EN_UPDATE, GetDlgCtrlID());
        return 0;
    }
    
    LRESULT CACEdit::OnCloseList(UINT wNotifyCode, UINT wID, HWND hWndCtl, BOOL& bHandled) {
        m_Liste.ShowWindow(false);
        return 0;
    }
    
    LRESULT CACEdit::OnEraseBkgnd(HDC hDC) {
        CDC dc(hDC);     
        RECT updatarect;       
        GetClientRect(&updatarect);   
    
        CBrush BackBrush = CreatePatternBrush(m_backBmp);
        CBrush oldBrush = dc.SelectBrush(BackBrush);           
    
        CPen penBlack = CreatePen(PS_NULL, 1, RGB(0, 0, 0));
        CPen oldPen = dc.SelectPen(penBlack);
    
        dc.Rectangle(&updatarect);     
    
        dc.SelectBrush(oldBrush);   
        dc.SelectPen(oldPen);
    
        return TRUE;
    }
    
    LRESULT CACEdit::OnUpdateFromList(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
        if(lParam == WM_KEYDOWN) {
            HandleKey(VK_DOWN, true);
        }
        return 0;
    }
    
    void CACEdit::OnDestroy() {
        m_Liste.SendMessage(WM_CLOSE);
    }
    
    void CACEdit::ReadDirectory(CString strDir) {
        if(strDir.Right(1) != _T('\')) {
            _tsplitpath_s(strDir, m_szDrive, m_szDir, m_szFname, m_szExt);
            strDir.Format(_T("%s%s"), m_szDrive, m_szDir);
        }
        TCHAR ch = (TCHAR)towupper(strDir.GetAt(0));
        strDir.SetAt(0, ch);
    
        CString m_Name, m_File, strDir1 = strDir;
        if(strDir.Right(1) != _T('\')) {
            strDir += _T("\");
        }
        if(m_strLastDirectory.CompareNoCase(strDir) == 0 && m_Liste.m_searchList.GetSize()) {
            return;
        }
        m_strLastDirectory = strDir;
        strDir += _T("*.*");
    
        WIN32_FIND_DATA findData;
        HANDLE findHandle = FindFirstFile(strDir, &findData);
        if(INVALID_HANDLE_VALUE == findHandle) {
            return;
        }
        while(FindNextFile(findHandle, &findData)) {
            m_File = findData.cFileName;
            if(findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN || 
                findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
                    continue;
            }
            if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                if(_MODE_ONLY_FILES & m_nMode) {
                    continue;
                }
                if(m_File.CompareNoCase(_T(".")) == 0 ||
                    m_File.CompareNoCase(_T("..")) == 0) {
                        continue;
                }
                if(m_File.Right(1) != _T('\')) {
                    m_File += _T("\");
                }
            } else {
                if(_MODE_ONLY_DIRS & m_nMode) {
                    continue;
                }
            }
    
            if(m_nMode & _MODE_FS_START_DIR_) {
                m_Name = m_File;
            } else {
                m_Name = strDir1;
                if(m_Name.Right(1) != _T('\')) {
                    m_Name += _T("\");
                }
                m_Name += m_File;
            }
            AddSearchString(m_Name);
        }
        FindClose(findHandle);
    }
    
    int CACEdit::FindSepLeftPos(int nPos, bool bFindSepLeftPos) {
        int nLen = m_strEditText.GetLength(); 
        TCHAR ch;
        if(nPos >= nLen && nLen != 1) {
            nPos =  nLen -1;
        }
    
        int i = nPos;
        for(; i>=0; i--) {
            ch = m_strEditText.GetAt(i);
            if(m_prefixChar == ch) {
                return i + (bFindSepLeftPos ? 1 : 0);
            }
            if(m_strSeparator.Find(ch) != -1) {
                break;
            }
        }
    
        return  i + 1;
    }
    
    int CACEdit::FindSepLeftPos2(int nPos) {
        int nLen = m_strEditText.GetLength(); 
        TCHAR ch;
    
        if(nPos >= nLen && nLen != 1) {
            nPos =  nLen - 1;
        }
    
        if(nLen == 1) {
            return 0;
        }
    
        for(int i=nPos; i>=0; i--) {
            ch = m_strEditText.GetAt(i);
            if(m_prefixChar == ch) {
                return 1;
            }
        }
    
        return  0;
    }
    
    int CACEdit::FindSepRightPos(int nPos) {
        int nLen = m_strEditText.GetLength(); 
        TCHAR ch;
    
        int i = nPos;
        for(; i<nLen; i++) {
            ch = m_strEditText.GetAt(i);
            if(m_strSeparator.Find(ch) != -1) {
                break;
            }
        }
        return i;
    }
    
    bool CACEdit::HandleKey(UINT nChar, bool bFromChild) {
        if (nChar == VK_ESCAPE || nChar == VK_RETURN) {
            m_Liste.ShowWindow(false);
            return true;
        }
    
        if (nChar == VK_DOWN || nChar == VK_UP || 
            nChar == VK_PRIOR || nChar == VK_NEXT || 
            nChar == VK_HOME || nChar == VK_END) {
            if(!m_Liste.IsWindowVisible() && (m_nMode & _MODE_CURSOR_O_LIST_)) {
                GetWindowText(m_strEditText);
                if(m_strEditText.IsEmpty()) {
                    m_Liste.CopyList();
                    return true;
                }    
            }
            if(m_Liste.IsWindowVisible()) {
                int nPos;
                if(m_nMode & _MODE_STANDARD_ || 
                   m_nMode & _MODE_FILESYSTEM_ || 
                   m_nMode & _MODE_FS_START_DIR_) {
                    m_bCursorMode = true;
                    if(!bFromChild) {
                        m_strEditText = m_Liste.GetNextString(nChar);
                    } else {
                        m_strEditText = m_Liste.GetString();
                    }
                    if(m_nMode & _MODE_FILESYSTEM_) {
                        if(m_strEditText.Right(1) == _T('\')) {
                            m_strEditText = m_strEditText.Mid(0, m_strEditText.GetLength() - 1);
                        }
                    }
    
                    m_Liste.SelectItem(-1);
                    SetWindowText(m_strEditText);
                    nPos = m_strEditText.GetLength();
                    
                    if(m_nType == _COMBOBOX_) {
                        m_pEdit->SetSel(nPos, nPos, true);
                        m_pEdit->SetModify(true);
                    }
                    if(m_nType == _EDIT_) {
                        this->SetSel(0, nPos, true);
                        this->SetModify(true);
                    }
    
                    SendMessage(ENAC_UPDATE, WM_KEYDOWN, GetDlgCtrlID());
                    m_bCursorMode = false;
                    return true;
                }
    
                if(m_nMode & _MODE_SEPARATION_) {
                    CString strText;
                    CString strLeft;
                    CString strRight;
                    int nLeft;
                    int nRight;
                    int nPos = 0;
                    int nLen;
    
                    m_bCursorMode = true;
                    GetWindowText(m_strEditText);
                    CPoint point;
                    if(m_nType == _EDIT_) {
                        GetCaretPos(&point);
                        nPos = LOWORD(((CEdit*)this)->CharFromPos(point));
                    }
    
                    if(m_nType == _COMBOBOX_) {
                        GetCaretPos(&point);
                        nPos = m_pEdit->CharFromPos(point);
                    }
                    
                    nLeft = FindSepLeftPos(nPos - 1, true);
                    nRight = FindSepRightPos(nPos);
    
                    strText = m_strEditText.Left(nLeft);
    
                    if(!bFromChild) {
                        strText += m_Liste.GetNextString(nChar);
                    } else {
                        strText += m_Liste.GetString();
                    }
                    m_Liste.SelectItem(-1);
                    strText += m_strEditText.Mid(nRight);
                    nLen = m_Liste.GetString().GetLength();
    
                    SetWindowText(strText);
                    SendMessage(ENAC_UPDATE, WM_KEYDOWN, GetDlgCtrlID());
                    
                    nRight = FindSepLeftPos2(nPos - 1);
                    nLeft -= nRight;
                    nLen += nRight;
    
                    if(m_nType == _EDIT_) {
                        ((CEdit*)this)->SetModify(true);
                        ((CEdit*)this)->SetSel(nLeft, nLeft + nLen, false);
                    }
    
                    if(m_nType == _COMBOBOX_) {
                        m_pEdit->SetModify(true);
                        m_pEdit->SetSel(nLeft, nLeft + nLen, true);
                    }
                    
                    m_bCursorMode = false;
                    return true;
                }
            }
        }
        return false;
    }

    ACListWnd.h

    #pragma once
    
    #define ENAC_UPDATE                WM_USER + 1200 
    #define IDTimerInstall             10
    #define _MAX_ENTRYS_              5
    
    #define _MODE_ONLY_FILES          (1L << 16)
    #define _MODE_ONLY_DIRS            (1L << 17)
    #define _MODE_STANDARD_            (1L << 0)
    #define _MODE_SEPARATION_         (1L << 1)
    #define _MODE_FILESYSTEM_          (1L << 2)
    #define _MODE_FS_START_DIR_        (1L << 3)
    #define _MODE_CURSOR_O_LIST_       (1L << 4)
    #define _MODE_FIND_ALL_            (1L << 5)
    #define _MODE_FS_ONLY_FILE_        (_MODE_FILESYSTEM_ | _MODE_ONLY_FILES)
    #define _MODE_FS_ONLY_DIR_         (_MODE_FILESYSTEM_ | _MODE_ONLY_DIRS)
    #define _MODE_SD_ONLY_FILE_        (_MODE_FS_START_DIR_ | _MODE_ONLY_FILES)
    #define _MODE_SD_ONLY_DIR_         (_MODE_FS_START_DIR_ | _MODE_ONLY_DIRS)
    
    class CACListWnd : public CWindowImpl<CACListWnd> {
    public:
        CACListWnd();
        virtual ~CACListWnd();
    
        void    Init(CWindow* pWindow);
        bool    EnsureVisible(int nItem, bool bWait);
        bool    SelectItem(int nItem);
        int     FindString(int nStartAfter, LPCTSTR lpszString, bool bDisplayOnly = false);
        int     FindStringExact(int nIndexStart, LPCTSTR lpszFind);
        int     SelectString(LPCTSTR lpszString);
        bool    GetText(int nItem, CString& strText);
        void    AddSearchString(LPCTSTR lpszString);
        void    RemoveAll();
        CString GetString();
        CString GetNextString(int nChar);
        void    CopyList();
        void    SortSearchList();
        void    DrawItem(CDC* pDC, long lItem, long lWidth);
        void    SetFontHeight(long lHeight);
        
        CString m_strDisplay;
        TCHAR   m_prefixChar;
        long    m_lMode;
        long    m_lFontHeight;
        CSimpleArray<CString> m_searchList;
    
    protected:
        BEGIN_MSG_MAP_EX(CACListWnd)
            MSG_WM_PAINT(OnPaint)
            MSG_WM_SIZE(OnSize)
            MSG_WM_ERASEBKGND(OnEraseBkgnd)
            MSG_WM_NCPAINT(OnNcPaint)
            MSG_WM_KEYDOWN(OnKeyDown)
            MSG_WM_NCCALCSIZE(OnNcCalcSize)
            MSG_WM_VSCROLL(OnVScroll)
            MSG_WM_ACTIVATEAPP(OnActivateApp)
            MSG_WM_NCHITTEST(OnNcHitTest)
            MSG_WM_LBUTTONDOWN(OnLButtonDown)
            MSG_WM_RBUTTONDOWN(OnRButtonDown)
            MSG_WM_SETCURSOR(OnSetCursor)
            MSG_WM_SHOWWINDOW(OnShowWindow)
            MSG_WM_NCLBUTTONDOWN(OnNcLButtonDown)
            MSG_WM_MOUSEMOVE(OnMouseMove)
            MSG_WM_TIMER(OnTimer)
            MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo)
        END_MSG_MAP()
    
        void    OnPaint(HDC hDC);
        void    OnSize(UINT nType, CSize size);
        LRESULT OnEraseBkgnd(HDC hDC);
        void    OnNcPaint(HRGN hRgn);
        void    OnKeyDown(TCHAR vkey, UINT repeats, UINT code);
        LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam);
        void    OnVScroll(int nSBCode, short nPos, HWND hWnd);
        void    OnActivateApp(BOOL bActive, DWORD dwThreadID);
        LRESULT OnNcHitTest(CPoint point);
        void    OnLButtonDown(UINT nFlags, CPoint point);
        void    OnRButtonDown(UINT nFlags, CPoint point);
        LRESULT OnSetCursor(HWND hWnd, UINT nHitTest, UINT nMessage);
        void    OnShowWindow(BOOL bShow, int nStatus);
        void    OnNcLButtonDown(UINT nHitTest, CPoint point);
        void    OnMouseMove(UINT nFlags, CPoint point);
        void    OnTimer(UINT nIDEvent);
        void    OnGetMinMaxInfo(LPMINMAXINFO lpMMI);
    
        int     HitTest(CPoint point);
        void    SetScroller();
        void    SetProp();
        long    ScrollBarWidth();
        void    InvalidateAndScroll();
        void    SortList(CSimpleArray<CString>& List);
        static int CompareString(const void* p1, const void* p2);
    
        CScrollBar m_vertBar;
        CScrollBar m_horzBar;
        CRect      m_lastSize;
        CRect      m_parentRect;
        CEdit*     m_pEdit;
        int        m_nIDTimer;
        long       m_lTopIndex;
        long       m_lCount;
        long       m_lItemHeight;
        long       m_lVisibleItems;
        long       m_lSelItem;
        CSimpleArray<CString> m_displayList;
    };

    ACListWnd.cpp

    #include "stdafx.h"
    #include "ACListWnd.h"
    
    void DoPaintMessageLoop() {
        MSG msg;
        while(::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE)) {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
    }
    
    CACListWnd::CACListWnd() {
        m_lTopIndex = 0;
        m_lCount = 0;
        m_lItemHeight = 16;
        m_lSelItem = -1;
        m_lVisibleItems = 0;
        m_pEdit = NULL;
        m_lastSize.SetRectEmpty();
        m_prefixChar = 0;
        m_lMode = 0;
        m_lFontHeight = 0;
    }
    
    CACListWnd::~CACListWnd() {
        m_searchList.RemoveAll();
        m_displayList.RemoveAll();
    }
    
    void CACListWnd::Init(CWindow* pWindow) {
        ATLASSERT(m_vertBar.Create(this->m_hWnd, 
                                   CRect(0, 0, GetSystemMetrics(SM_CYVSCROLL), 100),
                                   NULL, 
                                   WS_CHILD | WS_VISIBLE|SBS_VERT|SBS_LEFTALIGN,
                                   NULL));
    
        SetScroller();
        m_pEdit = (CEdit*)pWindow;
        m_lCount = m_displayList.GetSize();
        m_vertBar.SetScrollPos(0, false);
        SetProp();
    
        CDC dc(GetDC());
        LOGFONT logFont = {0};
        CFont((HFONT)GetStockObject(DEFAULT_GUI_FONT)).GetLogFont(&logFont);
    
        if (m_lFontHeight > 0) {
            logFont.lfHeight = m_lFontHeight;
            logFont.lfWeight = FW_BOLD;
            dc.SelectFont(CreateFontIndirect(&logFont));
        }
    
        m_lItemHeight = abs(logFont.lfHeight);
    }
    
    bool CACListWnd::EnsureVisible(int nItem, bool bWait) {
        if(nItem > m_lTopIndex && nItem < m_lTopIndex + m_lVisibleItems) {
            return false;
        }
    
        if(nItem > m_lTopIndex) {
            int nLen = nItem;
            for(int i=m_lTopIndex; i<nLen; i++) {
                if(i >= m_lCount - m_lVisibleItems || i + m_lVisibleItems > nItem) {
                    break;
                }
                m_lTopIndex++;
                if(bWait) {
                    InvalidateAndScroll();
                    Sleep(10);
                    DoPaintMessageLoop();
                }
            }
            InvalidateAndScroll();
            return true;
        }
    
        if(nItem < m_lTopIndex) {
            while(nItem < m_lTopIndex) {
                if(m_lTopIndex > 0) {
                    m_lTopIndex--;
                } else {
                    break;
                }
                if(bWait) {
                    InvalidateAndScroll();
                    Sleep(10);
                    DoPaintMessageLoop();
                }
            }
            InvalidateAndScroll();
            return true;
        }
        return false;
    }
    
    bool CACListWnd::SelectItem(int nItem) {
        if(nItem > m_lCount) {
            return false;
        }
        if(nItem == -1) {
            EnsureVisible(m_lSelItem, false);
            Invalidate();
            return false;
        }
        m_lSelItem = nItem;
        if(!EnsureVisible(nItem,true)) {
            Invalidate();
        }
        return true;
    }
    
    int CACListWnd::FindString(int nStartAfter, LPCTSTR lpszString, bool bDisplayOnly) {
        long lCount = m_displayList.GetSize();
        if(!bDisplayOnly) {
            CString str1;
            CString str2(lpszString);
            if(!m_pEdit) {
                ShowWindow(false);
                return -1;
            }
            if(nStartAfter > m_searchList.GetSize()) {
                ShowWindow(false);
                return -1;
            }
            if(str2.IsEmpty()) {
                ShowWindow(false);
                return -1;
            }
            m_displayList.RemoveAll();
            str2.MakeUpper();
            for(int i=nStartAfter + 1; i<m_searchList.GetSize(); i++) {
                if(m_prefixChar) {
                    str1 = m_prefixChar;
                } else {
                    str1 = _T("");
                }
                str1 += m_searchList[i];
                str1.MakeUpper();
                if(m_lMode & _MODE_FIND_ALL_) {
                    if(str1.Find(str2) >= 0) {
                        m_displayList.Add(m_searchList[i]);
                    }
                } else {
                    if(str1.Find(str2) == 0) {
                        m_displayList.Add(m_searchList[i]);
                    }
                }
            }
        }
    
        m_lCount = m_displayList.GetSize();
        if(m_lCount) {
            CRect rcWnd;
            int nWidth;
            m_pEdit->GetWindowRect(rcWnd);
            
            SetScroller();
            SetProp();
            ShowWindow(true);
            Invalidate();
    
            int nHeight = m_lCount * m_lItemHeight + 2 * GetSystemMetrics(SM_CYBORDER);
            if(m_lCount > _MAX_ENTRYS_) {
                nHeight = _MAX_ENTRYS_ * m_lItemHeight + 2 * GetSystemMetrics(SM_CYBORDER);
            }
    
            if(!m_lastSize.IsRectEmpty()) {
                nWidth = m_lastSize.Width(); 
                nHeight = m_lastSize.Height(); 
                rcWnd.top += rcWnd.Height();
                rcWnd.right = rcWnd.left + nWidth;
                rcWnd.bottom = rcWnd.top + nHeight;
                MoveWindow(rcWnd.left, rcWnd.top, rcWnd.Width(), rcWnd.Height());
            } else {
                MoveWindow(rcWnd.left, rcWnd.top + rcWnd.Height(), rcWnd.Width(), nHeight);
            }
    
            if(lCount != m_displayList.GetSize()) {
                m_lSelItem = -1;
            }
            SortList(m_displayList);
        } else {
            ShowWindow(false);
        }
        return 1;
    }
    
    int CACListWnd::FindStringExact(int nIndexStart, LPCTSTR lpszFind) {
        if(nIndexStart > m_searchList.GetSize()) {
            return -1;
        }
        for(int i=nIndexStart + 1; i<m_searchList.GetSize(); i++) {
            if(m_searchList[i].Compare(lpszFind) == 0) {
                return i;
            }
        }
        return -1;
    }
    
    int CACListWnd::SelectString(LPCTSTR lpszString) {
        int nItem = FindString(-1, lpszString);
        SelectItem(nItem);
        return nItem;
    }
    
    bool CACListWnd::GetText(int nItem, CString& strText) {
        if(nItem < 0 || nItem > m_searchList.GetSize()) {
            return false;
        }
        strText = m_searchList[nItem];
        return true;
    }
    
    void CACListWnd::AddSearchString(LPCTSTR lpszString) {
        m_searchList.Add(lpszString);
    }
    
    void CACListWnd::RemoveAll() {
        m_searchList.RemoveAll();
        m_displayList.RemoveAll();
    }
    
    CString CACListWnd::GetString() {
        int i = m_displayList.GetSize();
        if(i == 0) {
            return _T("");
        }
        if(i <= m_lSelItem || m_lSelItem == -1) {
            i = 0;
        } else {
            i = m_lSelItem;
        }
        return m_displayList[i];
    }
    
    CString CACListWnd::GetNextString(int nChar) {
        switch(nChar) {
        case VK_DOWN: 
            m_lSelItem++; 
            break;
        case VK_UP: 
            m_lSelItem--; 
            break;
        case VK_PRIOR:
            m_lSelItem -= m_lVisibleItems;
            if(m_lSelItem < 0) {
                m_lSelItem = 0;
            }
            break;
        case VK_NEXT:
            m_lSelItem += m_lVisibleItems;
            if(m_lSelItem >= m_lCount - 1) {
                m_lSelItem = m_lCount - 1;
            }
            break;
        case VK_HOME:
            m_lSelItem = 0;
            break;
        case VK_END:
            m_lSelItem = m_lCount - 1;
            break;
        }
    
        if(m_lSelItem < 0) {
            m_lSelItem = m_lCount - 1;
        }
        if(m_lSelItem >= m_lCount) {
            m_lSelItem = 0;
        }
        if(EnsureVisible(m_lSelItem, m_lCount > 50 ? false : true)) {
            InvalidateAndScroll();
        }
        return GetString();
    }
    
    void CACListWnd::CopyList() {
        m_displayList = m_searchList;
        m_lCount = m_displayList.GetSize();
        if(m_lCount) {
            FindString(0, _T(""), true);
        }
    }
    
    void CACListWnd::SortSearchList() {
        SortList(m_searchList);
    }
    
    void CACListWnd::DrawItem(CDC* pDC, long lItem, long lWidth) {
        long y = lItem - m_lTopIndex;
        CRect rcLabel(2, y * m_lItemHeight, lWidth, (y + 1) * m_lItemHeight);
        pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
        if(lItem == m_lSelItem) {
            rcLabel.left = 0;
            pDC->FillSolidRect(rcLabel, ::GetSysColor(COLOR_HIGHLIGHT));
            pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
            rcLabel.left = 2;
        }
        if(m_prefixChar) {
            m_strDisplay = m_prefixChar + m_displayList[lItem];
        } else {
            m_strDisplay = m_displayList[lItem];
        }
        pDC->DrawText(m_strDisplay, -1, rcLabel, DT_LEFT | DT_SINGLELINE | 
                      DT_NOPREFIX | DT_VCENTER | DT_END_ELLIPSIS);
    }
    
    void CACListWnd::SetFontHeight(long lHeight) {
        m_lFontHeight = lHeight;
    }
    
    void CACListWnd::OnPaint(HDC hDC) {
        CRect rcWnd;
        CRect rect;
        CRect rc;
        CDC* pDC = NULL;
    
        GetClientRect(rc);
        rcWnd = rect = rc;
    
        rc.left = rc.right - GetSystemMetrics(SM_CXHSCROLL);
        rc.top = rc.bottom - GetSystemMetrics(SM_CYVSCROLL);
    
        rect.right -= ScrollBarWidth();
        
        CPaintDC dc(this->m_hWnd);
        CDC MemDC = CreateCompatibleDC(dc);
    
        CBitmap bitmap = CreateCompatibleBitmap(dc, rect.Width(), rect.Height());
        CBitmap oldBitmap = MemDC.SelectBitmap(bitmap);
    
        MemDC.SetWindowOrg(rect.left, rect.top);
    
        long lWidth = rcWnd.Width() - ScrollBarWidth();
    
        MemDC.FillSolidRect(rcWnd, ::GetSysColor(COLOR_WINDOW));
        
        int i = 0;
        if (m_lFontHeight <= 0) {
            MemDC.SelectFont((HFONT)GetStockObject(DEFAULT_GUI_FONT)); 
            MemDC.SetBkMode(TRANSPARENT);
            for(i=m_lTopIndex; i<m_lCount; i++) {
                DrawItem(&MemDC, i, lWidth);
            }
        } else {        
            LOGFONT logFont = {0};
            CFont((HFONT)GetStockObject(DEFAULT_GUI_FONT)).GetLogFont(&logFont);
            logFont.lfHeight = m_lFontHeight;
            logFont.lfWeight =  FW_BOLD;
            logFont.lfItalic = TRUE;
            CFont font = CreateFontIndirect(&logFont);
            CFont oldFont = MemDC.SelectFont(font);
            MemDC.SetBkMode(TRANSPARENT);
            for(i=m_lTopIndex; i<m_lCount; i++) {
                DrawItem(&MemDC, i, lWidth);
            }
            MemDC.SelectFont(oldFont);
        }
    
        CPen pen1 = CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_WINDOW));
        CPen pen2 = CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_BTNFACE));
        CPen pen3 = CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW));
    
        pDC = &dc;
        if(m_vertBar.IsWindowVisible()) {
            dc.FillSolidRect(rc, ::GetSysColor(COLOR_BTNFACE));
        } else {
            pDC = &MemDC;
        }
    
        CPen oldPen = pDC->SelectPen(pen1);
        int nBottom= rcWnd.bottom - GetSystemMetrics(SM_CXHSCROLL) - 1;
        lWidth = GetSystemMetrics(SM_CXHSCROLL);
    
        int a = 1;
        for(i=0; i<20; i++, a++) {
            if(a == 1) {
                pDC->SelectPen(pen1);
            } else if(a == 2) {
                pDC->SelectPen(pen2);
            } else if(a == 3) {
                pDC->SelectPen(pen3);
            } else {
                a = 0;
            }
            pDC->MoveTo(rc.left + i - 1, rcWnd.bottom);
            pDC->LineTo(rc.left + i + lWidth, nBottom);
        }
        dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), MemDC, 
                  rect.left, rect.top, SRCCOPY);
        pDC->SelectPen(oldPen);
        MemDC.SelectBitmap(oldBitmap);
    }
    
    void CACListWnd::OnSize(UINT nType, CSize size) {
        SetScroller();
        SetProp();
        if(!m_lastSize.IsRectEmpty()) {
            GetWindowRect(m_lastSize);
        }
    }
    
    LRESULT CACListWnd::OnEraseBkgnd(HDC hDC) {
        return 0;
    }
    
    void CACListWnd::OnNcPaint(HRGN hRgn) {
        CWindowDC dc(this->m_hWnd);
        CRect rectClient;
        CRect rectWindow;
        CRect rcWnd;
        GetClientRect(rectClient);
        GetWindowRect(rectWindow);
        ScreenToClient(rectWindow);
    
        rectClient.OffsetRect(-(rectWindow.left), -(rectWindow.top));
        dc.ExcludeClipRect(rectClient);
    
        rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);
    
        dc.FillSolidRect(rectWindow, ::GetSysColor(COLOR_WINDOWTEXT));
    }
    
    void CACListWnd::OnKeyDown(TCHAR vkey, UINT repeats, UINT code) {
        if (vkey == VK_ESCAPE) {
            ShowWindow(false);
        }
    }
    
    LRESULT CACListWnd::OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) {
        NCCALCSIZE_PARAMS* lpncsp = (NCCALCSIZE_PARAMS*)lParam;
        return ::InflateRect(lpncsp->rgrc, -GetSystemMetrics(SM_CXBORDER),
                             -GetSystemMetrics(SM_CYBORDER));
    }
    
    void CACListWnd::OnVScroll(int nSBCode, short nPos, HWND hWnd) {
        long lOldTopIndex = m_lTopIndex;
        switch(nSBCode) {
        case SB_ENDSCROLL:
            break;
        case SB_PAGEUP:
            m_lTopIndex -= m_lVisibleItems;
            if(m_lTopIndex < 0) {
                m_lTopIndex = 0;
            }
            break;
        case SB_PAGEDOWN:
            m_lTopIndex += m_lVisibleItems;
            if(m_lTopIndex >= m_lCount - m_lVisibleItems) {
                m_lTopIndex = m_lCount-m_lVisibleItems;
            }
            break;
        case SB_LINEUP:
            m_lTopIndex--;
            if(m_lTopIndex < 0) {
                m_lTopIndex = 0;
            }
            break;
        case SB_LINEDOWN:
            m_lTopIndex++;
            if(m_lTopIndex >= m_lCount - m_lVisibleItems) {
                m_lTopIndex = m_lCount - m_lVisibleItems;
            }
            break;
        case SB_THUMBTRACK:
            m_lTopIndex = nPos;
            break;
        }
    
        m_vertBar.SetScrollPos(m_lTopIndex, true);
    
        if(lOldTopIndex != m_lTopIndex) {
            Invalidate();
        }
    }
    
    void CACListWnd::OnActivateApp(BOOL bActive, DWORD dwThreadID) {
        ShowWindow(false);
    }
    
    LRESULT CACListWnd::OnNcHitTest(CPoint point) {
        CRect rectClient;
        GetWindowRect(rectClient);
        rectClient.left = rectClient.right - GetSystemMetrics(SM_CYVSCROLL);
        rectClient.top = rectClient.bottom - GetSystemMetrics(SM_CXVSCROLL);
        if(rectClient.PtInRect(point)) {
            return HTBOTTOMRIGHT;
        } else {
            return HTCLIENT;
        }
    }
    
    void CACListWnd::OnLButtonDown(UINT nFlags, CPoint point) {
        int nSel = HitTest(point);
        if(nSel >= 0) {
            if(!EnsureVisible(nSel, true)) {
                Invalidate();
            }
            m_lSelItem = nSel;
            m_pEdit->SendMessage(ENAC_UPDATE, GetDlgCtrlID(), WM_KEYDOWN);
            DoPaintMessageLoop();
            Sleep(100);
            ShowWindow(false);
        } else {
            CRect rect;
            GetClientRect(rect);
            if(!rect.PtInRect(point)) {
                ShowWindow(false);
            }
        }
    }
    
    void CACListWnd::OnRButtonDown(UINT nFlags, CPoint point) {
        ShowWindow(false);
    }
    
    LRESULT CACListWnd::OnSetCursor(HWND hWnd, UINT nHitTest, UINT nMessage) {
        CRect rectClient;
        GetWindowRect(rectClient);
        ScreenToClient(&rectClient);
    
        rectClient.left = rectClient.right - GetSystemMetrics(SM_CYVSCROLL);
        rectClient.top = rectClient.bottom - GetSystemMetrics(SM_CXVSCROLL);
    
        CPoint ptCursor;
        GetCursorPos(&ptCursor);
        ScreenToClient(&ptCursor);
    
        SetCursor(LoadCursor(NULL, IDC_ARROW));
        return TRUE;
    }
    
    void CACListWnd::OnShowWindow(BOOL bShow, int nStatus) {
        if(bShow) {
            m_nIDTimer = SetTimer(IDTimerInstall, 200, NULL);
            m_pEdit->GetParent().GetWindowRect(m_parentRect);
        } else {
            if(m_nIDTimer) {
                KillTimer(IDTimerInstall);
            }
            m_nIDTimer = 0;
            m_lSelItem = -1;
            m_lTopIndex = 0;
        }
    }
    
    void CACListWnd::OnNcLButtonDown(UINT nHitTest, CPoint point) {
        if(OnNcHitTest(point) == HTBOTTOMRIGHT) {
            GetWindowRect(m_lastSize);
        }
    }
    
    void CACListWnd::OnMouseMove(UINT nFlags, CPoint point) {
        int nSel = HitTest(point);
        if(nSel >= 0) {
            Invalidate();
        }
    }
    
    void CACListWnd::OnTimer(UINT nIDEvent) {
        CRect parentRect;
        switch(nIDEvent) {
        case IDTimerInstall:
            m_pEdit->GetParent().GetWindowRect(parentRect);
            if(!parentRect.EqualRect(m_parentRect)) {
                ShowWindow(false);
            }
            break;
        default:
            break;
        }
    }
    
    void CACListWnd::OnGetMinMaxInfo(LPMINMAXINFO lpMMI) {
        if(this->m_hWnd) {
            long lMinY1 = 2 * GetSystemMetrics(SM_CYHSCROLL) + GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXHTHUMB);
            long lMinY2 = m_lCount * m_lItemHeight + 2 * GetSystemMetrics(SM_CYBORDER);
            if(m_lVisibleItems > m_lCount - 1 &&  lMinY2 < lMinY1) {
                lpMMI->ptMinTrackSize.y = lMinY2;
            } else {
                lpMMI->ptMinTrackSize.y = lMinY1;
            }
    
            lpMMI->ptMinTrackSize.x = 4 * GetSystemMetrics(SM_CXHSCROLL);
    
            if(m_pEdit != NULL) {
                RECT rect;
                m_pEdit->GetWindowRect(&rect);
                lpMMI->ptMinTrackSize.x = rect.right - rect.left;
            }
        }
    }
    
    int CACListWnd::HitTest(CPoint point) {
        CRect rcItem;
        CRect rcWnd;
    
        GetClientRect(rcWnd);
        long lWidth = rcWnd.Width() - ScrollBarWidth();
    
        for(int i=m_lTopIndex; i<m_lCount; i++) {
            long y = i - m_lTopIndex;
            rcItem.SetRect(2, y * m_lItemHeight, lWidth, (y + 1) * m_lItemHeight);
            if(PtInRect(&rcItem, point)) {
                return m_lSelItem = (y + m_lTopIndex);
            }
        }
        return -1;
    }
    
    void CACListWnd::SetScroller() {
        CRect rcWnd;
        CRect rcBar;
        GetClientRect(rcWnd);
        if(m_vertBar.m_hWnd) {
            rcBar = rcWnd;
            rcBar.top = -1;
            rcBar.left = rcWnd.Width() - GetSystemMetrics(SM_CYVSCROLL);
            rcBar.bottom -= GetSystemMetrics(SM_CYHSCROLL);
            m_vertBar.MoveWindow(rcBar);
            rcBar.top = rcWnd.bottom - 20;
            rcBar.bottom = rcWnd.bottom;
            m_vertBar.SetScrollPos(m_lTopIndex, true);    
        }
    }
    
    void CACListWnd::SetProp() {
        CRect rcWnd;
        CRect rcBar;
    
        if(!m_lCount) {
            return;
        }
    
        GetWindowRect(rcWnd);
        ScreenToClient(rcWnd);
    
        SCROLLINFO si;
        si.cbSize = sizeof(SCROLLINFO);
        si.fMask =  SIF_PAGE | SIF_RANGE;
        si.nMin = 0;
        si.nMax =  m_lCount - 1;
        m_lVisibleItems = si.nPage = rcWnd.Height() / m_lItemHeight;
        si.nTrackPos = 2;
        m_vertBar.SetScrollRange(0, m_lCount - 1);
        m_vertBar.SetScrollInfo(&si);
        if(m_lVisibleItems > m_lCount - 1) {
            m_vertBar.ShowWindow(false);
        } else {
            m_vertBar.ShowWindow(true);
        }
    
        if(m_lTopIndex + m_lVisibleItems > m_lCount) {
            m_lTopIndex = m_lCount - m_lVisibleItems;
            if(m_lTopIndex < 0) {
                m_lTopIndex = 0;
            }
            m_vertBar.SetScrollPos(m_lTopIndex, true);
        }
    }
    
    long CACListWnd::ScrollBarWidth() {
        if(m_vertBar.IsWindowVisible()) {
            return GetSystemMetrics(SM_CYVSCROLL);
        } else {
            return 0;
        }
    }
    
    void CACListWnd::InvalidateAndScroll() {
        m_vertBar.SetScrollPos(m_lTopIndex, true);
        Invalidate();
        DoPaintMessageLoop();
    }
    
    void CACListWnd::SortList(CSimpleArray<CString>& List) {
        int nCount = List.GetSize();    
        if (nCount > 1) {
            CSimpleArray<CString> List2 = List;
            LPCTSTR* ppSortArray = new LPCTSTR[nCount + 1];
            int i=0;
            for(; i<nCount; i++) {
                ppSortArray[i] = (LPCTSTR)List2[i];
            }        
            List.RemoveAll();
            qsort(ppSortArray, nCount, sizeof(LPCTSTR), CompareString);
    
            for(i=0; i<nCount; i++) {
                List.Add((LPCTSTR)ppSortArray[i]);
            }
            List2.RemoveAll();
            delete[] ppSortArray;
        }
    }
    
    int CACListWnd::CompareString(const void* p1, const void* p2) {
        return _stricmp(*(char**)p1, *(char**)p2);
    }
  • 相关阅读:
    百度mp3地址解密码
    VB 在EXE后附加信息
    截屏函数
    Base64和StrToByte
    The Android ION memory allocator, DMABUF is mentioned as well
    DDC EDID 介绍
    Memory management for graphic processors TTM的由来
    科普 写display driver的必看 How video card works [2D的四种主要操作]
    GEM vs TTM
    DMABUF 背景介绍文章 Sharing buffers between devices
  • 原文地址:https://www.cnblogs.com/mforestlaw/p/WTLACEdit.html
Copyright © 2020-2023  润新知