X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1384636de076a06388f9267fbd49f3babb38162d..cc8cc54f8308660af5730d8c3da5ba4710dc0dbb:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index a451b9a33a..223ae9ef0a 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,68 +114,29 @@ #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 +#ifdef __WXWINCE__ +extern wxChar *wxCanvasClassName; +#else extern const wxChar *wxCanvasClassName; +#endif // 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 +184,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 // --------------------------------------------------------------------------- @@ -230,21 +228,109 @@ static inline void wxBringWindowToTop(HWND hwnd) IMPLEMENT_ABSTRACT_CLASS(wxWindowMSW, wxWindowBase) #else // __WXMSW__ #if wxUSE_EXTENDED_RTTI -IMPLEMENT_DYNAMIC_CLASS_XTI(wxWindow, wxWindowBase,"wx/window.h") -WX_BEGIN_PROPERTIES_TABLE(wxWindow) - WX_READONLY_PROPERTY( Parent,wxWindow*, GetParent, ) - WX_PROPERTY( Id,wxWindowID, SetId, GetId, -1 ) - WX_PROPERTY_SET_BY_REF( Title,wxString, SetTitle, GetTitle, wxT("") ) - WX_PROPERTY_SET_BY_REF( Label,wxString, SetLabel, GetLabel, wxT("") ) - WX_PROPERTY_SET_BY_REF( Position,wxPoint, SetPosition , GetPosition, wxDefaultPosition ) - WX_PROPERTY_SET_BY_REF( Size,wxSize, SetSize, GetSize, wxDefaultSize ) -WX_END_PROPERTIES_TABLE() +// 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) -WX_BEGIN_HANDLERS_TABLE(wxWindow) -WX_END_HANDLERS_TABLE() +// 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, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) + wxPROPERTY( Id,wxWindowID, SetId, GetId, wxID_ANY, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) + wxPROPERTY( Position,wxPoint, SetPosition , GetPosition, wxDefaultPosition , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // pos + wxPROPERTY( Size,wxSize, SetSize, GetSize, wxDefaultSize , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // size + wxPROPERTY( WindowStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 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 , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // extstyle + wxPROPERTY( BackgroundColour , wxColour , SetBackgroundColour , GetBackgroundColour , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // bg + wxPROPERTY( ForegroundColour , wxColour , SetForegroundColour , GetForegroundColour , EMPTY_MACROVALUE , 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) -WX_CONSTRUCTOR_DUMMY(wxWindow) #else IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase) #endif @@ -335,7 +421,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; } // ---------------------------------------------------------------------------- @@ -344,16 +430,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; @@ -363,9 +447,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; @@ -376,7 +457,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: @@ -399,9 +480,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 @@ -426,10 +504,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); @@ -445,19 +523,17 @@ 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; } - return MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle); + if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) ) + return false; + + InheritAttributes(); + + return true; } // --------------------------------------------------------------------------- @@ -522,7 +598,7 @@ wxWindow *wxWindowBase::FindFocus() bool wxWindowMSW::Enable(bool enable) { if ( !wxWindowBase::Enable(enable) ) - return FALSE; + return false; HWND hWnd = GetHwnd(); if ( hWnd ) @@ -532,7 +608,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 @@ -581,13 +657,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; @@ -598,7 +674,7 @@ bool wxWindowMSW::Show(bool show) wxBringWindowToTop(hWnd); } - return TRUE; + return true; } // Raise the window to the top of the Z order @@ -652,7 +728,7 @@ bool wxWindowMSW::SetFont(const wxFont& font) if ( !wxWindowBase::SetFont(font) ) { // nothing to do - return FALSE; + return false; } HWND hWnd = GetHwnd(); @@ -665,14 +741,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() ) @@ -689,7 +765,7 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor) ::SetCursor(GetHcursorOf(m_cursor)); } - return TRUE; + return true; } void wxWindowMSW::WarpPointer (int x, int y) @@ -702,12 +778,6 @@ void wxWindowMSW::WarpPointer (int x, int y) } } -#if WXWIN_COMPATIBILITY -void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const -{ -} -#endif // WXWIN_COMPATIBILITY - // --------------------------------------------------------------------------- // scrolling stuff // --------------------------------------------------------------------------- @@ -718,48 +788,6 @@ 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__ @@ -885,11 +913,12 @@ void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect) else { 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); + ::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_SCROLLCHILDREN|SW_ERASE|SW_INVALIDATE); #else ::ScrollWindow(GetHwnd(), dx, dy, pr, pr); #endif @@ -948,19 +977,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 wxWidgets own windows as it can // simply check m_oldWndProc m_oldWndProc = NULL; } @@ -982,7 +1011,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; @@ -999,33 +1028,33 @@ bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc) // 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. + // 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; + extern wxChar *wxCanvasClassName; + extern 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; @@ -1092,8 +1121,11 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const { - // translate the style - WXDWORD style = WS_CHILD | WS_VISIBLE; + // translate common wxWidgets styles to Windows ones + + // most of windows are child ones, those which are not (such as + // wxTopLevelWindow) should remove WS_CHILD in their MSWGetStyle() + WXDWORD style = WS_CHILD; if ( flags & wxCLIP_CHILDREN ) style |= WS_CLIPCHILDREN; @@ -1166,37 +1198,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() { @@ -1229,7 +1230,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' @@ -1273,22 +1274,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) @@ -1300,16 +1300,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()") ); - // we need to refresh everything or otherwise he invalidated area is not - // repainted - Refresh(); + if ( !--m_frozenness ) + { + SendSetRedraw(GetHwnd(), true); + + // we need to refresh everything or otherwise he invalidated area is not + // repainted + Refresh(); + } } void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect) @@ -1498,7 +1506,7 @@ void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height) width = 0; if (height < 0) height = 0; - if ( !::MoveWindow(GetHwnd(), x, y, width, height, TRUE) ) + if ( !::MoveWindow(GetHwnd(), x, y, width, height, IsShown() /*Repaint?*/) ) { wxLogLastError(wxT("MoveWindow")); } @@ -1527,15 +1535,15 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags) return; } - if ( x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) + if ( x == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) x = currentX; - if ( y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) + if ( y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) y = currentY; AdjustForParentClientOrigin(x, y, sizeFlags); - wxSize size(-1, -1); - if ( width == -1 ) + wxSize size = wxDefaultSize; + if ( width == wxDefaultCoord ) { if ( sizeFlags & wxSIZE_AUTO_WIDTH ) { @@ -1549,11 +1557,11 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags) } } - if ( height == -1 ) + if ( height == wxDefaultCoord ) { if ( sizeFlags & wxSIZE_AUTO_HEIGHT ) { - if ( size.x == -1 ) + if ( size.x == wxDefaultCoord ) { size = DoGetBestSize(); } @@ -1591,8 +1599,8 @@ void wxWindowMSW::DoSetClientSize(int width, int height) ::GetClientRect(GetHwnd(), &rectClient); // if the size is already ok, stop here (rectClient.left = top = 0) - if ( (rectClient.right == width || width == -1) && - (rectClient.bottom == height || height == -1) ) + if ( (rectClient.right == width || width == wxDefaultCoord) && + (rectClient.bottom == height || height == wxDefaultCoord) ) { break; } @@ -1660,31 +1668,22 @@ void wxWindowMSW::GetTextExtent(const wxString& string, int *descent, int *externalLeading, const wxFont *theFont) const { - const wxFont *fontToUse = theFont; - if ( !fontToUse ) - fontToUse = &m_font; + wxASSERT_MSG( !theFont || theFont->Ok(), + _T("invalid font in GetTextExtent()") ); - HWND hWnd = GetHwnd(); - HDC dc = ::GetDC(hWnd); + wxFont fontToUse; + if (theFont) + fontToUse = *theFont; + else + fontToUse = GetFont(); - HFONT fnt = 0; - HFONT hfontOld = 0; - if ( fontToUse && fontToUse->Ok() ) - { - fnt = (HFONT)((wxFont *)fontToUse)->GetResourceHandle(); // const_cast - if ( fnt ) - hfontOld = (HFONT)SelectObject(dc,fnt); - } + WindowHDC hdc(GetHwnd()); + SelectInHDC selectFont(hdc, GetHfontOf(fontToUse)); SIZE sizeRect; TEXTMETRIC tm; - GetTextExtentPoint(dc, string, (int)string.Length(), &sizeRect); - GetTextMetrics(dc, &tm); - - if ( fontToUse && fnt && hfontOld ) - SelectObject(dc, hfontOld); - - ReleaseDC(hWnd, dc); + GetTextExtentPoint(hdc, string, string.length(), &sizeRect); + GetTextMetrics(hdc, &tm); if ( x ) *x = sizeRect.cx; @@ -1696,48 +1695,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 // --------------------------------------------------------------------------- @@ -1754,15 +1711,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) @@ -1770,6 +1733,12 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) menu->SetInvokingWindow(this); menu->UpdateUI(); + if ( x == -1 && y == -1 ) + { + wxPoint mouse = ScreenToClient(wxGetMousePosition()); + x = mouse.x; y = mouse.y; + } + HWND hWnd = GetHwnd(); HMENU hMenu = GetHmenuOf(menu); POINT point; @@ -1777,9 +1746,10 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) point.y = y; ::ClientToScreen(hWnd, &point); wxCurrentPopupMenu = menu; +#if defined(__WXWINCE__) UINT flags = 0; -#if !defined(__WXWINCE__) - flags = TPM_RIGHTBUTTON; +#else + UINT flags = TPM_RIGHTBUTTON; #endif ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL); @@ -1796,7 +1766,7 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) menu->SetInvokingWindow(NULL); - return TRUE; + return true; } #endif // wxUSE_MENUS_NATIVE @@ -1805,7 +1775,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); @@ -1847,19 +1817,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 @@ -1871,15 +1838,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: @@ -1889,7 +1875,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 ) { @@ -1905,7 +1891,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!! @@ -1919,11 +1905,11 @@ 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 - { #endif // wxUSE_BUTTON + { // this is a quick and dirty test for a text // control if ( !(lDlgCode & DLGC_HASSETSEL) ) @@ -1932,13 +1918,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 @@ -1949,7 +1935,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) break; default: - bProcess = FALSE; + bProcess = false; } if ( bProcess ) @@ -1961,7 +1947,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( GetEventHandler()->ProcessEvent(event) ) { - return TRUE; + return true; } } } @@ -1995,8 +1981,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 @@ -2008,7 +1993,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // then // assume we can call it by default - bool canSafelyCallIsDlgMsg = TRUE; + bool canSafelyCallIsDlgMsg = true; HWND hwndFocus = ::GetFocus(); @@ -2026,7 +2011,7 @@ 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() ) @@ -2037,7 +2022,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) WS_EX_CONTROLPARENT) ) { // it shouldn't hang... - canSafelyCallIsDlgMsg = TRUE; + canSafelyCallIsDlgMsg = true; break; } @@ -2057,7 +2042,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) !::IsWindowVisible(hwndFocus) ) { // it would enter an infinite loop if we do this! - canSafelyCallIsDlgMsg = FALSE; + canSafelyCallIsDlgMsg = false; break; } @@ -2078,7 +2063,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) ) { // IsDialogMessage() did something... - return TRUE; + return true; } } } @@ -2094,7 +2079,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } #endif // wxUSE_TOOLTIPS - return FALSE; + return false; } bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg) @@ -2103,14 +2088,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; } // --------------------------------------------------------------------------- @@ -2160,7 +2145,7 @@ void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, } // --------------------------------------------------------------------------- -// Main wxWindows window proc and the window proc for wxWindow +// Main wxWidgets window proc and the window proc for wxWindow // --------------------------------------------------------------------------- // Hook for new window just as it's being created, when the window isn't yet @@ -2211,16 +2196,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; @@ -2243,7 +2228,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! @@ -2361,17 +2346,35 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam break; } +#ifndef __WXWINCE__ + case WM_PRINT: + { +#if wxUSE_LISTCTRL + // Don't call the wx handlers in this case + if ( wxIsKindOf(this, wxListCtrl) ) + break; +#endif + + 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; @@ -2386,6 +2389,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); @@ -2411,7 +2470,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam { if (!win->IsEnabled()) { - processed = TRUE; + processed = true; break; } @@ -2475,10 +2534,6 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam break; #endif // __WXMICROWIN__ - case WM_SYSCOMMAND: - processed = HandleSysCommand(wParam, lParam); - break; - case WM_COMMAND: { WORD id, cmd; @@ -2493,7 +2548,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: @@ -2530,7 +2598,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; @@ -2542,7 +2610,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 ) @@ -2557,7 +2625,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: @@ -2583,10 +2651,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 @@ -2609,7 +2677,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: @@ -2638,12 +2706,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; @@ -2775,7 +2843,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()); } @@ -2794,7 +2862,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, @@ -2825,7 +2893,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; @@ -2839,7 +2907,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 @@ -2853,7 +2934,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; @@ -2879,7 +2960,7 @@ wxWinHashTable *wxWinHandleHash = NULL; wxWindow *wxFindWinFromHandle(WXHWND hWnd) { - return wxWinHandleHash->Get((long)hWnd); + return (wxWindow*)wxWinHandleHash->Get((long)hWnd); } void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win) @@ -2924,15 +3005,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 ( pos.x == wxDefaultCoord ) { - // 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; } @@ -2942,15 +3023,15 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, // neither because it is not handled as a special value by Windows then // and so we have to choose some default value for it x = pos.x; - y = pos.y == -1 ? DEFAULT_Y : pos.y; + y = pos.y == wxDefaultCoord ? DEFAULT_Y : pos.y; - nonDefault = TRUE; + nonDefault = true; } /* NB: there used to be some code here which set the initial size of the window to the client size of the parent if no explicit size was - specified. This was wrong because wxWindows programs often assume + specified. This was wrong because wxWidgets programs often assume that they get a WM_SIZE (EVT_SIZE) upon creation, however this broke it. To see why, you should understand that Windows sends WM_SIZE from inside ::CreateWindow() anyhow. However, ::CreateWindow() is called @@ -2959,24 +3040,51 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, event goes to some base class OnSize() instead). So the WM_SIZE we rely on is the one sent when the parent frame resizes its children but here is the problem: if the child already has just the right - size, nothing will happen as both wxWindows and Windows check for + size, nothing will happen as both wxWidgets and Windows check for 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 ) - { - // as above, h is not used at all in this case anyhow - w = + + + // 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 wxWidgets 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 + + // However, on PocketPC devices, we must use the default + // size if possible. +#ifdef _WIN32_WCE + if (size.x == wxDefaultCoord) + w = CW_USEDEFAULT; + else + w = size.x; + if (size.y == wxDefaultCoord) h = CW_USEDEFAULT; - } else + h = size.y; +#else + if ( size.x == wxDefaultCoord || size.y == wxDefaultCoord) { - // 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; - - nonDefault = TRUE; + nonDefault = true; } + w = WidthDefault(size.x); + h = HeightDefault(size.y); +#endif + + AdjustForParentClientOrigin(x, y); return nonDefault; } @@ -3005,7 +3113,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"); } @@ -3013,6 +3121,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // do create the window wxWindowCreationHook hook(this); + // VZ: anyonce cares to explain why is this done for CE? #ifdef __WXWINCE__ if (extendedStyle == 0) { @@ -3029,7 +3138,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, ); } else -#endif +#endif // __WXWINCE__ { m_hWnd = (WXHWND)::CreateWindowEx ( @@ -3049,14 +3158,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; } // =========================================================================== @@ -3096,7 +3203,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(); @@ -3106,7 +3213,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 } @@ -3122,35 +3229,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 @@ -3166,12 +3309,14 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip())) { // processed - return TRUE; + return true; } } +#else + wxUnusedVar(lParam); #endif // wxUSE_TOOLTIPS - return FALSE; + return false; } #endif // __WIN95__ @@ -3183,9 +3328,9 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) { #ifndef __WXWINCE__ - wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1); + wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY); event.SetEventObject(wxTheApp); - event.SetCanVeto(TRUE); + event.SetCanVeto(true); event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF); bool rc = wxTheApp->ProcessEvent(event); @@ -3199,7 +3344,7 @@ bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) return rc; #else - return FALSE; + return false; #endif } @@ -3208,20 +3353,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); + wxCloseEvent event(wxEVT_END_SESSION, wxID_ANY); 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 } @@ -3231,40 +3376,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() @@ -3283,7 +3409,7 @@ bool wxWindowMSW::HandleDestroy() #endif // wxUSE_DRAG_AND_DROP // WM_DESTROY handled - return TRUE; + return true; } // --------------------------------------------------------------------------- @@ -3322,7 +3448,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 @@ -3351,7 +3477,7 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl); if ( ctrl ) { - return FALSE; + return false; } #endif @@ -3359,7 +3485,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); @@ -3394,7 +3520,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; @@ -3447,7 +3573,7 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), if ( nHitTest != HTCLIENT ) { - return FALSE; + return false; } HCURSOR hcursor = 0; @@ -3508,19 +3634,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 @@ -3531,7 +3666,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 @@ -3552,14 +3687,20 @@ bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) #endif // USE_OWNER_DRAWN -#if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) +#if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) #if wxUSE_OWNER_DRAWN 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 - wxControl *item = wxDynamicCast(FindItem(id), wxButton); + wxControl *item = +# if wxUSE_BUTTON + wxDynamicCast(FindItem(id), wxButton) +# else + NULL +# endif + ; #endif // USE_OWNER_DRAWN if ( item ) @@ -3569,22 +3710,30 @@ bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *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 && !defined(__WXUNIVERSAL__) +#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); + + pMeasureStruct->itemWidth = w; + pMeasureStruct->itemHeight = h; - return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth, - &pMeasureStruct->itemHeight); + return rc; } wxControl *item = wxDynamicCast(FindItem(id), wxControl); @@ -3594,7 +3743,7 @@ bool wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) } #endif // wxUSE_OWNER_DRAWN - return FALSE; + return false; } // --------------------------------------------------------------------------- @@ -3610,7 +3759,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() @@ -3633,7 +3782,7 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHBRUSH hBrush = 0; #ifdef __WXWINCE__ - if (FALSE) + if (false) #else if ( nCtlColor == CTLCOLOR_DLG ) #endif @@ -3643,7 +3792,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); } @@ -3654,7 +3803,7 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, return hBrush != 0; #else // __WXMICROWIN__ - return FALSE; + return false; #endif } @@ -3699,7 +3848,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); } } @@ -3729,7 +3878,7 @@ bool wxWindowMSW::HandleQueryNewPalette() while (!win->HasCustomPalette() && win->GetParent()) win = win->GetParent(); if (win->HasCustomPalette()) { /* realize the palette to see whether redrawing is needed */ - HDC hdc = GetDC((HWND) GetHWND()); + HDC hdc = ::GetDC((HWND) GetHWND()); win->m_palette.SetHPALETTE( (WXHPALETTE) ::SelectPalette(hdc, (HPALETTE) win->m_palette.GetHPALETTE(), FALSE) ); @@ -3760,7 +3909,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 ) @@ -3778,20 +3927,6 @@ void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) node = node->GetNext(); } - - // 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 ) - { - m_foregroundColour = wxSystemSettings:: - GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); - } - - if ( !m_hasBgCol ) - { - m_backgroundColour = wxSystemSettings:: - GetSystemColour(wxSYS_COLOUR_BTNFACE); - } } extern wxCOLORMAP *wxGetStdColourMap() @@ -3801,7 +3936,7 @@ extern wxCOLORMAP *wxGetStdColourMap() if ( !gs_hasStdCmap ) { - static bool s_coloursInit = FALSE; + static bool s_coloursInit = false; if ( !s_coloursInit ) { @@ -3839,10 +3974,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) \ @@ -3910,12 +4045,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) @@ -3929,7 +4064,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; } } } @@ -3957,10 +4092,11 @@ void wxWindowMSW::OnEraseBackground(wxEraseEvent& event) { RECT rect; ::GetClientRect(GetHwnd(), &rect); - - COLORREF ref = PALETTERGB(m_backgroundColour.Red(), - m_backgroundColour.Green(), - m_backgroundColour.Blue()); + + wxColour backgroundColour( GetBackgroundColour()); + COLORREF ref = PALETTERGB(backgroundColour.Red(), + backgroundColour.Green(), + backgroundColour.Blue()); HBRUSH hBrush = ::CreateSolidBrush(ref); if ( !hBrush ) wxLogLastError(wxT("CreateSolidBrush")); @@ -4044,39 +4180,40 @@ bool wxWindowMSW::HandleSizing(wxRect& rect) bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) { #ifdef __WXWINCE__ - return FALSE; + wxUnusedVar(mmInfo); + return false; #else MINMAXINFO *info = (MINMAXINFO *)mmInfo; - bool rc = FALSE; + bool rc = false; int minWidth = GetMinWidth(), minHeight = GetMinHeight(), maxWidth = GetMaxWidth(), maxHeight = GetMaxHeight(); - if ( minWidth != -1 ) + if ( minWidth != wxDefaultCoord ) { info->ptMinTrackSize.x = minWidth; - rc = TRUE; + rc = true; } - if ( minHeight != -1 ) + if ( minHeight != wxDefaultCoord ) { info->ptMinTrackSize.y = minHeight; - rc = TRUE; + rc = true; } - if ( maxWidth != -1 ) + if ( maxWidth != wxDefaultCoord ) { info->ptMaxTrackSize.x = maxWidth; - rc = TRUE; + rc = true; } - if ( maxHeight != -1 ) + if ( maxHeight != wxDefaultCoord ) { info->ptMaxTrackSize.y = maxHeight; - rc = TRUE; + rc = true; } return rc; @@ -4144,28 +4281,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; -} - -bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam)) -{ -#ifndef __WXWINCE__ - // 4 bits are reserved - switch ( wParam & 0xFFFFFFF0 ) - { - case SC_MAXIMIZE: - return HandleMaximize(); - - case SC_MINIMIZE: - return HandleMinimize(); - } -#endif - - return FALSE; + return false; } // --------------------------------------------------------------------------- @@ -4191,7 +4311,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()); @@ -4303,8 +4426,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); @@ -4323,7 +4458,7 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) { m_lastMouseEvent = wxEVT_MOTION; - return FALSE; + return false; } #endif // wxUSE_MOUSEEVENT_HACK @@ -4363,7 +4498,7 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam) (void) wParam; (void) lParam; - return FALSE; + return false; #endif } @@ -4387,9 +4522,14 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, event.m_eventObject = (wxWindow *)this; // const_cast event.m_keyCode = id; +#if wxUSE_UNICODE + event.m_uniChar = wParam; +#endif 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; @@ -4405,18 +4545,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) ) { @@ -4435,19 +4573,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; } } @@ -4463,7 +4601,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); @@ -4471,7 +4609,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 ) { @@ -4484,16 +4622,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 ) { @@ -4505,10 +4643,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) @@ -4569,6 +4707,9 @@ int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam) wxLogLastError(_T("GetMenuItemInfo")); } } +#else + wxUnusedVar(chAccel); + wxUnusedVar(lParam); #endif return wxNOT_FOUND; } @@ -4648,7 +4789,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); @@ -4657,7 +4798,11 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) return GetEventHandler()->ProcessEvent(event); #else - return FALSE; + wxUnusedVar(msg); + wxUnusedVar(x); + wxUnusedVar(y); + wxUnusedVar(flags); + return false; #endif } @@ -4667,8 +4812,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 ) @@ -4735,7 +4880,7 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, break; default: - return FALSE; + return false; } return GetEventHandler()->ProcessEvent(event); @@ -4745,22 +4890,20 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, // global functions // =========================================================================== -void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font) +void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont& the_font) { TEXTMETRIC tm; HDC dc = ::GetDC((HWND) wnd); - HFONT fnt =0; HFONT was = 0; - if ( the_font ) - { - // the_font->UseResource(); - // the_font->RealizeResource(); - fnt = (HFONT)((wxFont *)the_font)->GetResourceHandle(); // const_cast - if ( fnt ) - was = (HFONT) SelectObject(dc,fnt); - } + + // the_font.UseResource(); + // the_font.RealizeResource(); + HFONT fnt = (HFONT)the_font.GetResourceHandle(); // const_cast + if ( fnt ) + was = (HFONT) SelectObject(dc,fnt); + GetTextMetrics(dc, &tm); - if ( the_font && fnt && was ) + if ( fnt && was ) { SelectObject(dc,was); } @@ -4771,13 +4914,12 @@ void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font) if ( y ) *y = tm.tmHeight + tm.tmExternalLeading; - // if ( the_font ) - // the_font->ReleaseResource(); + // the_font.ReleaseResource(); } // 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) @@ -4786,7 +4928,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; @@ -4868,6 +5009,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; } @@ -4877,16 +5025,18 @@ 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; case WXK_CLEAR: keySym = VK_CLEAR; break; case WXK_SHIFT: keySym = VK_SHIFT; break; case WXK_CONTROL: keySym = VK_CONTROL; break; + case WXK_ALT: keySym = VK_MENU; break; case WXK_MENU : keySym = VK_MENU; break; case WXK_PAUSE: keySym = VK_PAUSE; break; + case WXK_CAPITAL: keySym = VK_CAPITAL; break; case WXK_PRIOR: keySym = VK_PRIOR; break; case WXK_NEXT : keySym = VK_NEXT; break; case WXK_END: keySym = VK_END; break; @@ -4944,7 +5094,7 @@ int wxCharCodeWXToMSW(int id, bool *isVirtual) case WXK_SCROLL: keySym = VK_SCROLL; break; default: { - *isVirtual = FALSE; + *isVirtual = false; keySym = id; break; } @@ -4952,6 +5102,30 @@ int wxCharCodeWXToMSW(int id, bool *isVirtual) return keySym; } +bool wxGetKeyState(wxKeyCode key) +{ + bool bVirtual; + int vkey = wxCharCodeWXToMSW(key, &bVirtual); + SHORT state; + + switch (key) + { + case WXK_NUMLOCK: + case WXK_CAPITAL: + case WXK_SCROLL: + // get the toggle state of the special key + state = GetKeyState(vkey); + break; + + default: + // Get the current state of the physical key + state = GetAsyncKeyState(vkey); + break; + } + // if the most significant bit is set then the key is down + return ( state & 0x0001 ) != 0; +} + wxWindow *wxGetActiveWindow() { HWND hWnd = GetActiveWindow(); @@ -4981,7 +5155,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 @@ -5054,19 +5228,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 ) @@ -5077,7 +5252,7 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam) else { handler = wxTheApp; - event.SetId(-1); + event.SetId(wxID_ANY); } if ( handler && handler->ProcessEvent(event) ) @@ -5611,10 +5786,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) @@ -5623,12 +5798,14 @@ bool wxWindowMSW::UnregisterHotKey(int hotkeyId) { wxLogLastError(_T("UnregisterHotKey")); - return FALSE; + return false; } - return TRUE; + return true; } +#if wxUSE_ACCEL + bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) { int hotkeyId = wParam; @@ -5645,5 +5822,66 @@ bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) return GetEventHandler()->ProcessEvent(event); } +#endif // wxUSE_ACCEL + #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__ +