X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/39d2f9a7c866338762ca974209219f40d4420af6..35f512937be0f668f60d3a064547bdfcfa83e4ba:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 51243e6392..a8191c4e43 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 @@ -49,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 @@ -91,10 +93,11 @@ #include "wx/textctrl.h" #include "wx/notebook.h" +#include "wx/listctrl.h" #include -#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) #include #include #endif @@ -103,7 +106,7 @@ #include #endif -#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) #ifdef __WIN95__ #include #endif @@ -111,59 +114,16 @@ #include "wx/msw/gnuwin32/extra.h" #endif -#if defined(__GNUG__) #include "wx/msw/missing.h" -#endif #if defined(__WXWINCE__) #include "wx/msw/wince/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 -#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 @@ -172,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 @@ -220,6 +180,38 @@ static inline void wxBringWindowToTop(HWND hwnd) } } +// 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. + */ +#ifndef __WXWINCE__ + 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 // --------------------------------------------------------------------------- @@ -229,7 +221,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) @@ -317,7 +415,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; } // ---------------------------------------------------------------------------- @@ -326,16 +424,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; @@ -345,9 +441,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; @@ -358,7 +451,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: @@ -381,9 +474,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 @@ -408,10 +498,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); @@ -427,14 +517,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; } @@ -504,7 +587,7 @@ wxWindow *wxWindowBase::FindFocus() bool wxWindowMSW::Enable(bool enable) { if ( !wxWindowBase::Enable(enable) ) - return FALSE; + return false; HWND hWnd = GetHwnd(); if ( hWnd ) @@ -514,7 +597,7 @@ 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 @@ -563,13 +646,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; @@ -580,7 +663,7 @@ bool wxWindowMSW::Show(bool show) wxBringWindowToTop(hWnd); } - return TRUE; + return true; } // Raise the window to the top of the Z order @@ -634,7 +717,7 @@ bool wxWindowMSW::SetFont(const wxFont& font) if ( !wxWindowBase::SetFont(font) ) { // nothing to do - return FALSE; + return false; } HWND hWnd = GetHwnd(); @@ -647,14 +730,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() ) @@ -671,7 +754,7 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor) ::SetCursor(GetHcursorOf(m_cursor)); } - return TRUE; + return true; } void wxWindowMSW::WarpPointer (int x, int y) @@ -684,12 +767,6 @@ void wxWindowMSW::WarpPointer (int x, int y) } } -#if WXWIN_COMPATIBILITY -void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const -{ -} -#endif // WXWIN_COMPATIBILITY - // --------------------------------------------------------------------------- // scrolling stuff // --------------------------------------------------------------------------- @@ -700,61 +777,20 @@ 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 - SCROLLINFO scrollInfo; + WinStruct scrollInfo; scrollInfo.cbSize = sizeof(SCROLLINFO); scrollInfo.fMask = SIF_POS; if ( !::GetScrollInfo(hWnd, - wOrient, - &scrollInfo) ) + wOrient, + &scrollInfo) ) { - wxLogLastError(_T("GetScrollInfo")); + // Not neccessarily an error, if there are no scrollbars yet. + // wxLogLastError(_T("GetScrollInfo")); } return scrollInfo.nPos; // return ::GetScrollPos(hWnd, wOrient); @@ -781,13 +817,15 @@ int wxWindowMSW::GetScrollRange(int orient) const ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, &minPos, &maxPos); #endif - SCROLLINFO scrollInfo; + WinStruct scrollInfo; scrollInfo.fMask = SIF_RANGE; if ( !::GetScrollInfo(hWnd, - orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, - &scrollInfo) ) + orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &scrollInfo) ) { - wxLogLastError(_T("GetScrollInfo")); + // 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; @@ -927,19 +965,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) ) { - ::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; } @@ -961,7 +999,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; @@ -990,21 +1028,21 @@ bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc) wxString str(wxGetWindowClass(hWnd)); if (str == wxCanvasClassName || str == wxCanvasClassNameNR || - str == wxMDIFrameClassName || - str == wxMDIFrameClassNameNoRedraw || - str == wxMDIChildFrameClassName || - str == wxMDIChildFrameClassNameNoRedraw || + str == wxMDIFrameClassName || + str == wxMDIFrameClassNameNoRedraw || + str == wxMDIChildFrameClassName || + str == wxMDIChildFrameClassNameNoRedraw || str == _T("wxTLWHiddenParent")) - return TRUE; // Effectively means don't subclass + return true; // Effectively means don't subclass else - return FALSE; + return false; #else WNDCLASS cls; if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) ) { wxLogLastError(_T("GetClassInfo")); - return FALSE; + return false; } return wndProc == (WXFARPROC)cls.lpfnWndProc; @@ -1145,37 +1183,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() { @@ -1208,7 +1215,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' @@ -1252,22 +1259,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) @@ -1279,16 +1285,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) @@ -1675,48 +1689,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 // --------------------------------------------------------------------------- @@ -1733,15 +1705,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) @@ -1775,7 +1753,7 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) menu->SetInvokingWindow(NULL); - return TRUE; + return true; } #endif // wxUSE_MENUS_NATIVE @@ -1784,7 +1762,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); @@ -1826,19 +1804,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 @@ -1850,15 +1825,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: @@ -1868,7 +1862,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 ) { @@ -1884,7 +1878,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!! @@ -1898,7 +1892,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 { @@ -1911,13 +1905,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 @@ -1928,7 +1922,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) break; default: - bProcess = FALSE; + bProcess = false; } if ( bProcess ) @@ -1940,7 +1934,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( GetEventHandler()->ProcessEvent(event) ) { - return TRUE; + return true; } } } @@ -1974,8 +1968,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 @@ -1987,7 +1980,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // then // assume we can call it by default - bool canSafelyCallIsDlgMsg = TRUE; + bool canSafelyCallIsDlgMsg = true; HWND hwndFocus = ::GetFocus(); @@ -2005,21 +1998,24 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT ) { // passimistic by default - canSafelyCallIsDlgMsg = FALSE; + 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 +#endif // !__WXWINCE__ if ( canSafelyCallIsDlgMsg ) { @@ -2033,7 +2029,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) !::IsWindowVisible(hwndFocus) ) { // it would enter an infinite loop if we do this! - canSafelyCallIsDlgMsg = FALSE; + canSafelyCallIsDlgMsg = false; break; } @@ -2054,7 +2050,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) ) { // IsDialogMessage() did something... - return TRUE; + return true; } } } @@ -2070,7 +2066,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } #endif // wxUSE_TOOLTIPS - return FALSE; + return false; } bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg) @@ -2079,14 +2075,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; } // --------------------------------------------------------------------------- @@ -2187,16 +2183,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; @@ -2219,7 +2215,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! @@ -2323,20 +2319,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; @@ -2351,6 +2374,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); @@ -2376,7 +2455,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam { if (!win->IsEnabled()) { - processed = TRUE; + processed = true; break; } @@ -2458,7 +2537,20 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = HandleNotify((int)wParam, lParam, &rc.result); break; - // 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: @@ -2495,7 +2587,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; @@ -2507,7 +2599,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 ) @@ -2522,7 +2614,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: @@ -2548,10 +2640,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 @@ -2574,7 +2666,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: @@ -2603,12 +2695,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; @@ -2740,7 +2832,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()); } @@ -2759,7 +2851,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam { #endif wxWindowMSW* subjectOfHelp = this; - bool eventProcessed = FALSE; + bool eventProcessed = false; while (subjectOfHelp && !eventProcessed) { wxHelpEvent helpEvent(wxEVT_HELP, @@ -2790,7 +2882,7 @@ 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; @@ -2804,7 +2896,20 @@ 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 @@ -2818,7 +2923,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam if ( i != wxNOT_FOUND ) { rc.result = MAKELRESULT(i, MNC_EXECUTE); - processed = TRUE; + processed = true; } } break; @@ -2889,15 +2994,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; } @@ -2909,7 +3014,7 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, x = pos.x; y = pos.y == -1 ? DEFAULT_Y : pos.y; - nonDefault = TRUE; + nonDefault = true; } /* @@ -2928,20 +3033,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; } @@ -2970,7 +3088,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"); } @@ -3014,14 +3132,12 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, { 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; } // =========================================================================== @@ -3061,7 +3177,7 @@ bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) wxWindow *child = node->GetData(); if ( child->MSWOnNotify(idCtrl, lParam, result) ) { - return TRUE; + return true; } node = node->GetNext(); @@ -3071,7 +3187,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 } @@ -3087,35 +3203,71 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code, // we need to handle it as well, otherwise no tooltips will be shown in // this case #ifndef __WXWINCE__ - if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) || ttip.empty() ) + 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 @@ -3131,12 +3283,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__ @@ -3150,7 +3302,7 @@ 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); @@ -3164,7 +3316,7 @@ bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) return rc; #else - return FALSE; + return false; #endif } @@ -3173,20 +3325,20 @@ 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; + return false; #endif } @@ -3196,40 +3348,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(); - } - } -#endif + 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() @@ -3248,7 +3381,7 @@ bool wxWindowMSW::HandleDestroy() #endif // wxUSE_DRAG_AND_DROP // WM_DESTROY handled - return TRUE; + return true; } // --------------------------------------------------------------------------- @@ -3287,7 +3420,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 @@ -3316,7 +3449,7 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl); if ( ctrl ) { - return FALSE; + return false; } #endif @@ -3324,7 +3457,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); @@ -3359,7 +3492,7 @@ bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) { #if defined (__WXMICROWIN__) || defined(__WXWINCE__) - return FALSE; + return false; #else // __WXMICROWIN__ HDROP hFilesInfo = (HDROP) wParam; @@ -3380,9 +3513,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); @@ -3414,7 +3545,7 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), if ( nHitTest != HTCLIENT ) { - return FALSE; + return false; } HCURSOR hcursor = 0; @@ -3475,19 +3606,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 @@ -3498,7 +3638,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 @@ -3519,47 +3659,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 ); + + size_t w, h; + bool rc = pMenuItem->OnMeasureItem(&w, &h); - return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth, - &pMeasureStruct->itemHeight); + 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; } // --------------------------------------------------------------------------- @@ -3575,7 +3725,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() @@ -3598,7 +3748,7 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHBRUSH hBrush = 0; #ifdef __WXWINCE__ - if (FALSE) + if (false) #else if ( nCtlColor == CTLCOLOR_DLG ) #endif @@ -3608,7 +3758,7 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, #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); } @@ -3619,7 +3769,7 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, return hBrush != 0; #else // __WXMICROWIN__ - return FALSE; + return false; #endif } @@ -3664,7 +3814,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); } } @@ -3725,7 +3875,7 @@ void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) if ( IsTopLevel() ) { // FIXME-MT - gs_hasStdCmap = FALSE; + gs_hasStdCmap = false; } wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); while ( node ) @@ -3746,16 +3896,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; } } @@ -3766,7 +3914,7 @@ extern wxCOLORMAP *wxGetStdColourMap() if ( !gs_hasStdCmap ) { - static bool s_coloursInit = FALSE; + static bool s_coloursInit = false; if ( !s_coloursInit ) { @@ -3804,10 +3952,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) \ @@ -3875,12 +4023,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) @@ -3894,7 +4042,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; } } } @@ -4009,11 +4157,11 @@ bool wxWindowMSW::HandleSizing(wxRect& rect) bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) { #ifdef __WXWINCE__ - return FALSE; + return false; #else MINMAXINFO *info = (MINMAXINFO *)mmInfo; - bool rc = FALSE; + bool rc = false; int minWidth = GetMinWidth(), minHeight = GetMinHeight(), @@ -4023,25 +4171,25 @@ 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; @@ -4109,11 +4257,11 @@ 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)) @@ -4130,7 +4278,7 @@ bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam)) } #endif - return FALSE; + return false; } // --------------------------------------------------------------------------- @@ -4156,7 +4304,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()); @@ -4268,8 +4419,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); @@ -4288,7 +4451,7 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) { m_lastMouseEvent = wxEVT_MOTION; - return FALSE; + return false; } #endif // wxUSE_MOUSEEVENT_HACK @@ -4328,7 +4491,7 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam) (void) wParam; (void) lParam; - return FALSE; + return false; #endif } @@ -4354,7 +4517,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; @@ -4370,18 +4535,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) ) { @@ -4400,19 +4563,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; } } @@ -4428,7 +4591,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); @@ -4436,7 +4599,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 ) { @@ -4449,16 +4612,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 ) { @@ -4470,10 +4633,10 @@ 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) @@ -4613,7 +4776,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); @@ -4622,7 +4785,7 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) return GetEventHandler()->ProcessEvent(event); #else - return FALSE; + return false; #endif } @@ -4632,8 +4795,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 ) @@ -4687,7 +4850,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); @@ -4699,7 +4863,7 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, break; default: - return FALSE; + return false; } return GetEventHandler()->ProcessEvent(event); @@ -4741,7 +4905,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) @@ -4750,7 +4914,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; @@ -4832,6 +4995,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; } @@ -4841,8 +5011,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; @@ -4908,7 +5078,7 @@ int wxCharCodeWXToMSW(int id, bool *isVirtual) case WXK_SCROLL: keySym = VK_SCROLL; break; default: { - *isVirtual = FALSE; + *isVirtual = false; keySym = id; break; } @@ -4916,6 +5086,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(); @@ -4945,7 +5127,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 @@ -5018,19 +5200,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 ) @@ -5575,10 +5758,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) @@ -5587,10 +5770,10 @@ bool wxWindowMSW::UnregisterHotKey(int hotkeyId) { wxLogLastError(_T("UnregisterHotKey")); - return FALSE; + return false; } - return TRUE; + return true; } bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) @@ -5611,3 +5794,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__ +