X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3eeefdf9bdc41618a14a8fff96a016004b030e95..ea412ac4eb9f19e3c28dfa32aa9099a81ac7c74c:/src/msw/textentry.cpp diff --git a/src/msw/textentry.cpp b/src/msw/textentry.cpp index 65fbc3031f..298e07b8eb 100644 --- a/src/msw/textentry.cpp +++ b/src/msw/textentry.cpp @@ -35,18 +35,27 @@ #include "wx/msw/private.h" +#if wxUSE_UXTHEME + #include "wx/msw/uxtheme.h" +#endif + #define GetEditHwnd() ((HWND)(GetEditHWND())) // ---------------------------------------------------------------------------- // wxIEnumString implements IEnumString interface // ---------------------------------------------------------------------------- -#if wxUSE_OLE +// standard VC6 SDK (WINVER == 0x0400) does not know about IAutoComplete +#if wxUSE_OLE && (WINVER >= 0x0500) + #define HAS_AUTOCOMPLETE +#endif + +#ifdef HAS_AUTOCOMPLETE #include "wx/msw/ole/oleutils.h" #include -#if defined(__MINGW32__) +#if defined(__MINGW32__) || defined (__WATCOMC__) // needed for IID_IAutoComplete, IID_IAutoComplete2 and ACO_AUTOSUGGEST #include #endif @@ -70,6 +79,12 @@ public: m_index = 0; } + void ChangeStrings(const wxArrayString& strings) + { + m_strings = strings; + Reset(); + } + DECLARE_IUNKNOWN_METHODS; virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, @@ -90,7 +105,7 @@ public: if ( m_index == count ) return S_FALSE; - const wxWX2WCbuf wcbuf(m_strings[m_index].wc_str()); + 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 ) @@ -98,7 +113,7 @@ public: memcpy(olestr, wcbuf, size); - *rgelt++ = wx_static_cast(LPOLESTR, olestr); + *rgelt++ = static_cast(olestr); ++(*pceltFetched); } @@ -147,10 +162,10 @@ private: virtual ~wxIEnumString() { } - const wxArrayString m_strings; + wxArrayString m_strings; unsigned m_index; - DECLARE_NO_COPY_CLASS(wxIEnumString) + wxDECLARE_NO_COPY_CLASS(wxIEnumString); }; BEGIN_IID_TABLE(wxIEnumString) @@ -160,7 +175,7 @@ END_IID_TABLE; IMPLEMENT_IUNKNOWN_METHODS(wxIEnumString) -#endif // wxUSE_OLE +#endif // HAS_AUTOCOMPLETE // ============================================================================ // wxTextEntry implementation @@ -175,7 +190,7 @@ void wxTextEntry::WriteText(const wxString& text) ::SendMessage(GetEditHwnd(), EM_REPLACESEL, 0, (LPARAM)text.wx_str()); } -wxString wxTextEntry::GetValue() const +wxString wxTextEntry::DoGetValue() const { return wxGetWindowText(GetEditHWND()); } @@ -238,6 +253,11 @@ bool wxTextEntry::CanRedo() const void wxTextEntry::SetInsertionPoint(long pos) { + // calling DoSetSelection(-1, -1) would select everything which is not what + // we want here + if ( pos == -1 ) + pos = GetLastPosition(); + // be careful to call DoSetSelection() which is overridden in wxTextCtrl // and not just SetSelection() here DoSetSelection(pos, pos); @@ -283,17 +303,15 @@ void wxTextEntry::GetSelection(long *from, long *to) const // ---------------------------------------------------------------------------- #if wxUSE_OLE - bool wxTextEntry::AutoCompleteFileNames() { +#ifdef HAS_AUTOCOMPLETE typedef HRESULT (WINAPI *SHAutoComplete_t)(HWND, DWORD); static SHAutoComplete_t s_pfnSHAutoComplete = (SHAutoComplete_t)-1; static wxDynamicLibrary s_dllShlwapi; if ( s_pfnSHAutoComplete == (SHAutoComplete_t)-1 ) { - wxLogNull noLog; - - if ( !s_dllShlwapi.Load(_T("shlwapi.dll"), wxDL_VERBATIM) ) + if ( !s_dllShlwapi.Load(wxT("shlwapi.dll"), wxDL_VERBATIM | wxDL_QUIET) ) { s_pfnSHAutoComplete = NULL; } @@ -309,16 +327,27 @@ bool wxTextEntry::AutoCompleteFileNames() HRESULT hr = (*s_pfnSHAutoComplete)(GetEditHwnd(), SHACF_FILESYS_ONLY); if ( FAILED(hr) ) { - wxLogApiError(_T("SHAutoComplete()"), hr); + wxLogApiError(wxT("SHAutoComplete()"), hr); return false; } - return true; +#else // !HAS_AUTOCOMPLETE + return false; +#endif // HAS_AUTOCOMPLETE/!HAS_AUTOCOMPLETE } bool wxTextEntry::AutoComplete(const wxArrayString& choices) { +#ifdef HAS_AUTOCOMPLETE + // if we had an old enumerator we must reuse it as IAutoComplete doesn't + // free it if we call Init() again (see #10968) -- and it's also simpler + if ( m_enumStrings ) + { + m_enumStrings->ChangeStrings(choices); + return true; + } + // 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 @@ -330,22 +359,22 @@ bool wxTextEntry::AutoComplete(const wxArrayString& choices) NULL, CLSCTX_INPROC_SERVER, IID_IAutoComplete, - wx_reinterpret_cast(void **, &pAutoComplete) + reinterpret_cast(&pAutoComplete) ); if ( FAILED(hr) ) { - wxLogApiError(_T("CoCreateInstance(CLSID_AutoComplete)"), hr); + wxLogApiError(wxT("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(); + m_enumStrings = new wxIEnumString(choices); + m_enumStrings->AddRef(); + hr = pAutoComplete->Init(GetEditHwnd(), m_enumStrings, NULL, NULL); + m_enumStrings->Release(); if ( FAILED(hr) ) { - wxLogApiError(_T("IAutoComplete::Init"), hr); + wxLogApiError(wxT("IAutoComplete::Init"), hr); return false; } @@ -354,7 +383,7 @@ bool wxTextEntry::AutoComplete(const wxArrayString& choices) hr = pAutoComplete->QueryInterface ( IID_IAutoComplete2, - wx_reinterpret_cast(void **, &pAutoComplete2) + reinterpret_cast(&pAutoComplete2) ); if ( SUCCEEDED(hr) ) { @@ -366,10 +395,13 @@ bool wxTextEntry::AutoComplete(const wxArrayString& choices) // do it immediately, presumably the edit control itself keeps a reference // to the auto completer object pAutoComplete->Release(); - return true; -} +#else // !HAS_AUTOCOMPLETE + wxUnusedVar(choices); + return false; +#endif // HAS_AUTOCOMPLETE/!HAS_AUTOCOMPLETE +} #endif // wxUSE_OLE // ---------------------------------------------------------------------------- @@ -402,4 +434,88 @@ void wxTextEntry::SetMaxLength(unsigned long len) ::SendMessage(GetEditHwnd(), EM_LIMITTEXT, len, 0); } +// ---------------------------------------------------------------------------- +// hints +// ---------------------------------------------------------------------------- + +#if wxUSE_UXTHEME + +#ifndef EM_SETCUEBANNER + #define EM_SETCUEBANNER 0x1501 + #define EM_GETCUEBANNER 0x1502 +#endif + +bool wxTextEntry::SetHint(const wxString& hint) +{ + if ( wxUxThemeEngine::GetIfActive() ) + { + // notice that this message always works with Unicode strings + // + // we always use TRUE for wParam to show the hint even when the window + // has focus, otherwise there would be no way to show the hint for the + // initially focused window + if ( ::SendMessage(GetEditHwnd(), EM_SETCUEBANNER, + TRUE, (LPARAM)(const wchar_t *)hint.wc_str()) ) + return true; + } + + return wxTextEntryBase::SetHint(hint); +} + +wxString wxTextEntry::GetHint() const +{ + if ( wxUxThemeEngine::GetIfActive() ) + { + wchar_t buf[256]; + if ( ::SendMessage(GetEditHwnd(), EM_GETCUEBANNER, + (WPARAM)buf, WXSIZEOF(buf)) ) + return wxString(buf); + } + + return wxTextEntryBase::GetHint(); +} + + +#endif // wxUSE_UXTHEME + +// ---------------------------------------------------------------------------- +// margins support +// ---------------------------------------------------------------------------- + +bool wxTextEntry::DoSetMargins(const wxPoint& margins) +{ +#if !defined(__WXWINCE__) + bool res = true; + + if ( margins.x != -1 ) + { + // left margin + ::SendMessage(GetEditHwnd(), EM_SETMARGINS, + EC_LEFTMARGIN, MAKELONG(margins.x, 0)); + } + + if ( margins.y != -1 ) + { + res = false; + } + + return res; +#else + return false; +#endif +} + +wxPoint wxTextEntry::DoGetMargins() const +{ +#if !defined(__WXWINCE__) + LRESULT lResult = ::SendMessage(GetEditHwnd(), EM_GETMARGINS, + 0, 0); + int left = LOWORD(lResult); + int top = -1; + return wxPoint(left, top); +#else + return wxPoint(-1, -1); +#endif +} + #endif // wxUSE_TEXTCTRL || wxUSE_COMBOBOX