implement AutoComplete for wxMSW too

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49636 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2007-11-05 00:44:26 +00:00
parent 0c3d1aa7fd
commit 0847dca672
3 changed files with 197 additions and 2 deletions

View File

@ -335,8 +335,8 @@ the programmer should use \helpref{GetInsertionPoint}{wxtextctrlgetinsertionpoin
Call this function to enable auto-completion of the text typed in a single-line
text control using the given \arg{choices}.
Notice that currently this function is only implemented in wxGTK2 port and does
nothing under the other platforms.
Notice that currently this function is only implemented in wxGTK2 and wxMSW
ports and does nothing under the other platforms.
\newsince{2.9.0}

View File

@ -42,7 +42,12 @@ public:
{ DoSetSelection(from, to); }
virtual void GetSelection(long *from, long *to) const;
// auto-completion uses COM under Windows so they won't work without
// wxUSE_OLE as OleInitialize() is not called then
#if wxUSE_OLE
virtual bool AutoComplete(const wxArrayString& choices);
virtual bool AutoCompleteFileNames();
#endif // wxUSE_OLE
virtual bool IsEditable() const;
virtual void SetEditable(bool editable);

View File

@ -40,10 +40,119 @@
#define GetEditHwnd() ((HWND)(GetEditHWND()))
// ----------------------------------------------------------------------------
// wxIEnumString implements IEnumString interface
// ----------------------------------------------------------------------------
#if wxUSE_OLE
#include "wx/msw/ole/oleutils.h"
#include <shldisp.h>
DEFINE_GUID(CLSID_AutoComplete,
0x00bb2763, 0x6a77, 0x11d0, 0xa5, 0x35, 0x00, 0xc0, 0x4f, 0xd7, 0xd0, 0x62);
class wxIEnumString : public IEnumString
{
public:
wxIEnumString(const wxArrayString& strings) : m_strings(strings)
{
m_index = 0;
}
DECLARE_IUNKNOWN_METHODS;
virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt,
LPOLESTR *rgelt,
ULONG *pceltFetched)
{
if ( !rgelt || (!pceltFetched && celt > 1) )
return E_POINTER;
ULONG pceltFetchedDummy;
if ( !pceltFetched )
pceltFetched = &pceltFetchedDummy;
*pceltFetched = 0;
for ( const unsigned count = m_strings.size(); celt--; ++m_index )
{
if ( m_index == count )
return S_FALSE;
const wxWX2WCbuf wcbuf(m_strings[m_index].wc_str());
const size_t size = (wcslen(wcbuf) + 1)*sizeof(wchar_t);
void *olestr = CoTaskMemAlloc(size);
if ( !olestr )
return E_OUTOFMEMORY;
memcpy(olestr, wcbuf, size);
*rgelt++ = wx_static_cast(LPOLESTR, olestr);
++(*pceltFetched);
}
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
{
m_index += celt;
if ( m_index > m_strings.size() )
{
m_index = m_strings.size();
return S_FALSE;
}
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Reset()
{
m_index = 0;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumString **ppEnum)
{
if ( !ppEnum )
return E_POINTER;
wxIEnumString *e = new wxIEnumString(m_strings);
e->m_index = m_index;
e->AddRef();
*ppEnum = e;
return S_OK;
}
private:
const wxArrayString m_strings;
unsigned m_index;
DECLARE_NO_COPY_CLASS(wxIEnumString)
};
BEGIN_IID_TABLE(wxIEnumString)
ADD_IID(Unknown)
ADD_IID(EnumString)
END_IID_TABLE;
IMPLEMENT_IUNKNOWN_METHODS(wxIEnumString)
#endif // wxUSE_OLE
// ============================================================================
// wxTextEntry implementation
// ============================================================================
// ----------------------------------------------------------------------------
// operations on text
// ----------------------------------------------------------------------------
void wxTextEntry::WriteText(const wxString& text)
{
::SendMessage(GetEditHwnd(), EM_REPLACESEL, 0, (LPARAM)text.wx_str());
@ -60,6 +169,10 @@ void wxTextEntry::Remove(long from, long to)
WriteText(wxString());
}
// ----------------------------------------------------------------------------
// clipboard operations
// ----------------------------------------------------------------------------
void wxTextEntry::Copy()
{
::SendMessage(GetEditHwnd(), WM_COPY, 0, 0);
@ -75,6 +188,10 @@ void wxTextEntry::Paste()
::SendMessage(GetEditHwnd(), WM_PASTE, 0, 0);
}
// ----------------------------------------------------------------------------
// undo/redo
// ----------------------------------------------------------------------------
void wxTextEntry::Undo()
{
::SendMessage(GetEditHwnd(), EM_UNDO, 0, 0);
@ -98,6 +215,10 @@ bool wxTextEntry::CanRedo() const
return CanUndo();
}
// ----------------------------------------------------------------------------
// insertion point and selection
// ----------------------------------------------------------------------------
void wxTextEntry::SetInsertionPoint(long pos)
{
// be careful to call DoSetSelection() which is overridden in wxTextCtrl
@ -140,6 +261,12 @@ void wxTextEntry::GetSelection(long *from, long *to) const
*to = dwEnd;
}
// ----------------------------------------------------------------------------
// auto-completion
// ----------------------------------------------------------------------------
#if wxUSE_OLE
bool wxTextEntry::AutoCompleteFileNames()
{
typedef HRESULT (WINAPI *SHAutoComplete_t)(HWND, DWORD);
@ -173,6 +300,65 @@ bool wxTextEntry::AutoCompleteFileNames()
return true;
}
bool wxTextEntry::AutoComplete(const wxArrayString& choices)
{
// create an object exposing IAutoComplete interface (don't go for
// IAutoComplete2 immediately as, presumably, it might be not available on
// older systems as otherwise why do we have both -- although in practice I
// don't know when can this happen)
IAutoComplete *pAutoComplete = NULL;
HRESULT hr = CoCreateInstance
(
CLSID_AutoComplete,
NULL,
CLSCTX_INPROC_SERVER,
IID_IAutoComplete,
wx_reinterpret_cast(void **, &pAutoComplete)
);
if ( FAILED(hr) )
{
wxLogApiError(_T("CoCreateInstance(CLSID_AutoComplete)"), hr);
return false;
}
// associate it with our strings
wxIEnumString *pEnumString = new wxIEnumString(choices);
pEnumString->AddRef();
hr = pAutoComplete->Init(GetEditHwnd(), pEnumString, NULL, NULL);
pEnumString->Release();
if ( FAILED(hr) )
{
wxLogApiError(_T("IAutoComplete::Init"), hr);
return false;
}
// if IAutoComplete2 is available, set more user-friendly options
IAutoComplete2 *pAutoComplete2 = NULL;
hr = pAutoComplete->QueryInterface
(
IID_IAutoComplete2,
wx_reinterpret_cast(void **, &pAutoComplete2)
);
if ( SUCCEEDED(hr) )
{
pAutoComplete2->SetOptions(ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST);
pAutoComplete2->Release();
}
// the docs are unclear about when can we release it but it seems safe to
// do it immediately, presumably the edit control itself keeps a reference
// to the auto completer object
pAutoComplete->Release();
return true;
}
#endif // wxUSE_OLE
// ----------------------------------------------------------------------------
// editable state
// ----------------------------------------------------------------------------
bool wxTextEntry::IsEditable() const
{
return !(::GetWindowLong(GetEditHwnd(), GWL_STYLE) & ES_READONLY);
@ -183,6 +369,10 @@ void wxTextEntry::SetEditable(bool editable)
::SendMessage(GetEditHwnd(), EM_SETREADONLY, !editable, 0);
}
// ----------------------------------------------------------------------------
// max length
// ----------------------------------------------------------------------------
void wxTextEntry::SetMaxLength(unsigned long len)
{
if ( len >= 0xffff )