From: Włodzimierz Skiba Date: Mon, 23 Aug 2004 10:53:57 +0000 (+0000) Subject: Native SmartPhone wxChoice implementation. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/1550d5f80d130fea1c05302e890095b7ad27e085 Native SmartPhone wxChoice implementation. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28865 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 9b127643ab..1c00e590f4 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -1318,15 +1318,17 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/generic/dirdlgg.cpp src/generic/fdrepdlg.cpp src/generic/fontdlgg.cpp + src/msw/wince/choicece.cpp src/msw/wince/crt.cpp src/msw/wince/filedlgwce.cpp src/msw/wince/helpwce.cpp - src/msw/wince/tbarwce.cpp src/msw/wince/menuce.cpp + src/msw/wince/tbarwce.cpp wx/generic/fdrepdlg.h wx/generic/fontdlgg.h + wx/msw/wince/choicece.h wx/msw/wince/helpwce.h wx/msw/wince/libraries.h wx/msw/wince/missing.h diff --git a/docs/changes.txt b/docs/changes.txt index 8584dde749..8616b050af 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -273,6 +273,7 @@ wxUniv/X11: wxWinCE: +- added native SmartPhone wxChoice implementation using spinners - added automatized but customizable handling of native SmartPhone menus - fixed wxRadioBox and wxStaticBox diff --git a/include/wx/choice.h b/include/wx/choice.h index 3a95d2eff0..c11aa35550 100644 --- a/include/wx/choice.h +++ b/include/wx/choice.h @@ -67,6 +67,8 @@ private: #if defined(__WXUNIVERSAL__) #include "wx/univ/choice.h" +#elif defined(__SMARTPHONE__) + #include "wx/msw/wince/choicece.h" #elif defined(__WXMSW__) #include "wx/msw/choice.h" #elif defined(__WXMOTIF__) diff --git a/include/wx/msw/wince/choicece.h b/include/wx/msw/wince/choicece.h new file mode 100644 index 0000000000..bb893609f3 --- /dev/null +++ b/include/wx/msw/wince/choicece.h @@ -0,0 +1,141 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/wince/choicece.h +// Purpose: wxChoice implementation for Smartphones +// Author: Wlodzimierz ABX Skiba +// Modified by: +// Created: 29.07.2004 +// RCS-ID: $Id$ +// Copyright: (c) Wlodzimierz Skiba +// License: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_CHOICECE_H_BASE_ +#define _WX_CHOICECE_H_BASE_ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma interface "choicece.h" +#endif + +#include "wx/defs.h" + +#if wxUSE_CHOICE + +#include "wx/dynarray.h" + +class WXDLLEXPORT wxChoice; +WX_DEFINE_EXPORTED_ARRAY_PTR(wxChoice *, wxArrayChoiceSpins); + +// ---------------------------------------------------------------------------- +// Choice item +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxChoice : public wxChoiceBase +{ +public: + // ctors + wxChoice() { } + virtual ~wxChoice(); + + wxChoice(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, const wxString choices[] = NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxChoiceNameStr) + { + Create(parent, id, pos, size, n, choices, style, validator, name); + } + wxChoice(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxChoiceNameStr) + { + Create(parent, id, pos, size, choices, style, validator, name); + } + + bool Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, const wxString choices[] = NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxChoiceNameStr); + + bool Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxChoiceNameStr); + + // implement base class pure virtuals + virtual int DoAppend(const wxString& item); + virtual int DoInsert(const wxString& item, int pos); + virtual void Delete(int n); + virtual void Clear() ; + + virtual int GetCount() const; + virtual int GetSelection() const; + virtual void SetSelection(int n); + + virtual int FindString(const wxString& s) const; + virtual wxString GetString(int n) const; + virtual void SetString(int n, const wxString& s); + + // get the subclassed window proc of the buddy list of choices + WXFARPROC GetBuddyWndProc() const { return m_wndProcBuddy; } + +protected: + virtual void DoSetItemClientData( int n, void* clientData ); + virtual void* DoGetItemClientData( int n ) const; + virtual void DoSetItemClientObject( int n, wxClientData* clientData ); + virtual wxClientData* DoGetItemClientObject( int n ) const; + + // MSW implementation + virtual void DoGetPosition(int *x, int *y) const; + virtual void DoMoveWindow(int x, int y, int width, int height); + virtual wxSize DoGetBestSize() const; + virtual void DoGetSize(int *width, int *height) const; + + virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const; + + // create and initialize the control + bool CreateAndInit(wxWindow *parent, wxWindowID id, + const wxPoint& pos, + const wxSize& size, + int n, const wxString choices[], + long style, + const wxValidator& validator, + const wxString& name); + + // free all memory we have (used by Clear() and dtor) + void Free(); + + // the data for the "buddy" list + WXHWND m_hwndBuddy; + WXFARPROC m_wndProcBuddy; + + // all existing wxChoice - this allows to find the one corresponding to + // the given buddy window in GetSpinChoiceCtrl() + static wxArrayChoiceSpins ms_allChoiceSpins; + +private: + DECLARE_DYNAMIC_CLASS_NO_COPY(wxChoice) +}; + +#endif // wxUSE_CHOICE + +#endif // _WX_CHOICECE_H_BASE_ diff --git a/src/msw/choice.cpp b/src/msw/choice.cpp index 893d0ad9a2..7faa959c51 100644 --- a/src/msw/choice.cpp +++ b/src/msw/choice.cpp @@ -28,7 +28,7 @@ #pragma hdrstop #endif -#if wxUSE_CHOICE +#if wxUSE_CHOICE && !defined(__SMARTPHONE__) #ifndef WX_PRECOMP #include "wx/choice.h" @@ -601,4 +601,4 @@ WXHBRUSH wxChoice::OnCtlColor(WXHDC pDC, WXHWND WXUNUSED(pWnd), WXUINT WXUNUSED( return (WXHBRUSH)brush->GetResourceHandle(); } -#endif // wxUSE_CHOICE +#endif // wxUSE_CHOICE && !__SMARTPHONE__ diff --git a/src/msw/control.cpp b/src/msw/control.cpp index d00df75d1d..20ae5ca0dc 100644 --- a/src/msw/control.cpp +++ b/src/msw/control.cpp @@ -213,8 +213,14 @@ wxSize wxControl::DoGetBestSize() const wxSize wxControl::GetBestSpinerSize(const bool is_vertical) const { // take size according to layout - wxSize bestSize(GetSystemMetrics(is_vertical ? SM_CXVSCROLL : SM_CXHSCROLL), - GetSystemMetrics(is_vertical ? SM_CYVSCROLL : SM_CYHSCROLL)); + wxSize bestSize( +#ifdef __SMARTPHONE__ + 0,GetCharHeight() +#else !__SMARTPHONE__ + GetSystemMetrics(is_vertical ? SM_CXVSCROLL : SM_CXHSCROLL), + GetSystemMetrics(is_vertical ? SM_CYVSCROLL : SM_CYHSCROLL) +#endif __SMARTPHONE__/!__SMARTPHONE__ + ); // correct size as for undocumented MSW variants cases (WinCE and perhaps others) if (bestSize.x==0) diff --git a/src/msw/wince/choicece.cpp b/src/msw/wince/choicece.cpp new file mode 100644 index 0000000000..5f46de450b --- /dev/null +++ b/src/msw/wince/choicece.cpp @@ -0,0 +1,550 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/msw/wince/choicece.cpp +// Purpose: wxChoice implementation for Smartphones +// Author: Wlodzimierz ABX Skiba +// Modified by: +// Created: 29.07.2004 +// RCS-ID: $Id$ +// Copyright: (c) Wlodzimierz Skiba +// License: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) + #pragma implementation "choicece.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/choice.h" +#endif + +#include "wx/spinbutt.h" // for wxSpinnerBestSize + +#include +#include "wx/msw/missing.h" +#include "wx/msw/winundef.h" + +#if wxUSE_CHOICE && defined(__SMARTPHONE__) + +#if wxUSE_EXTENDED_RTTI +// TODO +#else +IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl) +#endif + +#define GetBuddyHwnd() (HWND)(m_hwndBuddy) + +#define IsVertical(wxStyle) ( (wxStyle & wxSP_HORIZONTAL) != wxSP_HORIZONTAL ) + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// the margin between the up-down control and its buddy (can be arbitrary, +// choose what you like - or may be decide during run-time depending on the +// font size?) +static const int MARGIN_BETWEEN = 0; + +// ============================================================================ +// implementation +// ============================================================================ + +wxArrayChoiceSpins wxChoice::ms_allChoiceSpins; + +// ---------------------------------------------------------------------------- +// wnd proc for the buddy text ctrl +// ---------------------------------------------------------------------------- + +LRESULT APIENTRY _EXPORT wxBuddyChoiceWndProc(HWND hwnd, + UINT message, + WPARAM wParam, + LPARAM lParam) +{ + wxChoice *spin = (wxChoice *)wxGetWindowUserData(hwnd); + + // forward some messages (the key and focus ones only so far) to + // the spin ctrl + switch ( message ) + { + case WM_SETFOCUS: + // if the focus comes from the spin control itself, don't set it + // back to it -- we don't want to go into an infinite loop + if ( (WXHWND)wParam == spin->GetHWND() ) + break; + //else: fall through + + case WM_KILLFOCUS: + case WM_CHAR: + case WM_DEADCHAR: + case WM_KEYUP: + case WM_KEYDOWN: + spin->MSWWindowProc(message, wParam, lParam); + + // The control may have been deleted at this point, so check. + if ( !::IsWindow(hwnd) || wxGetWindowUserData(hwnd) != spin ) + return 0; + break; + + case WM_GETDLGCODE: + // we want to get WXK_RETURN in order to generate the event for it + return DLGC_WANTCHARS; + } + + return ::CallWindowProc(CASTWNDPROC spin->GetBuddyWndProc(), + hwnd, message, wParam, lParam); +} + +// ---------------------------------------------------------------------------- +// creation +// ---------------------------------------------------------------------------- + +bool wxChoice::Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + int n, const wxString choices[], + long style, + const wxValidator& validator, + const wxString& name) +{ + return CreateAndInit(parent, id, pos, size, n, choices, style, + validator, name); +} + +bool wxChoice::CreateAndInit(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + int n, const wxString choices[], + long style, + const wxValidator& validator, + const wxString& name) +{ + if ( !(style & wxSP_VERTICAL) ) + style |= wxSP_HORIZONTAL; + + if ( (style & wxBORDER_MASK) == wxBORDER_DEFAULT ) + style |= wxBORDER_SIMPLE; + + style |= wxSP_ARROW_KEYS; + + SetWindowStyle(style); + + WXDWORD exStyle = 0; + WXDWORD msStyle = MSWGetStyle(GetWindowStyle(), & exStyle) ; + + wxSize sizeText(size), sizeBtn(size); + sizeBtn.x = GetBestSpinerSize(IsVertical(style)).x; + + sizeBtn.x; + + if ( sizeText.x == wxDefaultCoord ) + { + // DEFAULT_ITEM_WIDTH is the default width for the text control + sizeText.x = DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN + sizeBtn.x; + } + + sizeText.x -= sizeBtn.x + MARGIN_BETWEEN; + if ( sizeText.x <= 0 ) + { + wxLogDebug(_T("not enough space for wxSpinCtrl!")); + } + + wxPoint posBtn(pos); + posBtn.x += sizeText.x + MARGIN_BETWEEN; + + // we must create the list control before the spin button for the purpose + // of the dialog navigation: if there is a static text just before the spin + // control, activating it by Alt-letter should give focus to the text + // control, not the spin and the dialog navigation code will give focus to + // the next control (at Windows level), not the one after it + + // create the text window + + m_hwndBuddy = (WXHWND)::CreateWindowEx + ( + exStyle, // sunken border + _T("LISTBOX"), // window class + NULL, // no window title + msStyle, // style (will be shown later) + pos.x, pos.y, // position + 0, 0, // size (will be set later) + GetHwndOf(parent), // parent + (HMENU)-1, // control id + wxGetInstance(), // app instance + NULL // unused client data + ); + + if ( !m_hwndBuddy ) + { + wxLogLastError(wxT("CreateWindow(buddy text window)")); + + return false; + } + + // initialize wxControl + if ( !CreateControl(parent, id, posBtn, sizeBtn, style, validator, name) ) + return false; + + // now create the real HWND + WXDWORD spiner_style = WS_VISIBLE | + UDS_ALIGNRIGHT | + UDS_ARROWKEYS | + UDS_SETBUDDYINT | + UDS_EXPANDABLE; + + if ( !IsVertical(style) ) + spiner_style |= UDS_HORZ; + + if ( style & wxSP_WRAP ) + spiner_style |= UDS_WRAP; + + if ( !MSWCreateControl(UPDOWN_CLASS, spiner_style, posBtn, sizeBtn, _T(""), 0) ) + return false; + + // subclass the text ctrl to be able to intercept some events + wxSetWindowUserData(GetBuddyHwnd(), this); + m_wndProcBuddy = (WXFARPROC)wxSetWindowProc(GetBuddyHwnd(), + wxBuddyChoiceWndProc); + + // set up fonts and colours (This is nomally done in MSWCreateControl) + InheritAttributes(); + if (!m_hasFont) + SetFont(GetDefaultAttributes().font); + + // set the size of the text window - can do it only now, because we + // couldn't call DoGetBestSize() before as font wasn't set + if ( sizeText.y <= 0 ) + { + int cx, cy; + wxGetCharSize(GetHWND(), &cx, &cy, GetFont()); + + sizeText.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); + } + + SetBestSize(size); + + (void)::ShowWindow(GetBuddyHwnd(), SW_SHOW); + + // associate the list window with the spin button + (void)::SendMessage(GetHwnd(), UDM_SETBUDDY, (WPARAM)GetBuddyHwnd(), 0); + + // do it after finishing with m_hwndBuddy creation to avoid generating + // initial wxEVT_COMMAND_TEXT_UPDATED message + ms_allChoiceSpins.Add(this); + + // initialize the controls contents + for ( int i = 0; i < n; i++ ) + { + Append(choices[i]); + } + + return true; +} + +bool wxChoice::Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style, + const wxValidator& validator, + const wxString& name) +{ + wxCArrayString chs(choices); + return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(), + style, validator, name); +} + +WXDWORD wxChoice::MSWGetStyle(long style, WXDWORD *exstyle) const +{ + // we never have an external border + WXDWORD msStyle = wxControl::MSWGetStyle + ( + (style & ~wxBORDER_MASK) | wxBORDER_NONE, exstyle + ); + + msStyle |= WS_VISIBLE; + + // wxChoice-specific styles + msStyle |= LBS_NOINTEGRALHEIGHT; + if ( style & wxCB_SORT ) + msStyle |= LBS_SORT; + + return msStyle; +} + +wxChoice::~wxChoice() +{ + Free(); +} + +// ---------------------------------------------------------------------------- +// adding/deleting items to/from the list +// ---------------------------------------------------------------------------- + +int wxChoice::DoAppend(const wxString& item) +{ + int n = (int)SendMessage(GetBuddyHwnd(), LB_ADDSTRING, 0, (LPARAM)item.c_str()); + + if ( n == LB_ERR ) + { + wxLogLastError(wxT("SendMessage(LB_ADDSTRING)")); + } + + return n; +} + +int wxChoice::DoInsert(const wxString& item, int pos) +{ + wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into choice")); + wxCHECK_MSG((pos>=0) && (pos<=GetCount()), -1, wxT("invalid index")); + + int n = (int)SendMessage(GetBuddyHwnd(), LB_INSERTSTRING, pos, (LPARAM)item.c_str()); + if ( n == LB_ERR ) + { + wxLogLastError(wxT("SendMessage(LB_INSERTSTRING)")); + } + + return n; +} + +void wxChoice::Delete(int n) +{ + wxCHECK_RET( n < GetCount(), wxT("invalid item index in wxChoice::Delete") ); + + if ( HasClientObjectData() ) + { + delete GetClientObject(n); + } + + SendMessage(GetBuddyHwnd(), LB_DELETESTRING, n, 0); +} + +void wxChoice::Clear() +{ + Free(); + + SendMessage(GetBuddyHwnd(), LB_RESETCONTENT, 0, 0); +} + +void wxChoice::Free() +{ + if ( HasClientObjectData() ) + { + size_t count = GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + delete GetClientObject(n); + } + } +} + +// ---------------------------------------------------------------------------- +// selection +// ---------------------------------------------------------------------------- + +int wxChoice::GetSelection() const +{ + return (int)SendMessage(GetBuddyHwnd(), LB_GETCURSEL, 0, 0); +} + +void wxChoice::SetSelection(int n) +{ + SendMessage(GetBuddyHwnd(), LB_SETCURSEL, n, 0); +} + +// ---------------------------------------------------------------------------- +// string list functions +// ---------------------------------------------------------------------------- + +int wxChoice::GetCount() const +{ + return (int)SendMessage(GetBuddyHwnd(), LB_GETCOUNT, 0, 0); +} + +int wxChoice::FindString(const wxString& s) const +{ + int pos = (int)SendMessage(GetBuddyHwnd(), LB_FINDSTRINGEXACT, + (WPARAM)-1, (LPARAM)s.c_str()); + + return pos == LB_ERR ? wxNOT_FOUND : pos; +} + +void wxChoice::SetString(int n, const wxString& s) +{ + wxCHECK_RET( n >= 0 && n < GetCount(), + wxT("invalid item index in wxChoice::SetString") ); + + // we have to delete and add back the string as there is no way to change a + // string in place + + // we need to preserve the client data + void *data; + if ( m_clientDataItemsType != wxClientData_None ) + { + data = DoGetItemClientData(n); + } + else // no client data + { + data = NULL; + } + + ::SendMessage(GetBuddyHwnd(), LB_DELETESTRING, n, 0); + ::SendMessage(GetBuddyHwnd(), LB_INSERTSTRING, n, (LPARAM)s.c_str() ); + + if ( data ) + { + DoSetItemClientData(n, data); + } + //else: it's already NULL by default +} + +wxString wxChoice::GetString(int n) const +{ + int len = (int)::SendMessage(GetBuddyHwnd(), LB_GETTEXTLEN, n, 0); + + wxString str; + if ( len != LB_ERR && len > 0 ) + { + if ( ::SendMessage + ( + GetBuddyHwnd(), + LB_GETTEXT, + n, + (LPARAM)(wxChar *)wxStringBuffer(str, len) + ) == LB_ERR ) + { + wxLogLastError(wxT("SendMessage(LB_GETLBTEXT)")); + } + } + + return str; +} + +// ---------------------------------------------------------------------------- +// client data +// ---------------------------------------------------------------------------- + +void wxChoice::DoSetItemClientData( int n, void* clientData ) +{ + if ( ::SendMessage(GetHwnd(), LB_SETITEMDATA, + n, (LPARAM)clientData) == LB_ERR ) + { + wxLogLastError(wxT("LB_SETITEMDATA")); + } +} + +void* wxChoice::DoGetItemClientData( int n ) const +{ + LPARAM rc = SendMessage(GetHwnd(), LB_GETITEMDATA, n, 0); + if ( rc == LB_ERR ) + { + wxLogLastError(wxT("LB_GETITEMDATA")); + + // unfortunately, there is no way to return an error code to the user + rc = (LPARAM) NULL; + } + + return (void *)rc; +} + +void wxChoice::DoSetItemClientObject( int n, wxClientData* clientData ) +{ + DoSetItemClientData(n, clientData); +} + +wxClientData* wxChoice::DoGetItemClientObject( int n ) const +{ + return (wxClientData *)DoGetItemClientData(n); +} + +// ---------------------------------------------------------------------------- +// size calculations +// ---------------------------------------------------------------------------- + +wxSize wxChoice::DoGetBestSize() const +{ + wxSize sizeBtn = GetBestSpinerSize(IsVertical(GetWindowStyle())); + sizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN; + + int y; + wxGetCharSize(GetHWND(), NULL, &y, GetFont()); + y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(y); + + // JACS: we should always use the height calculated + // from above, because otherwise we'll get a spin control + // that's too big. So never use the height calculated + // from wxSpinButton::DoGetBestSize(). + + // if ( sizeBtn.y < y ) + { + // make the text tall enough + sizeBtn.y = y; + } + + return sizeBtn; +} + +void wxChoice::DoMoveWindow(int x, int y, int width, int height) +{ + int widthBtn = GetBestSpinerSize(IsVertical(GetWindowStyle())).x; + int widthText = width - widthBtn - MARGIN_BETWEEN; + if ( widthText <= 0 ) + { + wxLogDebug(_T("not enough space for wxSpinCtrl!")); + } + + if ( !::MoveWindow(GetBuddyHwnd(), x, y, widthText, height, TRUE) ) + { + wxLogLastError(wxT("MoveWindow(buddy)")); + } + + x += widthText + MARGIN_BETWEEN; + if ( !::MoveWindow(GetHwnd(), x, y, widthBtn, height, TRUE) ) + { + wxLogLastError(wxT("MoveWindow")); + } +} + +// get total size of the control +void wxChoice::DoGetSize(int *x, int *y) const +{ + RECT spinrect, textrect, ctrlrect; + GetWindowRect(GetHwnd(), &spinrect); + GetWindowRect(GetBuddyHwnd(), &textrect); + UnionRect(&ctrlrect, &textrect, &spinrect); + + if ( x ) + *x = ctrlrect.right - ctrlrect.left; + if ( y ) + *y = ctrlrect.bottom - ctrlrect.top; +} + +void wxChoice::DoGetPosition(int *x, int *y) const +{ + // hack: pretend that our HWND is the text control just for a moment + WXHWND hWnd = GetHWND(); + wxConstCast(this, wxChoice)->m_hWnd = m_hwndBuddy; + + wxChoiceBase::DoGetPosition(x, y); + + wxConstCast(this, wxChoice)->m_hWnd = hWnd; +} + +#endif // wxUSE_CHOICE && __SMARTPHONE__