[BROWSEUI] Implement auto-completion (#3507)

Implement IAutoComplete to realize input auto completion. CORE-9281, CORE-1419

- The main features of this PR are Auto-Suggest and Auto-Append.
- Auto-Suggest shows a list near the textbox (an EDIT control) when the user has typed partial pathname into the textbox.
- Auto-Append appends complement text into the textbox to complete the pathname with selected status.
- The list of AutoSuggest is a top-level window whose window class is "Auto-Suggest Dropdown". We call it "the drop-down window".
- The drop-down window contains three controls: a listview, a scrollbar and a sizebox.
- The drop-down window watches the input into the textbox. If the textbox changed, then the window updates the list.
- The sizebox control enables the user to resize the drop-down window.
This commit is contained in:
Katayama Hirofumi MZ 2021-03-10 16:22:57 +09:00 committed by GitHub
parent 0c34c067c4
commit c19d9df259
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 2249 additions and 621 deletions

File diff suppressed because it is too large Load diff

View file

@ -19,65 +19,286 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
#ifndef _AUTOCOMPLETE_H_
#define _AUTOCOMPLETE_H_
#include "atltypes.h"
#include "rosctrls.h"
class CAutoComplete :
public CComCoClass<CAutoComplete, &CLSID_AutoComplete>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IAutoComplete2,
public IAutoCompleteDropDown,
public IEnumString
class CACEditCtrl;
class CACListView;
class CACScrollBar;
class CACSizeBox;
class CAutoComplete;
//////////////////////////////////////////////////////////////////////////////
// CACEditCtrl --- auto-completion textbox
class CACEditCtrl
: public CWindowImpl<CACEditCtrl, CWindow, CControlWinTraits>
{
private:
BOOL m_enabled;
BOOL m_initialized;
HWND m_hwndEdit;
HWND m_hwndListBox;
WNDPROC m_wpOrigEditProc;
WNDPROC m_wpOrigLBoxProc;
LPWSTR m_txtbackup; // HeapAlloc'ed
LPWSTR m_quickComplete; // HeapAlloc'ed
CComPtr<IEnumString> m_enumstr;
AUTOCOMPLETEOPTIONS m_options;
public:
CAutoComplete* m_pDropDown;
static LPCWSTR GetWndClassName() { return WC_EDITW; }
CAutoComplete();
~CAutoComplete();
CACEditCtrl();
VOID HookWordBreakProc(BOOL bHook);
static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// message map
BEGIN_MSG_MAP(CACEditCtrl)
MESSAGE_HANDLER(WM_CHAR, OnChar)
MESSAGE_HANDLER(WM_CLEAR, OnCutPasteClear)
MESSAGE_HANDLER(WM_CUT, OnCutPasteClear)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
MESSAGE_HANDLER(WM_PASTE, OnCutPasteClear)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_SETTEXT, OnSetText)
END_MSG_MAP()
void CreateListbox();
// IAutoComplete2
virtual HRESULT WINAPI Enable(BOOL fEnable);
virtual HRESULT WINAPI Init(HWND hwndEdit, IUnknown *punkACL, LPCOLESTR pwzsRegKeyPath, LPCOLESTR pwszQuickComplete);
virtual HRESULT WINAPI GetOptions(DWORD *pdwFlag);
virtual HRESULT WINAPI SetOptions(DWORD dwFlag);
// IAutoCompleteDropDown
virtual HRESULT STDMETHODCALLTYPE GetDropDownStatus(DWORD *pdwFlags, LPWSTR *ppwszString);
virtual HRESULT STDMETHODCALLTYPE ResetEnumerator();
// IEnumString methods
virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched);
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);
virtual HRESULT STDMETHODCALLTYPE Reset();
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumString **ppenum);
DECLARE_REGISTRY_RESOURCEID(IDR_AUTOCOMPLETE)
DECLARE_NOT_AGGREGATABLE(CAutoComplete)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CAutoComplete)
COM_INTERFACE_ENTRY_IID(IID_IAutoComplete, IAutoComplete)
COM_INTERFACE_ENTRY_IID(IID_IAutoComplete2, IAutoComplete2)
COM_INTERFACE_ENTRY_IID(IID_IAutoCompleteDropDown, IAutoCompleteDropDown)
COM_INTERFACE_ENTRY_IID(IID_IEnumString, IEnumString)
END_COM_MAP()
protected:
// protected variables
EDITWORDBREAKPROCW m_fnOldWordBreakProc;
// message handlers
LRESULT OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnCutPasteClear(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnSetText(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
};
#endif /* _AUTOCOMPLETE_H_ */
//////////////////////////////////////////////////////////////////////////////
// CACListView --- auto-completion list control
class CACListView : public CWindowImpl<CACListView, CListView>
{
public:
CAutoComplete* m_pDropDown;
INT m_cyItem;
static LPCWSTR GetWndClassName() { return WC_LISTVIEW; }
CACListView();
HWND Create(HWND hwndParent);
VOID SetFont(HFONT hFont);
INT GetVisibleCount();
CStringW GetItemText(INT iItem);
INT ItemFromPoint(INT x, INT y);
INT GetCurSel();
VOID SetCurSel(INT iItem);
VOID SelectHere(INT x, INT y);
protected:
// message map
BEGIN_MSG_MAP(CACListView)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnButtonUp)
MESSAGE_HANDLER(WM_MBUTTONDOWN, OnMRButtonDown)
MESSAGE_HANDLER(WM_MBUTTONUP, OnButtonUp)
MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
MESSAGE_HANDLER(WM_NCHITTEST, OnNCHitTest)
MESSAGE_HANDLER(WM_RBUTTONDOWN, OnMRButtonDown)
MESSAGE_HANDLER(WM_RBUTTONUP, OnButtonUp)
END_MSG_MAP()
// message handlers
LRESULT OnButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnMRButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnNCHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
};
//////////////////////////////////////////////////////////////////////////////
// CACScrollBar --- auto-completion scrollbar control
class CACScrollBar : public CWindowImpl<CACScrollBar>
{
public:
CAutoComplete* m_pDropDown;
static LPCWSTR GetWndClassName() { return WC_SCROLLBARW; }
CACScrollBar();
HWND Create(HWND hwndParent);
protected:
// message map
BEGIN_MSG_MAP(CACScrollBar)
END_MSG_MAP()
};
//////////////////////////////////////////////////////////////////////////////
// CACSizeBox --- auto-completion size-box control
class CACSizeBox : public CWindowImpl<CACSizeBox>
{
public:
CAutoComplete* m_pDropDown;
static LPCWSTR GetWndClassName() { return WC_SCROLLBARW; }
CACSizeBox();
HWND Create(HWND hwndParent);
VOID SetStatus(BOOL bDowner, BOOL bLongList);
protected:
// protected variables
BOOL m_bDowner;
BOOL m_bLongList;
// message map
BEGIN_MSG_MAP(CACSizeBox)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkGnd)
MESSAGE_HANDLER(WM_NCHITTEST, OnNCHitTest)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
END_MSG_MAP()
// message handlers
LRESULT OnEraseBkGnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnNCHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
};
//////////////////////////////////////////////////////////////////////////////
// CAutoComplete --- auto-completion drop-down window
#define WC_DROPDOWNW L"Auto-Suggest Dropdown" // the window class name
class CAutoComplete
: public CComCoClass<CAutoComplete, &CLSID_AutoComplete>
, public CComObjectRootEx<CComMultiThreadModelNoCS>
, public CWindowImpl<CAutoComplete>
, public IAutoComplete2
, public IAutoCompleteDropDown
, public IEnumString
{
public:
DECLARE_WND_CLASS_EX(WC_DROPDOWNW, CS_DROPSHADOW | CS_SAVEBITS, COLOR_3DFACE)
static LPCWSTR GetWndClassName() { return WC_DROPDOWNW; }
BOOL m_bInSetText; // this flag avoids subsequent action in WM_SETTEXT
BOOL m_bInSelectItem; // this flag avoids subsequent action in LVN_ITEMCHANGED
// public methods
CAutoComplete();
HWND CreateDropDown();
virtual ~CAutoComplete();
BOOL CanAutoSuggest();
BOOL CanAutoAppend();
BOOL UseTab();
BOOL IsComboBoxDropped();
INT GetItemCount();
CStringW GetItemText(INT iItem);
CStringW GetEditText();
VOID SetEditText(LPCWSTR pszText);
CStringW GetStemText();
VOID SetEditSel(INT ich0, INT ich1);
VOID ShowDropDown();
VOID HideDropDown();
VOID SelectItem(INT iItem);
VOID DoAutoAppend();
VOID DoBackWord();
VOID UpdateScrollBar();
LRESULT OnEditChar(WPARAM wParam, LPARAM lParam);
BOOL OnEditKeyDown(WPARAM wParam, LPARAM lParam);
VOID OnEditUpdate(BOOL bAppendOK);
VOID OnListSelChange();
BOOL OnListUpDown(UINT vk);
// IAutoComplete methods
STDMETHODIMP Enable(BOOL fEnable) override;
STDMETHODIMP Init(HWND hwndEdit, IUnknown *punkACL, LPCOLESTR pwszRegKeyPath,
LPCOLESTR pwszQuickComplete) override;
// IAutoComplete2 methods
STDMETHODIMP GetOptions(DWORD *pdwFlag) override;
STDMETHODIMP SetOptions(DWORD dwFlag) override;
// IAutoCompleteDropDown methods
STDMETHODIMP GetDropDownStatus(DWORD *pdwFlags, LPWSTR *ppwszString) override;
STDMETHODIMP ResetEnumerator() override;
// IEnumString methods
STDMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched) override;
STDMETHODIMP Skip(ULONG celt) override;
STDMETHODIMP Reset() override;
STDMETHODIMP Clone(IEnumString **ppOut) override;
protected:
// The following variables are POD (plain old data):
BOOL m_bDowner; // downer or upper? (below textbox or above textbox)
DWORD m_dwOptions; // for IAutoComplete2::SetOptions
DWORD m_bEnabled; // the auto-composition is enabled?
HWND m_hwndCombo; // the combobox if any
HFONT m_hFont; // the font
BOOL m_bResized; // re-sized by size-box?
RECT m_rcEdit; // in screen coordinates, to watch the position
// The following variables are non-POD:
CStringW m_strText; // internal text (used in selecting item and reverting text)
CStringW m_strStemText; // dirname + '\\'
CStringW m_strQuickComplete; // used for [Ctrl]+[Enter]
CACEditCtrl m_hwndEdit; // subclassed to watch
CACListView m_hwndList; // this listview is virtual
CACScrollBar m_hwndScrollBar; // scroll bar contol
CACSizeBox m_hwndSizeBox; // the size grip
CComPtr<IEnumString> m_pEnum; // used for enumeration
CComPtr<IACList> m_pACList; // for IACList::Expand to update the list
CSimpleArray<CStringW> m_innerList; // internal list
CSimpleArray<CStringW> m_outerList; // owner data for virtual listview
// protected methods
VOID UpdateDropDownState();
VOID CalcRects(BOOL bDowner, RECT& rcListView, RECT& rcScrollBar, RECT& rcSizeBox);
VOID LoadQuickComplete(LPCWSTR pwszRegKeyPath, LPCWSTR pwszQuickComplete);
CStringW GetQuickEdit(LPCWSTR pszText);
VOID RepositionDropDown();
INT ReLoadInnerList();
INT UpdateInnerList();
INT UpdateOuterList();
VOID UpdateCompletion(BOOL bAppendOK);
// message map
BEGIN_MSG_MAP(CAutoComplete)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
MESSAGE_HANDLER(WM_EXITSIZEMOVE, OnExitSizeMove)
MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo)
MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
MESSAGE_HANDLER(WM_NCACTIVATE, OnNCActivate)
MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNCLButtonDown)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
MESSAGE_HANDLER(WM_NCHITTEST, OnNCHitTest)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
END_MSG_MAP()
// message handlers
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnExitSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnNCActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnNCLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnNCHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnVScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
DECLARE_REGISTRY_RESOURCEID(IDR_AUTOCOMPLETE)
DECLARE_NOT_AGGREGATABLE(CAutoComplete)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CAutoComplete)
COM_INTERFACE_ENTRY_IID(IID_IAutoComplete, IAutoComplete)
COM_INTERFACE_ENTRY_IID(IID_IAutoComplete2, IAutoComplete2)
COM_INTERFACE_ENTRY_IID(IID_IAutoCompleteDropDown, IAutoCompleteDropDown)
COM_INTERFACE_ENTRY_IID(IID_IEnumString, IEnumString)
END_COM_MAP()
};