X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/540b6b097f0a8056189b3f9ab5aab5c99834b9c7..d30ee785c216be96e1fdf0488d5891e93340700f:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index df95abf3a7..d0dca74f79 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -17,7 +17,7 @@ // headers // --------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "window.h" #endif @@ -29,8 +29,7 @@ #endif #ifndef WX_PRECOMP - #include - #include "wx/msw/winundef.h" + #include "wx/msw/wrapwin.h" #include "wx/window.h" #include "wx/accel.h" #include "wx/setup.h" @@ -50,10 +49,12 @@ #include "wx/statbox.h" #endif -#if wxUSE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__) #include "wx/ownerdrw.h" #endif +#include "wx/module.h" + #if wxUSE_DRAG_AND_DROP #include "wx/dnd.h" #endif @@ -92,10 +93,11 @@ #include "wx/textctrl.h" #include "wx/notebook.h" +#include "wx/listctrl.h" #include -#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) #include #include #endif @@ -104,63 +106,24 @@ #include #endif -#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) #ifdef __WIN95__ #include #endif -#elif !defined(__WXMICROWIN__) // broken compiler +#elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler #include "wx/msw/gnuwin32/extra.h" #endif -#if defined(__GNUG__) #include "wx/msw/missing.h" -#endif - -// ---------------------------------------------------------------------------- -// standard constants not available with all compilers/headers -// ---------------------------------------------------------------------------- - -// This didn't appear in mingw until 2.95.2 -#ifndef SIF_TRACKPOS -#define SIF_TRACKPOS 16 -#endif - -#if wxUSE_MOUSEWHEEL - #ifndef WM_MOUSEWHEEL - #define WM_MOUSEWHEEL 0x020A - #endif - #ifndef WHEEL_DELTA - #define WHEEL_DELTA 120 - #endif - #ifndef SPI_GETWHEELSCROLLLINES - #define SPI_GETWHEELSCROLLLINES 104 - #endif -#endif // wxUSE_MOUSEWHEEL - -#ifndef VK_OEM_1 - #define VK_OEM_1 0xBA - #define VK_OEM_2 0xBF - #define VK_OEM_3 0xC0 - #define VK_OEM_4 0xDB - #define VK_OEM_5 0xDC - #define VK_OEM_6 0xDD - #define VK_OEM_7 0xDE -#endif -#ifndef VK_OEM_COMMA - #define VK_OEM_PLUS 0xBB - #define VK_OEM_COMMA 0xBC - #define VK_OEM_MINUS 0xBD - #define VK_OEM_PERIOD 0xBE +#if defined(__WXWINCE__) +#include "wx/msw/wince/missing.h" #endif // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- -// the last Windows message we got (FIXME-MT) -extern MSG s_currentMsg; - #if wxUSE_MENUS_NATIVE wxMenu *wxCurrentPopupMenu = NULL; #endif // wxUSE_MENUS_NATIVE @@ -169,7 +132,7 @@ extern const wxChar *wxCanvasClassName; // true if we had already created the std colour map, used by // wxGetStdColourMap() and wxWindow::OnSysColourChanged() (FIXME-MT) -static bool gs_hasStdCmap = FALSE; +static bool gs_hasStdCmap = false; // --------------------------------------------------------------------------- // private functions @@ -217,6 +180,40 @@ static inline void wxBringWindowToTop(HWND hwnd) } } +#ifndef __WXWINCE__ + +// ensure that all our parent windows have WS_EX_CONTROLPARENT style +static void EnsureParentHasControlParentStyle(wxWindow *parent) +{ + /* + If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our + parent as well as otherwise several Win32 functions using + GetNextDlgTabItem() to iterate over all controls such as + IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, + all of them iterate over all the controls starting from the currently + focused one and stop iterating when they get back to the focus but + unless all parents have WS_EX_CONTROLPARENT bit set, they would never + get back to the initial (focused) window: as we do have this style, + GetNextDlgTabItem() will leave this window and continue in its parent, + but if the parent doesn't have it, it wouldn't recurse inside it later + on and so wouldn't have a chance of getting back to this window neither. + */ + while ( parent && !parent->IsTopLevel() ) + { + LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE); + if ( !(exStyle & WS_EX_CONTROLPARENT) ) + { + // force the parent to have this style + ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE, + exStyle | WS_EX_CONTROLPARENT); + } + + parent = parent->GetParent(); + } +} + +#endif // !__WXWINCE__ + // --------------------------------------------------------------------------- // event tables // --------------------------------------------------------------------------- @@ -226,7 +223,113 @@ static inline void wxBringWindowToTop(HWND hwnd) #ifdef __WXUNIVERSAL__ IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW, wxWindowBase) #else // __WXMSW__ +#if wxUSE_EXTENDED_RTTI + +// windows that are created from a parent window during its Create method, eg. spin controls in a calendar controls +// must never been streamed out separately otherwise chaos occurs. Right now easiest is to test for negative ids, as +// windows with negative ids never can be recreated anyway + +bool wxWindowStreamingCallback( const wxObject *object, wxWriter * , wxPersister * , wxxVariantArray & ) +{ + const wxWindow * win = dynamic_cast(object) ; + if ( win && win->GetId() < 0 ) + return false ; + return true ; +} + +IMPLEMENT_DYNAMIC_CLASS_XTI_CALLBACK(wxWindow, wxWindowBase,"wx/window.h", wxWindowStreamingCallback) + +// make wxWindowList known before the property is used + +wxCOLLECTION_TYPE_INFO( wxWindow* , wxWindowList ) ; + +template<> void wxCollectionToVariantArray( wxWindowList const &theList, wxxVariantArray &value) +{ + wxListCollectionToVariantArray( theList , value ) ; +} + +WX_DEFINE_FLAGS( wxWindowStyle ) + +wxBEGIN_FLAGS( wxWindowStyle ) + // new style border flags, we put them first to + // use them for streaming out + + wxFLAGS_MEMBER(wxBORDER_SIMPLE) + wxFLAGS_MEMBER(wxBORDER_SUNKEN) + wxFLAGS_MEMBER(wxBORDER_DOUBLE) + wxFLAGS_MEMBER(wxBORDER_RAISED) + wxFLAGS_MEMBER(wxBORDER_STATIC) + wxFLAGS_MEMBER(wxBORDER_NONE) + + // old style border flags + wxFLAGS_MEMBER(wxSIMPLE_BORDER) + wxFLAGS_MEMBER(wxSUNKEN_BORDER) + wxFLAGS_MEMBER(wxDOUBLE_BORDER) + wxFLAGS_MEMBER(wxRAISED_BORDER) + wxFLAGS_MEMBER(wxSTATIC_BORDER) + wxFLAGS_MEMBER(wxBORDER) + + // standard window styles + wxFLAGS_MEMBER(wxTAB_TRAVERSAL) + wxFLAGS_MEMBER(wxCLIP_CHILDREN) + wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW) + wxFLAGS_MEMBER(wxWANTS_CHARS) + wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE) + wxFLAGS_MEMBER(wxALWAYS_SHOW_SB ) + wxFLAGS_MEMBER(wxVSCROLL) + wxFLAGS_MEMBER(wxHSCROLL) + +wxEND_FLAGS( wxWindowStyle ) + +wxBEGIN_PROPERTIES_TABLE(wxWindow) + wxEVENT_PROPERTY( Close , wxEVT_CLOSE_WINDOW , wxCloseEvent) + wxEVENT_PROPERTY( Create , wxEVT_CREATE , wxWindowCreateEvent ) + wxEVENT_PROPERTY( Destroy , wxEVT_DESTROY , wxWindowDestroyEvent ) + // Always constructor Properties first + + wxREADONLY_PROPERTY( Parent,wxWindow*, GetParent, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) + wxPROPERTY( Id,wxWindowID, SetId, GetId, -1, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) + wxPROPERTY( Position,wxPoint, SetPosition , GetPosition, wxPoint(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos + wxPROPERTY( Size,wxSize, SetSize, GetSize, wxSize(-1,-1) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size + wxPROPERTY( WindowStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style + + // Then all relations of the object graph + + wxREADONLY_PROPERTY_COLLECTION( Children , wxWindowList , wxWindowBase* , GetWindowChildren , wxPROP_OBJECT_GRAPH /*flags*/ , wxT("Helpstring") , wxT("group")) + + // and finally all other properties + + wxPROPERTY( ExtraStyle , long , SetExtraStyle , GetExtraStyle , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle + wxPROPERTY( BackgroundColour , wxColour , SetBackgroundColour , GetBackgroundColour , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg + wxPROPERTY( ForegroundColour , wxColour , SetForegroundColour , GetForegroundColour , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // fg + wxPROPERTY( Enabled , bool , Enable , IsEnabled , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) + wxPROPERTY( Shown , bool , Show , IsShown , wxxVariant((bool)true) , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) +#if 0 + // possible property candidates (not in xrc) or not valid in all subclasses + wxPROPERTY( Title,wxString, SetTitle, GetTitle, wxT("") ) + wxPROPERTY( Font , wxFont , SetFont , GetWindowFont , ) + wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxT("") ) + // MaxHeight, Width , MinHeight , Width + // TODO switch label to control and title to toplevels + + wxPROPERTY( ThemeEnabled , bool , SetThemeEnabled , GetThemeEnabled , ) + //wxPROPERTY( Cursor , wxCursor , SetCursor , GetCursor , ) + // wxPROPERTY( ToolTip , wxString , SetToolTip , GetToolTipText , ) + wxPROPERTY( AutoLayout , bool , SetAutoLayout , GetAutoLayout , ) + + + +#endif +wxEND_PROPERTIES_TABLE() + +wxBEGIN_HANDLERS_TABLE(wxWindow) +wxEND_HANDLERS_TABLE() + +wxCONSTRUCTOR_DUMMY(wxWindow) + +#else IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase) +#endif #endif // __WXUNIVERSAL__/__WXMSW__ BEGIN_EVENT_TABLE(wxWindowMSW, wxWindowBase) @@ -262,7 +365,7 @@ wxWindow *wxWindowMSW::FindItem(long id) const } #endif // wxUSE_CONTROLS - wxWindowList::Node *current = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator current = GetChildren().GetFirst(); while (current) { wxWindow *childWin = current->GetData(); @@ -280,7 +383,7 @@ wxWindow *wxWindowMSW::FindItem(long id) const // Find an item given the MS Windows handle wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const { - wxWindowList::Node *current = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator current = GetChildren().GetFirst(); while (current) { wxWindow *parent = current->GetData(); @@ -314,7 +417,7 @@ wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const // Default command handler bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) { - return FALSE; + return false; } // ---------------------------------------------------------------------------- @@ -323,16 +426,14 @@ bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) void wxWindowMSW::Init() { - // generic - InitBase(); - // MSW specific - m_isBeingDeleted = FALSE; + m_isBeingDeleted = false; m_oldWndProc = NULL; - m_mouseInWindow = FALSE; - m_lastKeydownProcessed = FALSE; + m_mouseInWindow = false; + m_lastKeydownProcessed = false; m_childrenDisabled = NULL; + m_frozenness = 0; // wxWnd m_hMenu = 0; @@ -342,9 +443,6 @@ void wxWindowMSW::Init() m_xThumbSize = 0; m_yThumbSize = 0; - // as all windows are created with WS_VISIBLE style... - m_isShown = TRUE; - #if wxUSE_MOUSEEVENT_HACK m_lastMouseX = m_lastMouseY = -1; @@ -355,7 +453,7 @@ void wxWindowMSW::Init() // Destructor wxWindowMSW::~wxWindowMSW() { - m_isBeingDeleted = TRUE; + m_isBeingDeleted = true; #ifndef __WXUNIVERSAL__ // VS: make sure there's no wxFrame with last focus set to us: @@ -378,9 +476,6 @@ wxWindowMSW::~wxWindowMSW() // find their parent frame (see above). DestroyChildren(); - if ( m_parent ) - m_parent->RemoveChild(this); - if ( m_hWnd ) { // VZ: test temp removed to understand what really happens here @@ -405,10 +500,10 @@ bool wxWindowMSW::Create(wxWindow *parent, long style, const wxString& name) { - wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") ); + wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") ); if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) - return FALSE; + return false; parent->AddChild(this); @@ -424,14 +519,7 @@ bool wxWindowMSW::Create(wxWindow *parent, msflags &= ~WS_BORDER; #endif // wxUniversal - // all windows are created visible by default except popup ones (which are - // like the wxTopLevelWindows in this aspect) - if ( style & wxPOPUP_WINDOW ) - { - msflags &= ~WS_VISIBLE; - m_isShown = FALSE; - } - else + if ( IsShown() ) { msflags |= WS_VISIBLE; } @@ -448,7 +536,7 @@ void wxWindowMSW::SetFocus() HWND hWnd = GetHwnd(); wxCHECK_RET( hWnd, _T("can't set focus to invalid window") ); -#ifndef __WXMICROWIN__ +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) ::SetLastError(0); #endif @@ -501,7 +589,7 @@ wxWindow *wxWindowBase::FindFocus() bool wxWindowMSW::Enable(bool enable) { if ( !wxWindowBase::Enable(enable) ) - return FALSE; + return false; HWND hWnd = GetHwnd(); if ( hWnd ) @@ -511,13 +599,13 @@ bool wxWindowMSW::Enable(bool enable) // showing a modal dialog would result in total greying out (and ungreying // out later) of everything which would be really ugly if ( IsTopLevel() ) - return TRUE; + return true; // when the parent is disabled, all of its children should be disabled as // well but when it is enabled back, only those of the children which // hadn't been already disabled in the beginning should be enabled again, // so we have to keep the list of those children - for ( wxWindowList::Node *node = GetChildren().GetFirst(); + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() ) { @@ -560,13 +648,13 @@ bool wxWindowMSW::Enable(bool enable) m_childrenDisabled = NULL; } - return TRUE; + return true; } bool wxWindowMSW::Show(bool show) { if ( !wxWindowBase::Show(show) ) - return FALSE; + return false; HWND hWnd = GetHwnd(); int cshow = show ? SW_SHOW : SW_HIDE; @@ -577,7 +665,7 @@ bool wxWindowMSW::Show(bool show) wxBringWindowToTop(hWnd); } - return TRUE; + return true; } // Raise the window to the top of the Z order @@ -631,7 +719,7 @@ bool wxWindowMSW::SetFont(const wxFont& font) if ( !wxWindowBase::SetFont(font) ) { // nothing to do - return FALSE; + return false; } HWND hWnd = GetHwnd(); @@ -644,14 +732,14 @@ bool wxWindowMSW::SetFont(const wxFont& font) ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0)); } - return TRUE; + return true; } bool wxWindowMSW::SetCursor(const wxCursor& cursor) { if ( !wxWindowBase::SetCursor(cursor) ) { // no change - return FALSE; + return false; } if ( m_cursor.Ok() ) @@ -668,7 +756,7 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor) ::SetCursor(GetHcursorOf(m_cursor)); } - return TRUE; + return true; } void wxWindowMSW::WarpPointer (int x, int y) @@ -681,12 +769,6 @@ void wxWindowMSW::WarpPointer (int x, int y) } } -#if WXWIN_COMPATIBILITY -void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const -{ -} -#endif // WXWIN_COMPATIBILITY - // --------------------------------------------------------------------------- // scrolling stuff // --------------------------------------------------------------------------- @@ -697,54 +779,23 @@ static inline int wxDirToWinStyle(int orient) return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT; } -#if WXWIN_COMPATIBILITY -void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh) -{ - int range1 = range; - - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = GetScrollPage(orient); - if ( pageSize > 1 && range > 0) - { - range1 += (pageSize - 1); - } - - WinStruct info; - info.nPage = pageSize; // Have to set this, or scrollbar goes awry - info.nMin = 0; - info.nMax = range1; - info.fMask = SIF_RANGE | SIF_PAGE; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh); -} - -void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh) -{ - WinStruct info; - info.nPage = page; - info.fMask = SIF_PAGE; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh); -} - -int wxWindowMSW::GetScrollPage(int orient) const -{ - return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize; -} - -#endif // WXWIN_COMPATIBILITY - inline int GetScrollPosition(HWND hWnd, int wOrient) { #ifdef __WXMICROWIN__ return ::GetScrollPosWX(hWnd, wOrient); #else - return ::GetScrollPos(hWnd, wOrient); + WinStruct scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + scrollInfo.fMask = SIF_POS; + if ( !::GetScrollInfo(hWnd, + wOrient, + &scrollInfo) ) + { + // Not neccessarily an error, if there are no scrollbars yet. + // wxLogLastError(_T("GetScrollInfo")); + } + return scrollInfo.nPos; +// return ::GetScrollPos(hWnd, wOrient); #endif } @@ -760,13 +811,25 @@ int wxWindowMSW::GetScrollPos(int orient) const // of positions that we can scroll. int wxWindowMSW::GetScrollRange(int orient) const { - int minPos, maxPos; + int maxPos; HWND hWnd = GetHwnd(); if ( !hWnd ) return 0; - +#if 0 ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, &minPos, &maxPos); +#endif + WinStruct scrollInfo; + scrollInfo.fMask = SIF_RANGE; + if ( !::GetScrollInfo(hWnd, + orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &scrollInfo) ) + { + // Most of the time this is not really an error, since the return + // value can also be zero when there is no scrollbar yet. + // wxLogLastError(_T("GetScrollInfo")); + } + maxPos = scrollInfo.nMax; // undo "range - 1" done in SetScrollbar() return maxPos + 1; @@ -843,7 +906,12 @@ void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect) pr = NULL; } +#ifdef __WXWINCE__ + // FIXME: is this the exact equivalent of the line below? + ::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_ERASE|SW_INVALIDATE); +#else ::ScrollWindow(GetHwnd(), dx, dy, pr, pr); +#endif } static bool ScrollVertically(HWND hwnd, int kind, int count) @@ -899,19 +967,19 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd) wxAssociateWinWithHandle(hwnd, this); - m_oldWndProc = (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC); + m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd); // we don't need to subclass the window of our own class (in the Windows // sense of the word) - if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) ) + if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) ) { - ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc); + wxSetWindowProc(hwnd, wxWndProc); } else { // don't bother restoring it neither: this also makes it easy to - // implement IsOfStandardClass() method which returns TRUE for the - // standard controls and FALSE for the wxWindows own windows as it can + // implement IsOfStandardClass() method which returns true for the + // standard controls and false for the wxWindows own windows as it can // simply check m_oldWndProc m_oldWndProc = NULL; } @@ -933,7 +1001,7 @@ void wxWindowMSW::UnsubclassWin() { if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) ) { - ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc); + wxSetWindowProc(hwnd, (WNDPROC)m_oldWndProc); } m_oldWndProc = NULL; @@ -949,15 +1017,38 @@ bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc) // unicows.dll, we can override unicows hooks by setting // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own // versions that keep track of fake<->real wnd proc mapping. + + // On WinCE (at least), the wndproc comparison doesn't work, + // so have to use something like this. +#ifdef __WXWINCE__ + extern const wxChar *wxCanvasClassName; + extern const wxChar *wxCanvasClassNameNR; + extern const wxChar *wxMDIFrameClassName; + extern const wxChar *wxMDIFrameClassNameNoRedraw; + extern const wxChar *wxMDIChildFrameClassName; + extern const wxChar *wxMDIChildFrameClassNameNoRedraw; + wxString str(wxGetWindowClass(hWnd)); + if (str == wxCanvasClassName || + str == wxCanvasClassNameNR || + str == wxMDIFrameClassName || + str == wxMDIFrameClassNameNoRedraw || + str == wxMDIChildFrameClassName || + str == wxMDIChildFrameClassNameNoRedraw || + str == _T("wxTLWHiddenParent")) + return true; // Effectively means don't subclass + else + return false; +#else WNDCLASS cls; if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) ) { wxLogLastError(_T("GetClassInfo")); - return FALSE; + return false; } return wndProc == (WXFARPROC)cls.lpfnWndProc; +#endif } // ---------------------------------------------------------------------------- @@ -1046,8 +1137,10 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const { *exstyle = 0; +#ifndef __WXWINCE__ if ( flags & wxTRANSPARENT_WINDOW ) *exstyle |= WS_EX_TRANSPARENT; +#endif switch ( border ) { @@ -1079,7 +1172,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const } // wxUniv doesn't use Windows dialog navigation functions at all -#ifndef __WXUNIVERSAL__ +#if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__) // to make the dialog navigation work with the nested panels we must // use this style (top level windows such as dialogs don't need it) if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() ) @@ -1092,37 +1185,6 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const return style; } -#if WXWIN_COMPATIBILITY -// If nothing defined for this, try the parent. -// E.g. we may be a button loaded from a resource, with no callback function -// defined. -void wxWindowMSW::OnCommand(wxWindow& win, wxCommandEvent& event) -{ - if ( GetEventHandler()->ProcessEvent(event) ) - return; - if ( m_parent ) - m_parent->GetEventHandler()->OnCommand(win, event); -} -#endif // WXWIN_COMPATIBILITY_2 - -#if WXWIN_COMPATIBILITY -wxObject* wxWindowMSW::GetChild(int number) const -{ - // Return a pointer to the Nth object in the Panel - wxNode *node = GetChildren().First(); - int n = number; - while (node && n--) - node = node->Next(); - if ( node ) - { - wxObject *obj = (wxObject *)node->Data(); - return(obj); - } - else - return NULL; -} -#endif // WXWIN_COMPATIBILITY - // Setup background and foreground colours correctly void wxWindowMSW::SetupColours() { @@ -1155,7 +1217,7 @@ void wxWindowMSW::OnInternalIdle() if ( !IsMouseInWindow() ) { // Generate a LEAVE event - m_mouseInWindow = FALSE; + m_mouseInWindow = false; // Unfortunately the mouse button and keyboard state may have // changed by the time the OnInternalIdle function is called, so 'state' @@ -1199,22 +1261,21 @@ void wxWindowMSW::OnInternalIdle() bool wxWindowMSW::Reparent(wxWindowBase *parent) { if ( !wxWindowBase::Reparent(parent) ) - return FALSE; + return false; HWND hWndChild = GetHwnd(); HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0; ::SetParent(hWndChild, hWndParent); - return TRUE; -} +#ifndef __WXWINCE__ + if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT ) + { + EnsureParentHasControlParentStyle(GetParent()); + } +#endif // !__WXWINCE__ -void wxWindowMSW::Clear() -{ - wxClientDC dc((wxWindow *)this); - wxBrush brush(GetBackgroundColour(), wxSOLID); - dc.SetBackground(brush); - dc.Clear(); + return true; } static inline void SendSetRedraw(HWND hwnd, bool on) @@ -1226,16 +1287,24 @@ static inline void SendSetRedraw(HWND hwnd, bool on) void wxWindowMSW::Freeze() { - SendSetRedraw(GetHwnd(), FALSE); + if ( !m_frozenness++ ) + { + SendSetRedraw(GetHwnd(), false); + } } void wxWindowMSW::Thaw() { - SendSetRedraw(GetHwnd(), TRUE); + wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") ); + + if ( !--m_frozenness ) + { + SendSetRedraw(GetHwnd(), true); - // we need to refresh everything or otherwise he invalidated area is not - // repainted - Refresh(); + // we need to refresh everything or otherwise he invalidated area is not + // repainted + Refresh(); + } } void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect) @@ -1265,7 +1334,7 @@ void wxWindowMSW::Update() wxLogLastError(_T("UpdateWindow")); } -#if !defined(__WXMICROWIN__) +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // just calling UpdateWindow() is not enough, what we did in our WM_PAINT // handler needs to be really drawn right now (void)::GdiFlush(); @@ -1295,9 +1364,11 @@ void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget) // DragAcceptFiles in parallel with SetDropTarget. void wxWindowMSW::DragAcceptFiles(bool accept) { +#if !defined(__WXWINCE__) HWND hWnd = GetHwnd(); if ( hWnd ) ::DragAcceptFiles(hWnd, (BOOL)accept); +#endif } // ---------------------------------------------------------------------------- @@ -1620,48 +1691,6 @@ void wxWindowMSW::GetTextExtent(const wxString& string, *externalLeading = tm.tmExternalLeading; } -#if wxUSE_CARET && WXWIN_COMPATIBILITY -// --------------------------------------------------------------------------- -// Caret manipulation -// --------------------------------------------------------------------------- - -void wxWindowMSW::CreateCaret(int w, int h) -{ - SetCaret(new wxCaret(this, w, h)); -} - -void wxWindowMSW::CreateCaret(const wxBitmap *WXUNUSED(bitmap)) -{ - wxFAIL_MSG("not implemented"); -} - -void wxWindowMSW::ShowCaret(bool show) -{ - wxCHECK_RET( m_caret, "no caret to show" ); - - m_caret->Show(show); -} - -void wxWindowMSW::DestroyCaret() -{ - SetCaret(NULL); -} - -void wxWindowMSW::SetCaretPos(int x, int y) -{ - wxCHECK_RET( m_caret, "no caret to move" ); - - m_caret->Move(x, y); -} - -void wxWindowMSW::GetCaretPos(int *x, int *y) const -{ - wxCHECK_RET( m_caret, "no caret to get position of" ); - - m_caret->GetPosition(x, y); -} -#endif // wxUSE_CARET - // --------------------------------------------------------------------------- // popup menu // --------------------------------------------------------------------------- @@ -1678,15 +1707,21 @@ static void wxYieldForCommandsOnly() // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't // want to process it here) MSG msg; - while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE) - && msg.message != WM_QUIT ) + while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE) ) { - wxTheApp->DoMessage((WXMSG *)&msg); - } + if ( msg.message == WM_QUIT ) + { + // if we retrieved a WM_QUIT, insert back into the message queue. + ::PostQuitMessage(0); + break; + } - // If we retrieved a WM_QUIT, insert back into the message queue. - if (msg.message == WM_QUIT) - ::PostQuitMessage(0); + // luckily (as we don't have access to wxEventLoopImpl method from here + // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it + // immediately + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } } bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) @@ -1701,7 +1736,11 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) point.y = y; ::ClientToScreen(hWnd, &point); wxCurrentPopupMenu = menu; - ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL); + UINT flags = 0; +#if !defined(__WXWINCE__) + flags = TPM_RIGHTBUTTON; +#endif + ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL); // we need to do it righ now as otherwise the events are never going to be // sent to wxCurrentPopupMenu from HandleCommand() @@ -1716,7 +1755,7 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) menu->SetInvokingWindow(NULL); - return TRUE; + return true; } #endif // wxUSE_MENUS_NATIVE @@ -1725,7 +1764,7 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) // pre/post message processing // =========================================================================== -long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +WXLRESULT wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { if ( m_oldWndProc ) return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam); @@ -1767,19 +1806,16 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } } - bool bForward = TRUE, - bWindowChange = FALSE; + bool bForward = true, + bWindowChange = false; // should we process this message specially? - bool bProcess = TRUE; + bool bProcess = true; switch ( msg->wParam ) { case VK_TAB: - // assume that nobody wants Shift-TAB for himself - if we - // don't do it there is no easy way for a control to grab - // TABs but still let Shift-TAB work as navugation key - if ( (lDlgCode & DLGC_WANTTAB) && !bShiftDown ) { - bProcess = FALSE; + if ( lDlgCode & DLGC_WANTTAB ) { + bProcess = false; } else { // Ctrl-Tab cycles thru notebook pages @@ -1791,15 +1827,34 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) case VK_UP: case VK_LEFT: if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown ) - bProcess = FALSE; + bProcess = false; else - bForward = FALSE; + bForward = false; break; case VK_DOWN: case VK_RIGHT: if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown ) - bProcess = FALSE; + bProcess = false; + break; + + case VK_ESCAPE: + { +#if wxUSE_BUTTON + wxButton *btn = wxDynamicCast(FindWindow(wxID_CANCEL), + wxButton); + if ( btn && btn->IsEnabled() ) + { + // if we do have a cancel button, do press it + btn->MSWCommand(BN_CLICKED, 0 /* unused */); + + // we consumed the message + return true; + } +#endif // wxUSE_BUTTON + + bProcess = false; + } break; case VK_RETURN: @@ -1809,7 +1864,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // control wants to process Enter itself, don't // call IsDialogMessage() which would interpret // it - return FALSE; + return false; } else if ( lDlgCode & DLGC_BUTTON ) { @@ -1825,7 +1880,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) btn->MSWCommand(BN_CLICKED, 0 /* unused */); } - bProcess = FALSE; + bProcess = false; } // FIXME: this should be handled by // wxNavigationKeyEvent handler and not here!! @@ -1839,7 +1894,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // if we do have a default button, do press it btn->MSWCommand(BN_CLICKED, 0 /* unused */); - return TRUE; + return true; } else // no default button { @@ -1852,13 +1907,13 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // need it for itself and don't let // ::IsDialogMessage() have it as it can // eat the Enter events sometimes - return FALSE; + return false; } else if (!IsTopLevel()) { // if not a top level window, let parent // handle it - return FALSE; + return false; } //else: treat Enter as TAB: pass to the next // control as this is the best thing to do @@ -1869,7 +1924,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) break; default: - bProcess = FALSE; + bProcess = false; } if ( bProcess ) @@ -1881,7 +1936,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( GetEventHandler()->ProcessEvent(event) ) { - return TRUE; + return true; } } } @@ -1915,8 +1970,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } #endif // 1/0 - // we handle VK_ESCAPE ourselves in wxDialog::OnCharHook() and we - // shouldn't let IsDialogMessage() get it as it _always_ eats the + // don't let IsDialogMessage() get VK_ESCAPE as it _always_ eats the // message even when there is no cancel button and when the message is // needed by the control itself: in particular, it prevents the tree in // place edit control from being closed with Escape in a dialog @@ -1928,7 +1982,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // then // assume we can call it by default - bool canSafelyCallIsDlgMsg = TRUE; + bool canSafelyCallIsDlgMsg = true; HWND hwndFocus = ::GetFocus(); @@ -1942,23 +1996,28 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // style has the focus, it can happen. One such possibility is if // all windows are either toplevel, wxDialog, wxPanel or static // controls and no window can actually accept keyboard input. +#if !defined(__WXWINCE__) if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT ) { // passimistic by default - canSafelyCallIsDlgMsg = FALSE; - for ( wxWindowList::Node *node = GetChildren().GetFirst(); + canSafelyCallIsDlgMsg = false; + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() ) { - if ( node->GetData()->AcceptsFocus() ) + wxWindow * const win = node->GetData(); + if ( win->AcceptsFocus() && + !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) & + WS_EX_CONTROLPARENT) ) { // it shouldn't hang... - canSafelyCallIsDlgMsg = TRUE; + canSafelyCallIsDlgMsg = true; break; } } } +#endif // !__WXWINCE__ if ( canSafelyCallIsDlgMsg ) { @@ -1972,7 +2031,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) !::IsWindowVisible(hwndFocus) ) { // it would enter an infinite loop if we do this! - canSafelyCallIsDlgMsg = FALSE; + canSafelyCallIsDlgMsg = false; break; } @@ -1993,7 +2052,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) ) { // IsDialogMessage() did something... - return TRUE; + return true; } } } @@ -2009,7 +2068,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } #endif // wxUSE_TOOLTIPS - return FALSE; + return false; } bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg) @@ -2018,14 +2077,14 @@ bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg) return m_acceleratorTable.Translate(this, pMsg); #else (void) pMsg; - return FALSE; + return false; #endif // wxUSE_ACCEL } bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* WXUNUSED(pMsg)) { // preprocess all messages by default - return TRUE; + return true; } // --------------------------------------------------------------------------- @@ -2126,16 +2185,16 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w return rc; } -long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) { // did we process the message? - bool processed = FALSE; + bool processed = false; // the return value union { bool allow; - long result; + WXLRESULT result; WXHICON hIcon; WXHBRUSH hBrush; } rc; @@ -2158,7 +2217,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam break; case WM_DESTROY: - // never set processed to TRUE and *always* pass WM_DESTROY to + // never set processed to true and *always* pass WM_DESTROY to // DefWindowProc() as Windows may do some internal cleanup when // processing it and failing to pass the message along may cause // memory and resource leaks! @@ -2169,6 +2228,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; +#if !defined(__WXWINCE__) case WM_MOVING: { LPRECT pRect = (LPRECT)lParam; @@ -2186,6 +2246,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } } break; +#endif case WM_SIZE: switch ( wParam ) @@ -2215,6 +2276,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; +#if !defined(__WXWINCE__) case WM_SIZING: { LPRECT pRect = (LPRECT)lParam; @@ -2232,8 +2294,9 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } } break; +#endif -#ifndef __WXMICROWIN__ +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) case WM_ACTIVATEAPP: wxTheApp->SetActive(wParam != 0, FindFocus()); break; @@ -2258,20 +2321,47 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam break; case WM_PAINT: - processed = HandlePaint(); + { + if ( wParam ) + { + // cast to wxWindow is needed for wxUniv + wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam); + processed = HandlePaint(); + } + else + { + processed = HandlePaint(); + } + break; + } + +#ifndef __WXWINCE__ + case WM_PRINT: + { + // Don't call the wx handlers in this case + if ( wxIsKindOf(this, wxListCtrl) ) + break; + + if ( lParam & PRF_ERASEBKGND ) + HandleEraseBkgnd((WXHDC)(HDC)wParam); + + wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam); + processed = HandlePaint(); + } break; +#endif case WM_CLOSE: #ifdef __WXUNIVERSAL__ // Universal uses its own wxFrame/wxDialog, so we don't receive // close events unless we have this. Close(); - processed = TRUE; + processed = true; rc.result = TRUE; #else // don't let the DefWindowProc() destroy our window - we'll do it // ourselves in ~wxWindow - processed = TRUE; + processed = true; rc.result = TRUE; #endif break; @@ -2286,6 +2376,62 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam wParam); break; + // Seems to be broken currently +#if 0 // ndef __WXWINCE__ + case WM_MOUSELEAVE: + { + wxASSERT_MSG( !m_mouseInWindow, wxT("the mouse should be in a window to generate this event!") ); + + // only process this message if the mouse is not in the window, + // This can also check for children in composite windows. + // however, this may mean the the wxEVT_LEAVE_WINDOW is never sent + // if the mouse does not enter the window from it's child before + // leaving the scope of the window. ( perhaps this can be picked + // up in the OnIdle code as before, for this special case ) + if ( /*IsComposite() && */ !IsMouseInWindow() ) + { + m_mouseInWindow = false; + + // Unfortunately no mouse state is passed with a WM_MOUSE_LEAVE + int state = 0; + if ( wxIsShiftDown() ) + state |= MK_SHIFT; + if ( wxIsCtrlDown() ) + state |= MK_CONTROL; + if ( GetKeyState( VK_LBUTTON ) ) + state |= MK_LBUTTON; + if ( GetKeyState( VK_MBUTTON ) ) + state |= MK_MBUTTON; + if ( GetKeyState( VK_RBUTTON ) ) + state |= MK_RBUTTON; + + POINT pt; + if ( !::GetCursorPos(&pt) ) + { + wxLogLastError(_T("GetCursorPos")); + } + + // we need to have client coordinates here for symmetry with + // wxEVT_ENTER_WINDOW + RECT rect = wxGetWindowRect(GetHwnd()); + pt.x -= rect.left; + pt.y -= rect.top; + + wxMouseEvent event2(wxEVT_LEAVE_WINDOW); + InitMouseEvent(event2, pt.x, pt.y, state); + + (void)GetEventHandler()->ProcessEvent(event2); + } + // always pass processed back as false, this allows the window + // manager to process the message too. This is needed to ensure + // windows XP themes work properly as the mouse moves over widgets + // like buttons. + processed = false; + } + break; +#endif + // __WXWINCE__ + #if wxUSE_MOUSEWHEEL case WM_MOUSEWHEEL: processed = HandleMouseWheel(wParam, lParam); @@ -2311,7 +2457,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam { if (!win->IsEnabled()) { - processed = TRUE; + processed = true; break; } @@ -2389,13 +2535,24 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; -#ifdef __WIN95__ case WM_NOTIFY: processed = HandleNotify((int)wParam, lParam, &rc.result); break; -#endif // Win95 - // for these messages we must return TRUE if process the message + // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU, + // otherwise DefWindowProc() does it perfectly fine for us, but MSLU + // apparently doesn't always behave properly and needs some help +#if wxUSE_UNICODE_MSLU && defined(NF_QUERY) + case WM_NOTIFYFORMAT: + if ( lParam == NF_QUERY ) + { + processed = true; + rc.result = NFR_UNICODE; + } + break; +#endif // wxUSE_UNICODE_MSLU + + // for these messages we must return true if process the message #ifdef WM_DRAWITEM case WM_DRAWITEM: case WM_MEASUREITEM: @@ -2432,7 +2589,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam DLGC_WANTALLKEYS; } - processed = TRUE; + processed = true; } //else: get the dlg code from the DefWindowProc() break; @@ -2444,7 +2601,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam m_lastKeydownProcessed = HandleKeyDown((WORD) wParam, lParam); if ( m_lastKeydownProcessed ) { - processed = TRUE; + processed = true; } if ( !processed ) @@ -2459,7 +2616,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case VK_CAPITAL: case VK_NUMLOCK: case VK_SCROLL: - processed = TRUE; + processed = true; break; // avoid duplicate messages to OnChar for these ASCII keys: @@ -2485,10 +2642,10 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case VK_OEM_COMMA: case VK_OEM_MINUS: case VK_OEM_PERIOD: - // but set processed to FALSE, not TRUE to still pass them + // but set processed to false, not true to still pass them // to the control's default window proc - otherwise // built-in keyboard handling won't work - processed = FALSE; + processed = false; break; #ifdef VK_APPS @@ -2511,7 +2668,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } } if (message == WM_SYSKEYDOWN) // Let Windows still handle the SYSKEYs - processed = FALSE; + processed = false; break; case WM_SYSKEYUP: @@ -2540,12 +2697,12 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam // The key was handled in the EVT_KEY_DOWN and handling // a key in an EVT_KEY_DOWN handler is meant, by // design, to prevent EVT_CHARs from happening - m_lastKeydownProcessed = FALSE; - processed = TRUE; + m_lastKeydownProcessed = false; + processed = true; } else { - processed = HandleChar((WORD)wParam, lParam, TRUE); + processed = HandleChar((WORD)wParam, lParam, true); } break; @@ -2600,9 +2757,11 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = HandleSysColorChange(); break; +#if !defined(__WXWINCE__) case WM_DISPLAYCHANGE: processed = HandleDisplayChange(); break; +#endif case WM_PALETTECHANGED: processed = HandlePaletteChanged((WXHWND) (HWND) wParam); @@ -2625,9 +2784,11 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; +#if !defined(__WXWINCE__) case WM_DROPFILES: processed = HandleDropFiles(wParam); break; +#endif case WM_INITDIALOG: processed = HandleInitDialog((WXHWND)(HWND)wParam); @@ -2639,6 +2800,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; +#if !defined(__WXWINCE__) case WM_QUERYENDSESSION: processed = HandleQueryEndSession(lParam, &rc.allow); break; @@ -2650,6 +2812,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case WM_GETMINMAXINFO: processed = HandleGetMinMaxInfo((MINMAXINFO*)lParam); break; +#endif case WM_SETCURSOR: processed = HandleSetCursor((WXHWND)(HWND)wParam, @@ -2671,7 +2834,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam //WPARAM dwFlags = (WPARAM) (DWORD) wParam; LPARAM dwObjId = (LPARAM) (DWORD) lParam; - if (dwObjId == OBJID_CLIENT && GetOrCreateAccessible()) + if (dwObjId == (LPARAM)OBJID_CLIENT && GetOrCreateAccessible()) { return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible()); } @@ -2682,18 +2845,26 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam #if defined(WM_HELP) case WM_HELP: { + // HELPINFO doesn't seem to be supported on WinCE. +#ifndef __WXWINCE__ HELPINFO* info = (HELPINFO*) lParam; // Don't yet process menu help events, just windows if (info->iContextType == HELPINFO_WINDOW) { +#endif wxWindowMSW* subjectOfHelp = this; - bool eventProcessed = FALSE; + bool eventProcessed = false; while (subjectOfHelp && !eventProcessed) { wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), - wxPoint(info->MousePos.x, - info->MousePos.y) ); +#ifdef __WXWINCE__ + wxPoint(0, 0) +#else + wxPoint(info->MousePos.x, info->MousePos.y) +#endif + ); + helpEvent.SetEventObject(this); eventProcessed = GetEventHandler()->ProcessEvent(helpEvent); @@ -2704,6 +2875,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } processed = eventProcessed; +#ifndef __WXWINCE__ } else if (info->iContextType == HELPINFO_MENUITEM) { @@ -2712,10 +2884,13 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = GetEventHandler()->ProcessEvent(helpEvent); } - //else: processed is already FALSE + //else: processed is already false +#endif } break; +#endif +#if !defined(__WXWINCE__) case WM_CONTEXTMENU: { // we don't convert from screen to client coordinates as @@ -2723,9 +2898,23 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt); - processed = GetEventHandler()->ProcessEvent(evtCtx); + + // we could have got an event from our child, reflect it back + // to it if this is the case + wxWindowMSW *win = NULL; + if ( (WXHWND)wParam != m_hWnd ) + { + win = FindItemByHWND((WXHWND)wParam); + } + + if ( !win ) + win = this; + + evtCtx.SetEventObject(win); + processed = win->GetEventHandler()->ProcessEvent(evtCtx); } break; +#endif case WM_MENUCHAR: // we're only interested in our own menus, not MF_SYSMENU @@ -2736,11 +2925,10 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam if ( i != wxNOT_FOUND ) { rc.result = MAKELRESULT(i, MNC_EXECUTE); - processed = TRUE; + processed = true; } } break; -#endif } if ( !processed ) @@ -2808,15 +2996,15 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, int& x, int& y, int& w, int& h) const { + // yes, those are just some arbitrary hardcoded numbers static const int DEFAULT_Y = 200; - static const int DEFAULT_H = 250; - bool nonDefault = FALSE; + bool nonDefault = false; if ( pos.x == -1 ) { - // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can - // just as well set it to CW_USEDEFAULT as well + // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we + // can just as well set it to CW_USEDEFAULT as well x = y = CW_USEDEFAULT; } @@ -2828,7 +3016,7 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, x = pos.x; y = pos.y == -1 ? DEFAULT_Y : pos.y; - nonDefault = TRUE; + nonDefault = true; } /* @@ -2847,20 +3035,33 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, this and ignore any attempts to change the window size to the size it already has - so no WM_SIZE would be sent. */ - if ( size.x == -1 ) + + + // we don't use CW_USEDEFAULT here for several reasons: + // + // 1. it results in huge frames on modern screens (1000*800 is not + // uncommon on my 1280*1024 screen) which is way too big for a half + // empty frame of most of wxWindows samples for example) + // + // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which + // the default is for whatever reason 8*8 which breaks client <-> + // window size calculations (it would be nice if it didn't, but it + // does and the simplest way to fix it seemed to change the broken + // default size anyhow) + // + // 3. there is just no advantage in doing it: with x and y it is + // possible that [future versions of] Windows position the new top + // level window in some smart way which we can't do, but we can + // guess a reasonably good size for a new window just as well + // ourselves + if ( size.x == -1 || size.y == -1) { - // as above, h is not used at all in this case anyhow - w = - h = CW_USEDEFAULT; + nonDefault = true; } - else - { - // and, again as above, we can't set the height to CW_USEDEFAULT here - w = size.x; - h = size.y == -1 ? DEFAULT_H : size.y; + w = WidthDefault(size.x); + h = HeightDefault(size.y); - nonDefault = TRUE; - } + AdjustForParentClientOrigin(x, y); return nonDefault; } @@ -2889,7 +3090,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // which is the same but without CS_[HV]REDRAW class styles so using it // ensures that the window is not fully repainted on each resize wxString className(wclass); - if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE ) + if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) ) { className += wxT("NR"); } @@ -2897,31 +3098,49 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // do create the window wxWindowCreationHook hook(this); - m_hWnd = (WXHWND)::CreateWindowEx - ( - extendedStyle, - className, - title ? title : wxEmptyString, - style, - x, y, w, h, - (HWND)MSWGetParent(), - (HMENU)controlId, - wxGetInstance(), - NULL // no extra data - ); + // VZ: anyonce cares to explain why is this done for CE? +#ifdef __WXWINCE__ + if (extendedStyle == 0) + { + m_hWnd = (WXHWND)::CreateWindow + ( + className, + title ? title : wxEmptyString, + style, + x, y, w, h, + (HWND)MSWGetParent(), + (HMENU)controlId, + wxGetInstance(), + NULL // no extra data + ); + } + else +#endif // __WXWINCE__ + { + m_hWnd = (WXHWND)::CreateWindowEx + ( + extendedStyle, + className, + title ? title : wxEmptyString, + style, + x, y, w, h, + (HWND)MSWGetParent(), + (HMENU)controlId, + wxGetInstance(), + NULL // no extra data + ); + } if ( !m_hWnd ) { wxLogSysError(_("Can't create window of class %s"), wclass); - return FALSE; + return false; } SubclassWin(m_hWnd); - SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); - - return TRUE; + return true; } // =========================================================================== @@ -2955,13 +3174,13 @@ bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // correct button tooltips #if 0 // try all our children - wxWindowList::Node *node = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); while ( node ) { wxWindow *child = node->GetData(); if ( child->MSWOnNotify(idCtrl, lParam, result) ) { - return TRUE; + return true; } node = node->GetNext(); @@ -2971,7 +3190,7 @@ bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // by default, handle it ourselves return MSWOnNotify(idCtrl, lParam, result); #else // __WXMICROWIN__ - return FALSE; + return false; #endif } @@ -2986,35 +3205,72 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code, // this message is supposed to be sent to Unicode programs only) -- hence // we need to handle it as well, otherwise no tooltips will be shown in // this case - - if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) || ttip.empty() ) +#ifndef __WXWINCE__ + if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) + || ttip.empty() ) { // not a tooltip message or no tooltip to show anyhow - return FALSE; + return false; } +#endif LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; + // We don't want to use the szText buffer because it has a limit of 80 + // bytes and this is not enough, especially for Unicode build where it + // limits the tooltip string length to only 40 characters + // + // The best would be, of course, to not impose any length limitations at + // all but then the buffer would have to be dynamic and someone would have + // to free it and we don't have the tooltip owner object here any more, so + // for now use our own static buffer with a higher fixed max length. + // + // Note that using a static buffer should not be a problem as only a single + // tooltip can be shown at the same time anyhow. #if !wxUSE_UNICODE - if ( code == (WXUINT) TTN_NEEDTEXTA ) - { - // we pass just the pointer as we store the string internally anyhow - ttText->lpszText = (char *)ttip.c_str(); + if ( code == (WXUINT) TTN_NEEDTEXTW ) + { + // We need to convert tooltip from multi byte to Unicode on the fly. + static wchar_t buf[513]; + + // Truncate tooltip length if needed as otherwise we might not have + // enough space for it in the buffer and MultiByteToWideChar() would + // return an error + size_t tipLength = wxMin(ttip.Len(), WXSIZEOF(buf) - 1); + + // Convert to WideChar without adding the NULL character. The NULL + // character is added afterwards (this is more efficient). + int len = ::MultiByteToWideChar + ( + CP_ACP, + 0, // no flags + ttip, + tipLength, + buf, + WXSIZEOF(buf) - 1 + ); + + if ( !len ) + { + wxLogLastError(_T("MultiByteToWideChar()")); + } + + buf[len] = L'\0'; + ttText->lpszText = (LPSTR) buf; } - else // TTN_NEEDTEXTW -#endif // !Unicode + else // TTN_NEEDTEXTA +#endif // !wxUSE_UNICODE { -#if wxUSE_UNICODE - // in Unicode mode this is just what we need - ttText->lpszText = (wxChar *)ttip.c_str(); -#else // !Unicode - MultiByteToWideChar(CP_ACP, 0, ttip, ttip.length()+1, - (wchar_t *)ttText->szText, - sizeof(ttText->szText) / sizeof(wchar_t)); -#endif // Unicode/!Unicode + // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or + // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have + // to copy the string we have into the buffer + static wxChar buf[513]; + wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1); + buf[WXSIZEOF(buf) - 1] = _T('\0'); + ttText->lpszText = buf; } - return TRUE; + return true; } #endif // wxUSE_TOOLTIPS @@ -3030,12 +3286,12 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip())) { // processed - return TRUE; + return true; } } #endif // wxUSE_TOOLTIPS - return FALSE; + return false; } #endif // __WIN95__ @@ -3046,9 +3302,10 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) { +#ifndef __WXWINCE__ wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1); event.SetEventObject(wxTheApp); - event.SetCanVeto(TRUE); + event.SetCanVeto(true); event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF); bool rc = wxTheApp->ProcessEvent(event); @@ -3061,24 +3318,31 @@ bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) } return rc; +#else + return false; +#endif } bool wxWindowMSW::HandleEndSession(bool endSession, long logOff) { +#ifndef __WXWINCE__ // do nothing if the session isn't ending if ( !endSession ) - return FALSE; + return false; // only send once if ( (this != wxTheApp->GetTopWindow()) ) - return FALSE; + return false; wxCloseEvent event(wxEVT_END_SESSION, -1); event.SetEventObject(wxTheApp); - event.SetCanVeto(FALSE); + event.SetCanVeto(false); event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) ); return wxTheApp->ProcessEvent(event); +#else + return false; +#endif } // --------------------------------------------------------------------------- @@ -3087,38 +3351,21 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff) bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate) { - // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our - // parent as well as otherwise several Win32 functions using - // GetNextDlgTabItem() to iterate over all controls such as - // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, - // all of them iterate over all the controls starting from the focus and - // stop iterating when they get back to the focus but unless all parents - // have WS_EX_CONTROLPARENT bit set, they would never get back to focus + // VZ: why is this commented out for WinCE? If it doesn't support + // WS_EX_CONTROLPARENT at all it should be somehow handled globally, + // not with multiple #ifdef's! +#ifndef __WXWINCE__ if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT ) - { - // there is no need to do anything for the top level windows - const wxWindow *parent = GetParent(); - while ( parent && !parent->IsTopLevel() ) - { - LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE); - if ( !(exStyle & WS_EX_CONTROLPARENT) ) - { - // force the parent to have this style - ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE, - exStyle | WS_EX_CONTROLPARENT); - } - - parent = parent->GetParent(); - } - } + EnsureParentHasControlParentStyle(GetParent()); +#endif // !__WXWINCE__ // TODO: should generate this event from WM_NCCREATE wxWindowCreateEvent event((wxWindow *)this); (void)GetEventHandler()->ProcessEvent(event); - *mayCreate = TRUE; + *mayCreate = true; - return TRUE; + return true; } bool wxWindowMSW::HandleDestroy() @@ -3137,7 +3384,7 @@ bool wxWindowMSW::HandleDestroy() #endif // wxUSE_DRAG_AND_DROP // WM_DESTROY handled - return TRUE; + return true; } // --------------------------------------------------------------------------- @@ -3176,7 +3423,7 @@ bool wxWindowMSW::HandleSetFocus(WXHWND hwnd) // after the control gets to process it from EN_FOCUS handler if ( wxDynamicCastThis(wxTextCtrl) ) { - return FALSE; + return false; } #endif // wxUSE_TEXTCTRL @@ -3205,7 +3452,7 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl); if ( ctrl ) { - return FALSE; + return false; } #endif @@ -3213,7 +3460,7 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) // only cause problems if the event handler tries to access the object. if ( m_isBeingDeleted ) { - return FALSE; + return false; } wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId); @@ -3247,8 +3494,8 @@ bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) { -#if defined (__WXMICROWIN__) - return FALSE; +#if defined (__WXMICROWIN__) || defined(__WXWINCE__) + return false; #else // __WXMICROWIN__ HDROP hFilesInfo = (HDROP) wParam; @@ -3269,9 +3516,7 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) // and now get the file name ::DragQueryFile(hFilesInfo, wIndex, - files[wIndex].GetWriteBuf(len), len); - - files[wIndex].UngetWriteBuf(); + wxStringBuffer(files[wIndex], len), len); } DragFinish (hFilesInfo); @@ -3303,7 +3548,7 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), if ( nHitTest != HTCLIENT ) { - return FALSE; + return false; } HCURSOR hcursor = 0; @@ -3364,19 +3609,28 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), ::SetCursor(hcursor); // cursor set, stop here - return TRUE; + return true; } #endif // __WXMICROWIN__ // pass up the window chain - return FALSE; + return false; } // --------------------------------------------------------------------------- // owner drawn stuff // --------------------------------------------------------------------------- -bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) +#if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \ + (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)) + #define WXUNUSED_UNLESS_ODRAWN(param) param +#else + #define WXUNUSED_UNLESS_ODRAWN(param) +#endif + +bool +wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id), + WXDRAWITEMSTRUCT * WXUNUSED_UNLESS_ODRAWN(itemStruct)) { #if wxUSE_OWNER_DRAWN @@ -3387,7 +3641,7 @@ bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) { wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData); - wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); + wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), false ); // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent // the DC from being released @@ -3408,47 +3662,57 @@ bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) #endif // USE_OWNER_DRAWN -#if wxUSE_CONTROLS +#if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) #if wxUSE_OWNER_DRAWN - wxWindow *item = FindItem(id); - if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) - return ((wxControl *)item)->MSWOnDraw(itemStruct); -#elif !defined(__WXUNIVERSAL__) + wxControl *item = wxDynamicCast(FindItem(id), wxControl); +#else // !wxUSE_OWNER_DRAWN // we may still have owner-drawn buttons internally because we have to make // them owner-drawn to support colour change - wxWindow *item = FindItem(id); - if ( item && item->IsKindOf(CLASSINFO(wxButton)) ) - return ((wxButton *)item)->MSWOnDraw(itemStruct); + wxControl *item = wxDynamicCast(FindItem(id), wxButton); #endif // USE_OWNER_DRAWN + if ( item ) + { + return item->MSWOnDraw(itemStruct); + } + #endif // wxUSE_CONTROLS - return FALSE; + return false; } -bool wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) +bool +wxWindowMSW::MSWOnMeasureItem(int WXUNUSED_UNLESS_ODRAWN(id), + WXMEASUREITEMSTRUCT * + WXUNUSED_UNLESS_ODRAWN(itemStruct)) { -#if wxUSE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE // is it a menu item? MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct; if ( id == 0 && pMeasureStruct->CtlType == ODT_MENU ) { wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData); - wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); + wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), false ); - return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth, - &pMeasureStruct->itemHeight); + size_t w, h; + bool rc = pMenuItem->OnMeasureItem(&w, &h); + + pMeasureStruct->itemWidth = w; + pMeasureStruct->itemHeight = h; + + return rc; } - wxWindow *item = FindItem(id); - if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) + wxControl *item = wxDynamicCast(FindItem(id), wxControl); + if ( item ) { - return ((wxControl *)item)->MSWOnMeasure(itemStruct); + return item->MSWOnMeasure(itemStruct); } -#endif // owner-drawn menus - return FALSE; +#endif // wxUSE_OWNER_DRAWN + + return false; } // --------------------------------------------------------------------------- @@ -3464,7 +3728,7 @@ bool wxWindowMSW::HandleSysColorChange() // always let the system carry on the default processing to allow the // native controls to react to the colours update - return FALSE; + return false; } bool wxWindowMSW::HandleDisplayChange() @@ -3486,14 +3750,18 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, #ifndef __WXMICROWIN__ WXHBRUSH hBrush = 0; +#ifdef __WXWINCE__ + if (false) +#else if ( nCtlColor == CTLCOLOR_DLG ) +#endif { hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam); } #if wxUSE_CONTROLS else { - wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE); + wxControl *item = (wxControl *)FindItemByHWND(pWnd, true); if ( item ) hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam); } @@ -3504,7 +3772,7 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, return hBrush != 0; #else // __WXMICROWIN__ - return FALSE; + return false; #endif } @@ -3549,7 +3817,7 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange) // now check for the need to redraw if (result > 0) - InvalidateRect((HWND) hWndPalChange, NULL, TRUE); + ::InvalidateRect((HWND) hWndPalChange, NULL, TRUE); } } @@ -3610,9 +3878,9 @@ void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) if ( IsTopLevel() ) { // FIXME-MT - gs_hasStdCmap = FALSE; + gs_hasStdCmap = false; } - wxWindowList::Node *node = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); while ( node ) { // Only propagate to non-top-level windows because Windows already @@ -3631,16 +3899,14 @@ void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) // update the colours we use if they were not set explicitly by the user: // this must be done or OnCtlColor() would continue to use the old colours - if ( !m_hasFgCol ) + if ( !m_hasFgCol || !m_hasBgCol ) { - m_foregroundColour = wxSystemSettings:: - GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); - } + wxVisualAttributes attrs = GetDefaultAttributes(); + if ( !m_hasFgCol ) + m_foregroundColour = attrs.colFg; - if ( !m_hasBgCol ) - { - m_backgroundColour = wxSystemSettings:: - GetSystemColour(wxSYS_COLOUR_BTNFACE); + if ( !m_hasBgCol ) + m_backgroundColour = attrs.colBg; } } @@ -3651,7 +3917,7 @@ extern wxCOLORMAP *wxGetStdColourMap() if ( !gs_hasStdCmap ) { - static bool s_coloursInit = FALSE; + static bool s_coloursInit = false; if ( !s_coloursInit ) { @@ -3689,10 +3955,10 @@ extern wxCOLORMAP *wxGetStdColourMap() //s_stdColours[5] = RGB(255,000,255); // magenta } - s_coloursInit = TRUE; + s_coloursInit = true; } - gs_hasStdCmap = TRUE; + gs_hasStdCmap = true; // create the colour map #define INIT_CMAP_ENTRY(col) \ @@ -3760,12 +4026,12 @@ bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc) { // Prevents flicker when dragging if ( ::IsIconic(GetHwnd()) ) - return TRUE; + return true; #if 0 if (GetParent() && GetParent()->GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) { - return FALSE; + return false; } if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) @@ -3779,7 +4045,7 @@ bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc) ::GetClientRect((HWND) GetHWND(), (RECT*) & rect); wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme, hdc, 10 /* TABP_BODY */, 0, &rect, &rect); wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme); - return TRUE; + return true; } } } @@ -3817,11 +4083,16 @@ void wxWindowMSW::OnEraseBackground(wxEraseEvent& event) HDC hdc = (HDC)event.GetDC()->GetHDC(); +#ifndef __WXWINCE__ int mode = ::SetMapMode(hdc, MM_TEXT); +#endif ::FillRect(hdc, &rect, hBrush); ::DeleteObject(hBrush); + +#ifndef __WXWINCE__ ::SetMapMode(hdc, mode); +#endif } // --------------------------------------------------------------------------- @@ -3888,9 +4159,12 @@ bool wxWindowMSW::HandleSizing(wxRect& rect) bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) { +#ifdef __WXWINCE__ + return false; +#else MINMAXINFO *info = (MINMAXINFO *)mmInfo; - bool rc = FALSE; + bool rc = false; int minWidth = GetMinWidth(), minHeight = GetMinHeight(), @@ -3900,28 +4174,29 @@ bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) if ( minWidth != -1 ) { info->ptMinTrackSize.x = minWidth; - rc = TRUE; + rc = true; } if ( minHeight != -1 ) { info->ptMinTrackSize.y = minHeight; - rc = TRUE; + rc = true; } if ( maxWidth != -1 ) { info->ptMaxTrackSize.x = maxWidth; - rc = TRUE; + rc = true; } if ( maxHeight != -1 ) { info->ptMaxTrackSize.y = maxHeight; - rc = TRUE; + rc = true; } return rc; +#endif } // --------------------------------------------------------------------------- @@ -3985,15 +4260,16 @@ bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) // wxSpinCtrl wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control); if ( spin && spin->ProcessTextCommand(cmd, id) ) - return TRUE; + return true; } #endif // wxUSE_SPINCTRL - return FALSE; + return false; } bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam)) { +#ifndef __WXWINCE__ // 4 bits are reserved switch ( wParam & 0xFFFFFFF0 ) { @@ -4003,8 +4279,9 @@ bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam)) case SC_MINIMIZE: return HandleMinimize(); } +#endif - return FALSE; + return false; } // --------------------------------------------------------------------------- @@ -4030,7 +4307,10 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event, // so simply test for negative value. event.m_altDown = ::GetKeyState(VK_MENU) < 0; - event.SetTimestamp(s_currentMsg.time); +#ifndef __WXWINCE__ + event.SetTimestamp(::GetMessageTime()); +#endif + event.m_eventObject = this; event.SetId(GetId()); @@ -4061,6 +4341,13 @@ static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) // HWND hwnd = GetHwndOf(win), hwndUnderMouse; +#ifdef __WXWINCE__ + hwndUnderMouse = ::ChildWindowFromPoint + ( + hwnd, + pt + ); +#else hwndUnderMouse = ::ChildWindowFromPointEx ( hwnd, @@ -4069,6 +4356,7 @@ static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) // CWP_SKIPDISABLED | CWP_SKIPTRANSPARENT ); +#endif if ( !hwndUnderMouse || hwndUnderMouse == hwnd ) { @@ -4134,8 +4422,20 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) if ( !HasCapture() || IsMouseInWindow() ) { // Generate an ENTER event - m_mouseInWindow = TRUE; - + m_mouseInWindow = true; +#if _WIN32_WINNT >= 0x0400 +#ifndef __WXWINCE__ + TRACKMOUSEEVENT trackinfo; + + trackinfo.cbSize = sizeof(trackinfo); + trackinfo.dwFlags = TME_LEAVE; + trackinfo.hwndTrack = GetHwnd(); + //Use the commctrl.h _TrackMouseEvent, which will call the + // appropriate TrackMouseEvent or emulate it ( win95 ) + // else we need _WIN32_WINNT >= 0x0400 + _TrackMouseEvent(&trackinfo); +#endif +#endif wxMouseEvent event(wxEVT_ENTER_WINDOW); InitMouseEvent(event, x, y, flags); @@ -4154,7 +4454,7 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) { m_lastMouseEvent = wxEVT_MOTION; - return FALSE; + return false; } #endif // wxUSE_MOUSEEVENT_HACK @@ -4194,7 +4494,7 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam) (void) wParam; (void) lParam; - return FALSE; + return false; #endif } @@ -4220,7 +4520,9 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, event.m_keyCode = id; event.m_rawCode = (wxUint32) wParam; event.m_rawFlags = (wxUint32) lParam; - event.SetTimestamp(s_currentMsg.time); +#ifndef __WXWINCE__ + event.SetTimestamp(::GetMessageTime()); +#endif // translate the position to client coords POINT pt; @@ -4236,18 +4538,16 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, return event; } -// isASCII is TRUE only when we're called from WM_CHAR handler and not from +// isASCII is true only when we're called from WM_CHAR handler and not from // WM_KEYDOWN one bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) { - bool ctrlDown = FALSE; - int id; if ( isASCII ) { // If 1 -> 26, translate to either special keycode or just set // ctrlDown. IOW, Ctrl-C should result in keycode == 3 and - // ControlDown() == TRUE. + // ControlDown() == true. id = wParam; if ( (id > 0) && (id < 27) ) { @@ -4266,19 +4566,19 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) break; default: - ctrlDown = TRUE; + //ctrlDown = true; break; } } } else // we're called from WM_KEYDOWN { - id = wxCharCodeMSWToWX(wParam); + id = wxCharCodeMSWToWX(wParam, lParam); if ( id == 0 ) { // it's ASCII and will be processed here only when called from - // WM_CHAR (i.e. when isASCII = TRUE), don't process it now - return FALSE; + // WM_CHAR (i.e. when isASCII = true), don't process it now + return false; } } @@ -4294,7 +4594,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) (id >= 32 && id < 256) ) { event.m_controlDown = - event.m_altDown = FALSE; + event.m_altDown = false; } return GetEventHandler()->ProcessEvent(event); @@ -4302,7 +4602,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( !id ) { @@ -4315,16 +4615,16 @@ bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam)); if ( GetEventHandler()->ProcessEvent(event) ) { - return TRUE; + return true; } } - return FALSE; + return false; } bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( !id ) { @@ -4336,14 +4636,17 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) { wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam)); if ( GetEventHandler()->ProcessEvent(event) ) - return TRUE; + return true; } - return FALSE; + return false; } int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam) { + // FIXME: implement GetMenuItemCount for WinCE, possibly + // in terms of GetMenuItemInfo +#ifndef __WXWINCE__ const HMENU hmenu = (HMENU)lParam; MENUITEMINFO mii; @@ -4397,7 +4700,7 @@ int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam) wxLogLastError(_T("GetMenuItemInfo")); } } - +#endif return wxNOT_FOUND; } @@ -4476,7 +4779,7 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) default: wxFAIL_MSG(wxT("no such joystick event")); - return FALSE; + return false; } wxJoystickEvent event(eventType, buttons, joystick, change); @@ -4485,7 +4788,7 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) return GetEventHandler()->ProcessEvent(event); #else - return FALSE; + return false; #endif } @@ -4495,8 +4798,8 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, WXWORD pos, WXHWND control) -{ - if ( control ) +{ + if ( control && control != m_hWnd ) // Prevent infinite recursion { wxWindow *child = wxFindWinFromHandle(control); if ( child ) @@ -4550,7 +4853,8 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, : SB_VERT, &scrollInfo) ) { - wxLogLastError(_T("GetScrollInfo")); + // Not neccessarily an error, if there are no scrollbars yet. + // wxLogLastError(_T("GetScrollInfo")); } event.SetPosition(scrollInfo.nTrackPos); @@ -4562,7 +4866,7 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, break; default: - return FALSE; + return false; } return GetEventHandler()->ProcessEvent(event); @@ -4604,7 +4908,7 @@ void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font) // Returns 0 if was a normal ASCII value, not a special key. This indicates that // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. -int wxCharCodeMSWToWX(int keySym) +int wxCharCodeMSWToWX(int keySym, WXLPARAM lParam) { int id; switch (keySym) @@ -4613,7 +4917,6 @@ int wxCharCodeMSWToWX(int keySym) case VK_BACK: id = WXK_BACK; break; case VK_TAB: id = WXK_TAB; break; case VK_CLEAR: id = WXK_CLEAR; break; - case VK_RETURN: id = WXK_RETURN; break; case VK_SHIFT: id = WXK_SHIFT; break; case VK_CONTROL: id = WXK_CONTROL; break; case VK_MENU : id = WXK_MENU; break; @@ -4695,6 +4998,13 @@ int wxCharCodeMSWToWX(int keySym) case VK_APPS: id = WXK_WINDOWS_MENU; break; #endif // VK_APPS defined + case VK_RETURN: + // the same key is sent for both the "return" key on the main + // keyboard and the numeric keypad but we want to distinguish + // between them: we do this using the "extended" bit (24) of lParam + id = lParam & (1 << 24) ? WXK_NUMPAD_ENTER : WXK_RETURN; + break; + default: id = 0; } @@ -4704,8 +5014,8 @@ int wxCharCodeMSWToWX(int keySym) int wxCharCodeWXToMSW(int id, bool *isVirtual) { - *isVirtual = TRUE; - int keySym = 0; + *isVirtual = true; + int keySym; switch (id) { case WXK_CANCEL: keySym = VK_CANCEL; break; @@ -4771,7 +5081,7 @@ int wxCharCodeWXToMSW(int id, bool *isVirtual) case WXK_SCROLL: keySym = VK_SCROLL; break; default: { - *isVirtual = FALSE; + *isVirtual = false; keySym = id; break; } @@ -4779,6 +5089,18 @@ int wxCharCodeWXToMSW(int id, bool *isVirtual) return keySym; } +bool wxGetKeyState(wxKeyCode key) +{ + bool bVirtual; + int vkey = wxCharCodeWXToMSW(key, &bVirtual); + + //there aren't WXK_ macros for non-virtual key codes + if (bVirtual == false) + return false; + + return GetKeyState(vkey) < 0; +} + wxWindow *wxGetActiveWindow() { HWND hWnd = GetActiveWindow(); @@ -4808,7 +5130,7 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) // do it as well, win would be already non NULL if ( ::SendMessage(hwnd, WM_GETDLGCODE, 0, 0) & DLGC_RADIOBUTTON ) { - win = (wxWindow *)::GetWindowLong(hwnd, GWL_USERDATA); + win = (wxWindow *)wxGetWindowUserData(hwnd); } //else: it's a wxRadioButton, not a radiobutton from wxRadioBox #endif // wxUSE_RADIOBOX @@ -4849,7 +5171,7 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) return win; } -#ifndef __WXMICROWIN__ +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE // in active frames and dialogs, regardless of where the focus is. @@ -4881,19 +5203,20 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam) DWORD hiWord = HIWORD(lParam); if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) ) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( id != 0 ) { wxKeyEvent event(wxEVT_CHAR_HOOK); if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN ) - event.m_altDown = TRUE; + event.m_altDown = true; event.m_eventObject = NULL; event.m_keyCode = id; event.m_shiftDown = wxIsShiftDown(); event.m_controlDown = wxIsCtrlDown(); - event.SetTimestamp(s_currentMsg.time); - +#ifndef __WXWINCE__ + event.SetTimestamp(::GetMessageTime()); +#endif wxWindow *win = wxGetActiveWindow(); wxEvtHandler *handler; if ( win ) @@ -5438,10 +5761,10 @@ bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode) { wxLogLastError(_T("RegisterHotKey")); - return FALSE; + return false; } - return TRUE; + return true; } bool wxWindowMSW::UnregisterHotKey(int hotkeyId) @@ -5450,10 +5773,10 @@ bool wxWindowMSW::UnregisterHotKey(int hotkeyId) { wxLogLastError(_T("UnregisterHotKey")); - return FALSE; + return false; } - return TRUE; + return true; } bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) @@ -5474,3 +5797,62 @@ bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) #endif // wxUSE_HOTKEY +// Not tested under WinCE +#ifndef __WXWINCE__ + +// this class installs a message hook which really wakes up our idle processing +// each time a WM_NULL is received (wxWakeUpIdle does this), even if we're +// sitting inside a local modal loop (e.g. a menu is opened or scrollbar is +// being dragged or even inside ::MessageBox()) and so don't control message +// dispatching otherwise +class wxIdleWakeUpModule : public wxModule +{ +public: + virtual bool OnInit() + { + ms_hMsgHookProc = ::SetWindowsHookEx + ( + WH_GETMESSAGE, + &wxIdleWakeUpModule::MsgHookProc, + NULL, + GetCurrentThreadId() + ); + + if ( !ms_hMsgHookProc ) + { + wxLogLastError(_T("SetWindowsHookEx(WH_GETMESSAGE)")); + + return false; + } + + return true; + } + + virtual void OnExit() + { + ::UnhookWindowsHookEx(wxIdleWakeUpModule::ms_hMsgHookProc); + } + + static LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam) + { + MSG *msg = (MSG*)lParam; + if ( msg->message == WM_NULL ) + { + wxTheApp->ProcessPendingEvents(); + } + + return CallNextHookEx(ms_hMsgHookProc, nCode, wParam, lParam); + }; + +private: + static HHOOK ms_hMsgHookProc; + + DECLARE_DYNAMIC_CLASS(wxIdleWakeUpModule) +}; + +HHOOK wxIdleWakeUpModule::ms_hMsgHookProc = 0; + +IMPLEMENT_DYNAMIC_CLASS(wxIdleWakeUpModule, wxModule) + +#endif // __WXWINCE__ +