X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/05d3cd45e5991ee8275ca870d17b28b17ca34c87..7848088476db284a94f19eeb24411b45d676ac46:/src/msw/window.cpp?ds=sidebyside diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 4167197fda..d0dca74f79 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -17,7 +17,7 @@ // headers // --------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "window.h" #endif @@ -29,8 +29,7 @@ #endif #ifndef WX_PRECOMP - #include - #include "wx/msw/winundef.h" + #include "wx/msw/wrapwin.h" #include "wx/window.h" #include "wx/accel.h" #include "wx/setup.h" @@ -50,16 +49,19 @@ #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 #if wxUSE_ACCESSIBILITY #include "wx/access.h" + #include #include #ifndef WM_GETOBJECT #define WM_GETOBJECT 0x003D @@ -91,10 +93,11 @@ #include "wx/textctrl.h" #include "wx/notebook.h" +#include "wx/listctrl.h" #include -#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) #include #include #endif @@ -103,58 +106,24 @@ #include #endif -#if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__) #ifdef __WIN95__ #include #endif -#elif !defined(__WXMICROWIN__) // broken compiler - #ifndef __TWIN32__ - #include "wx/msw/gnuwin32/extra.h" - #endif +#elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler + #include "wx/msw/gnuwin32/extra.h" #endif -// ---------------------------------------------------------------------------- -// standard constants not available with all compilers/headers -// ---------------------------------------------------------------------------- +#include "wx/msw/missing.h" -// 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_PLUS 0xBB - #define VK_OEM_COMMA 0xBC - #define VK_OEM_MINUS 0xBD - #define VK_OEM_PERIOD 0xBE - #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 +#if defined(__WXWINCE__) +#include "wx/msw/wince/missing.h" #endif // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- -// the last Windows message we got (FIXME-MT) -extern MSG s_currentMsg; - #if wxUSE_MENUS_NATIVE wxMenu *wxCurrentPopupMenu = NULL; #endif // wxUSE_MENUS_NATIVE @@ -163,32 +132,23 @@ 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 // --------------------------------------------------------------------------- // the window proc for all our windows -#ifdef __DIGITALMARS__ -extern "C" LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, - WPARAM wParam, LPARAM lParam); -#else LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); -#endif - + #ifdef __WXDEBUG__ const char *wxGetMessageName(int message); #endif //__WXDEBUG__ void wxRemoveHandleAssociation(wxWindowMSW *win); -#ifdef __DIGITALMARS__ -extern "C" void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win); -#else extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win); -#endif wxWindow *wxFindWinFromHandle(WXHWND hWnd); // this magical function is used to translate VK_APPS key presses to right @@ -211,17 +171,49 @@ static inline void wxBringWindowToTop(HWND hwnd) // activate (set focus to) specified window ::SetFocus(hwnd); +#endif // raise top level parent to top of z order - ::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); -#else // !__WXMICROWIN__ - if ( !::BringWindowToTop(hwnd) ) + if (!::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)) { - wxLogLastError(_T("BringWindowToTop")); + wxLogLastError(_T("SetWindowPos")); } -#endif // __WXMICROWIN__/!__WXMICROWIN__ } +#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 // --------------------------------------------------------------------------- @@ -231,14 +223,119 @@ 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) EVT_ERASE_BACKGROUND(wxWindowMSW::OnEraseBackground) EVT_SYS_COLOUR_CHANGED(wxWindowMSW::OnSysColourChanged) EVT_INIT_DIALOG(wxWindowMSW::OnInitDialog) - EVT_IDLE(wxWindowMSW::OnIdle) END_EVENT_TABLE() // =========================================================================== @@ -268,7 +365,7 @@ wxWindow *wxWindowMSW::FindItem(long id) const } #endif // wxUSE_CONTROLS - wxWindowList::Node *current = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator current = GetChildren().GetFirst(); while (current) { wxWindow *childWin = current->GetData(); @@ -286,7 +383,7 @@ wxWindow *wxWindowMSW::FindItem(long id) const // Find an item given the MS Windows handle wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const { - wxWindowList::Node *current = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator current = GetChildren().GetFirst(); while (current) { wxWindow *parent = current->GetData(); @@ -320,7 +417,7 @@ wxWindow *wxWindowMSW::FindItemByHWND(WXHWND hWnd, bool controlOnly) const // Default command handler bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) { - return FALSE; + return false; } // ---------------------------------------------------------------------------- @@ -329,17 +426,14 @@ bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) void wxWindowMSW::Init() { - // generic - InitBase(); - // MSW specific - m_isBeingDeleted = FALSE; + m_isBeingDeleted = false; m_oldWndProc = NULL; - m_useCtl3D = FALSE; - m_mouseInWindow = FALSE; - m_lastKeydownProcessed = FALSE; + m_mouseInWindow = false; + m_lastKeydownProcessed = false; m_childrenDisabled = NULL; + m_frozenness = 0; // wxWnd m_hMenu = 0; @@ -348,10 +442,6 @@ void wxWindowMSW::Init() m_xThumbSize = 0; m_yThumbSize = 0; - m_backgroundTransparent = FALSE; - - // as all windows are created with WS_VISIBLE style... - m_isShown = TRUE; #if wxUSE_MOUSEEVENT_HACK m_lastMouseX = @@ -363,7 +453,7 @@ void wxWindowMSW::Init() // Destructor wxWindowMSW::~wxWindowMSW() { - m_isBeingDeleted = TRUE; + m_isBeingDeleted = true; #ifndef __WXUNIVERSAL__ // VS: make sure there's no wxFrame with last focus set to us: @@ -386,9 +476,6 @@ wxWindowMSW::~wxWindowMSW() // find their parent frame (see above). DestroyChildren(); - if ( m_parent ) - m_parent->RemoveChild(this); - if ( m_hWnd ) { // VZ: test temp removed to understand what really happens here @@ -413,10 +500,10 @@ bool wxWindowMSW::Create(wxWindow *parent, long style, const wxString& name) { - wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") ); + wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") ); if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) - return FALSE; + return false; parent->AddChild(this); @@ -432,14 +519,7 @@ bool wxWindowMSW::Create(wxWindow *parent, msflags &= ~WS_BORDER; #endif // wxUniversal - // all windows are created visible by default except popup ones (which are - // like the wxTopLevelWindows in this aspect) - if ( style & wxPOPUP_WINDOW ) - { - msflags &= ~WS_VISIBLE; - m_isShown = FALSE; - } - else + if ( IsShown() ) { msflags |= WS_VISIBLE; } @@ -456,7 +536,7 @@ void wxWindowMSW::SetFocus() HWND hWnd = GetHwnd(); wxCHECK_RET( hWnd, _T("can't set focus to invalid window") ); -#ifndef __WXMICROWIN__ +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) ::SetLastError(0); #endif @@ -479,8 +559,6 @@ void wxWindowMSW::SetFocus() void wxWindowMSW::SetFocusFromKbd() { - wxWindowBase::SetFocusFromKbd(); - // when the focus is given to the control with DLGC_HASSETSEL style from // keyboard its contents should be entirely selected: this is what // ::IsDialogMessage() does and so we should do it as well to provide the @@ -489,6 +567,11 @@ void wxWindowMSW::SetFocusFromKbd() { ::SendMessage(GetHwnd(), EM_SETSEL, 0, -1); } + + // do this after (maybe) setting the selection as like this when + // wxEVT_SET_FOCUS handler is called, the selection would have been already + // set correctly -- this may be important + wxWindowBase::SetFocusFromKbd(); } // Get the window with the focus @@ -506,7 +589,7 @@ wxWindow *wxWindowBase::FindFocus() bool wxWindowMSW::Enable(bool enable) { if ( !wxWindowBase::Enable(enable) ) - return FALSE; + return false; HWND hWnd = GetHwnd(); if ( hWnd ) @@ -516,13 +599,13 @@ bool wxWindowMSW::Enable(bool enable) // showing a modal dialog would result in total greying out (and ungreying // out later) of everything which would be really ugly if ( IsTopLevel() ) - return TRUE; + return true; // when the parent is disabled, all of its children should be disabled as // well but when it is enabled back, only those of the children which // hadn't been already disabled in the beginning should be enabled again, // so we have to keep the list of those children - for ( wxWindowList::Node *node = GetChildren().GetFirst(); + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() ) { @@ -565,24 +648,24 @@ 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; ::ShowWindow(hWnd, cshow); - if ( show ) + if ( show && IsTopLevel() ) { wxBringWindowToTop(hWnd); } - return TRUE; + return true; } // Raise the window to the top of the Z order @@ -636,7 +719,7 @@ bool wxWindowMSW::SetFont(const wxFont& font) if ( !wxWindowBase::SetFont(font) ) { // nothing to do - return FALSE; + return false; } HWND hWnd = GetHwnd(); @@ -649,14 +732,14 @@ bool wxWindowMSW::SetFont(const wxFont& font) ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0)); } - return TRUE; + return true; } bool wxWindowMSW::SetCursor(const wxCursor& cursor) { if ( !wxWindowBase::SetCursor(cursor) ) { // no change - return FALSE; + return false; } if ( m_cursor.Ok() ) @@ -673,7 +756,7 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor) ::SetCursor(GetHcursorOf(m_cursor)); } - return TRUE; + return true; } void wxWindowMSW::WarpPointer (int x, int y) @@ -686,201 +769,75 @@ void wxWindowMSW::WarpPointer (int x, int y) } } -#if WXWIN_COMPATIBILITY -void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const -{ -} -#endif // WXWIN_COMPATIBILITY - // --------------------------------------------------------------------------- // scrolling stuff // --------------------------------------------------------------------------- -#if WXWIN_COMPATIBILITY -void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh) +// convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT +static inline int wxDirToWinStyle(int orient) { -#if defined(__WIN95__) - - 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); - } - - SCROLLINFO info; - int dir; - - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - } else { - dir = SB_VERT; - } - - info.cbSize = sizeof(SCROLLINFO); - info.nPage = pageSize; // Have to set this, or scrollbar goes awry - info.nMin = 0; - info.nMax = range1; - info.nPos = 0; - info.fMask = SIF_RANGE | SIF_PAGE; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollRange(hWnd, wOrient, 0, range, refresh); -#endif -} - -void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh) -{ -#if defined(__WIN95__) - SCROLLINFO info; - int dir; - - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - m_xThumbSize = page; - } else { - dir = SB_VERT; - m_yThumbSize = page; - } - - info.cbSize = sizeof(SCROLLINFO); - info.nPage = page; - info.nMin = 0; - info.fMask = SIF_PAGE; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else - if ( orient == wxHORIZONTAL ) - m_xThumbSize = page; - else - m_yThumbSize = page; -#endif -} - -int wxWindowMSW::OldGetScrollRange(int orient) const -{ - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - -#if __WATCOMC__ && defined(__WINDOWS_386__) - short minPos, maxPos; -#else - int minPos, maxPos; -#endif - HWND hWnd = GetHwnd(); - if ( hWnd ) - { - ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos); -#if defined(__WIN95__) - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = GetScrollPage(orient); - if ( pageSize > 1 ) - { - maxPos -= (pageSize - 1); - } -#endif - return maxPos; - } - else - return 0; + return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT; } -int wxWindowMSW::GetScrollPage(int orient) const -{ - if ( orient == wxHORIZONTAL ) - return m_xThumbSize; - else - return m_yThumbSize; -} - -#endif // WXWIN_COMPATIBILITY - inline int GetScrollPosition(HWND hWnd, int wOrient) { #ifdef __WXMICROWIN__ return ::GetScrollPosWX(hWnd, wOrient); #else - return ::GetScrollPos(hWnd, wOrient); + WinStruct scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + scrollInfo.fMask = SIF_POS; + if ( !::GetScrollInfo(hWnd, + wOrient, + &scrollInfo) ) + { + // Not neccessarily an error, if there are no scrollbars yet. + // wxLogLastError(_T("GetScrollInfo")); + } + return scrollInfo.nPos; +// return ::GetScrollPos(hWnd, wOrient); #endif } int wxWindowMSW::GetScrollPos(int orient) const { - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - HWND hWnd = GetHwnd(); wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") ); - return GetScrollPosition(hWnd, wOrient); + return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT); } // This now returns the whole range, not just the number // of positions that we can scroll. int wxWindowMSW::GetScrollRange(int orient) const { - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - -#if __WATCOMC__ && defined(__WINDOWS_386__) - short minPos, maxPos; -#else - int minPos, maxPos; -#endif + int maxPos; HWND hWnd = GetHwnd(); - if ( hWnd ) - { - ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos); -#if defined(__WIN95__) - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = GetScrollThumb(orient); - if ( pageSize > 1 ) - { - maxPos -= (pageSize - 1); - } - // October 10th: new range concept. - maxPos += pageSize; + if ( !hWnd ) + return 0; +#if 0 + ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &minPos, &maxPos); #endif - - return maxPos; + WinStruct scrollInfo; + scrollInfo.fMask = SIF_RANGE; + if ( !::GetScrollInfo(hWnd, + orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &scrollInfo) ) + { + // Most of the time this is not really an error, since the return + // value can also be zero when there is no scrollbar yet. + // wxLogLastError(_T("GetScrollInfo")); } - else - return 0; + maxPos = scrollInfo.nMax; + + // undo "range - 1" done in SetScrollbar() + return maxPos + 1; } int wxWindowMSW::GetScrollThumb(int orient) const { - if ( orient == wxHORIZONTAL ) - return m_xThumbSize; - else - return m_yThumbSize; + return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize; } void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh) @@ -888,77 +845,48 @@ void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh) HWND hWnd = GetHwnd(); wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") ); - int dir = orient == wxHORIZONTAL ? SB_HORZ : SB_VERT; - -#if defined(__WIN95__) - SCROLLINFO info; - info.cbSize = sizeof(SCROLLINFO); + WinStruct info; info.nPage = 0; info.nMin = 0; info.nPos = pos; info.fMask = SIF_POS; - - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else // !__WIN95__ - ::SetScrollPos(hWnd, dir, pos, refresh); -#endif // __WIN95__/!__WIN95__ -} - -// New function that will replace some of the above. -void wxWindowMSW::SetScrollbar(int orient, int pos, int thumbVisible, - int range, bool refresh) -{ -#if defined(__WIN95__) - int oldRange = range - thumbVisible; - - int range1 = oldRange; - - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = thumbVisible; - if ( pageSize > 1 && range > 0) + if ( HasFlag(wxALWAYS_SHOW_SB) ) { - range1 += (pageSize - 1); + // disable scrollbar instead of removing it then + info.fMask |= SIF_DISABLENOSCROLL; } - SCROLLINFO info; - int dir; - - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - } else { - dir = SB_VERT; - } + ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &info, refresh); +} - info.cbSize = sizeof(SCROLLINFO); - info.nPage = pageSize; // Have to set this, or scrollbar goes awry - info.nMin = 0; - info.nMax = range1; +// New function that will replace some of the above. +void wxWindowMSW::SetScrollbar(int orient, + int pos, + int pageSize, + int range, + bool refresh) +{ + WinStruct info; + info.nPage = pageSize; + info.nMin = 0; // range is nMax - nMin + 1 + info.nMax = range - 1; // as both nMax and nMax are inclusive info.nPos = pos; info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; + if ( HasFlag(wxALWAYS_SHOW_SB) ) + { + // disable scrollbar instead of removing it then + info.fMask |= SIF_DISABLENOSCROLL; + } HWND hWnd = GetHwnd(); if ( hWnd ) { - ::SetScrollRange(hWnd, wOrient, 0, range, FALSE); - ::SetScrollPos(hWnd, wOrient, pos, refresh); - } -#endif - if ( orient == wxHORIZONTAL ) { - m_xThumbSize = thumbVisible; - } else { - m_yThumbSize = thumbVisible; + ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &info, refresh); } + + *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize; } void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect) @@ -978,7 +906,12 @@ void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect) pr = NULL; } +#ifdef __WXWINCE__ + // FIXME: is this the exact equivalent of the line below? + ::ScrollWindowEx(GetHwnd(), dx, dy, pr, pr, 0, 0, SW_ERASE|SW_INVALIDATE); +#else ::ScrollWindow(GetHwnd(), dx, dy, pr, pr); +#endif } static bool ScrollVertically(HWND hwnd, int kind, int count) @@ -1034,19 +967,19 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd) wxAssociateWinWithHandle(hwnd, this); - m_oldWndProc = (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC); + m_oldWndProc = (WXFARPROC)wxGetWindowProc((HWND)hWnd); // we don't need to subclass the window of our own class (in the Windows // sense of the word) - if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) ) + if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) ) { - ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) wxWndProc); + wxSetWindowProc(hwnd, wxWndProc); } else { // don't bother restoring it neither: this also makes it easy to - // implement IsOfStandardClass() method which returns TRUE for the - // standard controls and FALSE for the wxWindows own windows as it can + // implement IsOfStandardClass() method which returns true for the + // standard controls and false for the wxWindows own windows as it can // simply check m_oldWndProc m_oldWndProc = NULL; } @@ -1068,7 +1001,7 @@ void wxWindowMSW::UnsubclassWin() { if ( !wxCheckWindowWndProc((WXHWND)hwnd, m_oldWndProc) ) { - ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) m_oldWndProc); + wxSetWindowProc(hwnd, (WNDPROC)m_oldWndProc); } m_oldWndProc = NULL; @@ -1084,15 +1017,38 @@ bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc) // unicows.dll, we can override unicows hooks by setting // Unicows_{Set,Get}WindowLong and Unicows_RegisterClass to our own // versions that keep track of fake<->real wnd proc mapping. + + // On WinCE (at least), the wndproc comparison doesn't work, + // so have to use something like this. +#ifdef __WXWINCE__ + extern const wxChar *wxCanvasClassName; + extern const wxChar *wxCanvasClassNameNR; + extern const wxChar *wxMDIFrameClassName; + extern const wxChar *wxMDIFrameClassNameNoRedraw; + extern const wxChar *wxMDIChildFrameClassName; + extern const wxChar *wxMDIChildFrameClassNameNoRedraw; + wxString str(wxGetWindowClass(hWnd)); + if (str == wxCanvasClassName || + str == wxCanvasClassNameNR || + str == wxMDIFrameClassName || + str == wxMDIFrameClassNameNoRedraw || + str == wxMDIChildFrameClassName || + str == wxMDIChildFrameClassNameNoRedraw || + str == _T("wxTLWHiddenParent")) + return true; // Effectively means don't subclass + else + return false; +#else WNDCLASS cls; if ( !::GetClassInfo(wxGetInstance(), wxGetWindowClass(hWnd), &cls) ) { wxLogLastError(_T("GetClassInfo")); - return FALSE; + return false; } return wndProc == (WXFARPROC)cls.lpfnWndProc; +#endif } // ---------------------------------------------------------------------------- @@ -1156,7 +1112,7 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const { // translate the style - WXDWORD style = WS_CHILD; + WXDWORD style = WS_CHILD | WS_VISIBLE; if ( flags & wxCLIP_CHILDREN ) style |= WS_CLIPCHILDREN; @@ -1164,40 +1120,37 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const if ( flags & wxCLIP_SIBLINGS ) style |= WS_CLIPSIBLINGS; - wxBorder border = (wxBorder)(flags & wxBORDER_MASK); - - // Check if we want to automatically give it a sunken style. - // Note than because 'sunken' actually maps to WS_EX_CLIENTEDGE, which - // is a more neutral term, we don't necessarily get a sunken effect in - // Windows XP. Instead we get the appropriate style for the theme. + if ( flags & wxVSCROLL ) + style |= WS_VSCROLL; - if (border == wxBORDER_DEFAULT && wxTheApp->GetAuto3D() && GetParent() && - ((GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS)) - { - border = (wxBorder)((flags & wxBORDER_MASK) | wxBORDER_SUNKEN); - } - - // Only give it WS_BORDER for wxBORDER_SIMPLE - if (border & wxBORDER_SIMPLE) + if ( flags & wxHSCROLL ) + style |= WS_HSCROLL; + + const wxBorder border = GetBorder(flags); + + // WS_BORDER is only required for wxBORDER_SIMPLE + if ( border == wxBORDER_SIMPLE ) style |= WS_BORDER; - + // now deal with ext style if the caller wants it if ( exstyle ) { *exstyle = 0; +#ifndef __WXWINCE__ if ( flags & wxTRANSPARENT_WINDOW ) *exstyle |= WS_EX_TRANSPARENT; +#endif switch ( border ) { default: + case wxBORDER_DEFAULT: wxFAIL_MSG( _T("unknown border style") ); // fall through case wxBORDER_NONE: case wxBORDER_SIMPLE: - case wxBORDER_DEFAULT: break; case wxBORDER_STATIC: @@ -1205,7 +1158,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const break; case wxBORDER_RAISED: - *exstyle |= WS_EX_WINDOWEDGE; + *exstyle |= WS_EX_DLGMODALFRAME; break; case wxBORDER_SUNKEN: @@ -1219,7 +1172,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const } // wxUniv doesn't use Windows dialog navigation functions at all -#ifndef __WXUNIVERSAL__ +#if !defined(__WXUNIVERSAL__) && !defined(__WXWINCE__) // to make the dialog navigation work with the nested panels we must // use this style (top level windows such as dialogs don't need it) if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() ) @@ -1232,37 +1185,6 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const return style; } -#if WXWIN_COMPATIBILITY -// If nothing defined for this, try the parent. -// E.g. we may be a button loaded from a resource, with no callback function -// defined. -void wxWindowMSW::OnCommand(wxWindow& win, wxCommandEvent& event) -{ - if ( GetEventHandler()->ProcessEvent(event) ) - return; - if ( m_parent ) - m_parent->GetEventHandler()->OnCommand(win, event); -} -#endif // WXWIN_COMPATIBILITY_2 - -#if WXWIN_COMPATIBILITY -wxObject* wxWindowMSW::GetChild(int number) const -{ - // Return a pointer to the Nth object in the Panel - wxNode *node = GetChildren().First(); - int n = number; - while (node && n--) - node = node->Next(); - if ( node ) - { - wxObject *obj = (wxObject *)node->Data(); - return(obj); - } - else - return NULL; -} -#endif // WXWIN_COMPATIBILITY - // Setup background and foreground colours correctly void wxWindowMSW::SetupColours() { @@ -1285,7 +1207,7 @@ bool wxWindowMSW::IsMouseInWindow() const return hwnd != NULL; } -void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event)) +void wxWindowMSW::OnInternalIdle() { // Check if we need to send a LEAVE event if ( m_mouseInWindow ) @@ -1295,10 +1217,10 @@ void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event)) 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 OnIdle function is called, so 'state' + // changed by the time the OnInternalIdle function is called, so 'state' // may be meaningless. int state = 0; if ( wxIsShiftDown() ) @@ -1331,29 +1253,29 @@ void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event)) } } - UpdateWindowUI(); + if (wxUpdateUIEvent::CanUpdate(this)) + UpdateWindowUI(wxUPDATE_UI_FROMIDLE); } // Set this window to be the child of 'parent'. 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) @@ -1365,16 +1287,24 @@ static inline void SendSetRedraw(HWND hwnd, bool on) void wxWindowMSW::Freeze() { - SendSetRedraw(GetHwnd(), FALSE); + if ( !m_frozenness++ ) + { + SendSetRedraw(GetHwnd(), false); + } } void wxWindowMSW::Thaw() { - SendSetRedraw(GetHwnd(), TRUE); + wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") ); - // 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) @@ -1404,7 +1334,7 @@ void wxWindowMSW::Update() wxLogLastError(_T("UpdateWindow")); } -#if defined(__WIN32__) && !defined(__WXMICROWIN__) +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // just calling UpdateWindow() is not enough, what we did in our WM_PAINT // handler needs to be really drawn right now (void)::GdiFlush(); @@ -1434,9 +1364,11 @@ void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget) // DragAcceptFiles in parallel with SetDropTarget. void wxWindowMSW::DragAcceptFiles(bool accept) { +#if !defined(__WXWINCE__) HWND hWnd = GetHwnd(); if ( hWnd ) ::DragAcceptFiles(hWnd, (BOOL)accept); +#endif } // ---------------------------------------------------------------------------- @@ -1759,48 +1691,6 @@ void wxWindowMSW::GetTextExtent(const wxString& string, *externalLeading = tm.tmExternalLeading; } -#if wxUSE_CARET && WXWIN_COMPATIBILITY -// --------------------------------------------------------------------------- -// Caret manipulation -// --------------------------------------------------------------------------- - -void wxWindowMSW::CreateCaret(int w, int h) -{ - SetCaret(new wxCaret(this, w, h)); -} - -void wxWindowMSW::CreateCaret(const wxBitmap *WXUNUSED(bitmap)) -{ - wxFAIL_MSG("not implemented"); -} - -void wxWindowMSW::ShowCaret(bool show) -{ - wxCHECK_RET( m_caret, "no caret to show" ); - - m_caret->Show(show); -} - -void wxWindowMSW::DestroyCaret() -{ - SetCaret(NULL); -} - -void wxWindowMSW::SetCaretPos(int x, int y) -{ - wxCHECK_RET( m_caret, "no caret to move" ); - - m_caret->Move(x, y); -} - -void wxWindowMSW::GetCaretPos(int *x, int *y) const -{ - wxCHECK_RET( m_caret, "no caret to get position of" ); - - m_caret->GetPosition(x, y); -} -#endif // wxUSE_CARET - // --------------------------------------------------------------------------- // popup menu // --------------------------------------------------------------------------- @@ -1817,15 +1707,21 @@ static void wxYieldForCommandsOnly() // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't // want to process it here) MSG msg; - while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE) - && msg.message != WM_QUIT ) + while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE) ) { - wxTheApp->DoMessage((WXMSG *)&msg); - } + if ( msg.message == WM_QUIT ) + { + // if we retrieved a WM_QUIT, insert back into the message queue. + ::PostQuitMessage(0); + break; + } - // If we retrieved a WM_QUIT, insert back into the message queue. - if (msg.message == WM_QUIT) - ::PostQuitMessage(0); + // luckily (as we don't have access to wxEventLoopImpl method from here + // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it + // immediately + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } } bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) @@ -1840,7 +1736,11 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) point.y = y; ::ClientToScreen(hWnd, &point); wxCurrentPopupMenu = menu; - ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL); + UINT flags = 0; +#if !defined(__WXWINCE__) + flags = TPM_RIGHTBUTTON; +#endif + ::TrackPopupMenu(hMenu, flags, point.x, point.y, 0, hWnd, NULL); // we need to do it righ now as otherwise the events are never going to be // sent to wxCurrentPopupMenu from HandleCommand() @@ -1855,7 +1755,7 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) menu->SetInvokingWindow(NULL); - return TRUE; + return true; } #endif // wxUSE_MENUS_NATIVE @@ -1864,14 +1764,10 @@ 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 ) -#ifdef __DIGITALMARS__ - return ::CallWindowProc( (FARPROC) m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam); -#else return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam); -#endif else return ::DefWindowProc(GetHwnd(), nMsg, wParam, lParam); } @@ -1910,19 +1806,16 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } } - bool bForward = TRUE, - bWindowChange = FALSE; + bool bForward = true, + bWindowChange = false; // should we process this message specially? - bool bProcess = TRUE; + bool bProcess = true; switch ( msg->wParam ) { case VK_TAB: - // assume that nobody wants Shift-TAB for himself - if we - // don't do it there is no easy way for a control to grab - // TABs but still let Shift-TAB work as navugation key - if ( (lDlgCode & DLGC_WANTTAB) && !bShiftDown ) { - bProcess = FALSE; + if ( lDlgCode & DLGC_WANTTAB ) { + bProcess = false; } else { // Ctrl-Tab cycles thru notebook pages @@ -1934,15 +1827,34 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) case VK_UP: case VK_LEFT: if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown ) - bProcess = FALSE; + bProcess = false; else - bForward = FALSE; + bForward = false; break; case VK_DOWN: case VK_RIGHT: if ( (lDlgCode & DLGC_WANTARROWS) || bCtrlDown ) - bProcess = FALSE; + bProcess = false; + break; + + case VK_ESCAPE: + { +#if wxUSE_BUTTON + wxButton *btn = wxDynamicCast(FindWindow(wxID_CANCEL), + wxButton); + if ( btn && btn->IsEnabled() ) + { + // if we do have a cancel button, do press it + btn->MSWCommand(BN_CLICKED, 0 /* unused */); + + // we consumed the message + return true; + } +#endif // wxUSE_BUTTON + + bProcess = false; + } break; case VK_RETURN: @@ -1952,7 +1864,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // control wants to process Enter itself, don't // call IsDialogMessage() which would interpret // it - return FALSE; + return false; } else if ( lDlgCode & DLGC_BUTTON ) { @@ -1968,7 +1880,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) btn->MSWCommand(BN_CLICKED, 0 /* unused */); } - bProcess = FALSE; + bProcess = false; } // FIXME: this should be handled by // wxNavigationKeyEvent handler and not here!! @@ -1982,7 +1894,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // if we do have a default button, do press it btn->MSWCommand(BN_CLICKED, 0 /* unused */); - return TRUE; + return true; } else // no default button { @@ -1995,13 +1907,13 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // need it for itself and don't let // ::IsDialogMessage() have it as it can // eat the Enter events sometimes - return FALSE; + return false; } else if (!IsTopLevel()) { // if not a top level window, let parent // handle it - return FALSE; + return false; } //else: treat Enter as TAB: pass to the next // control as this is the best thing to do @@ -2012,7 +1924,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) break; default: - bProcess = FALSE; + bProcess = false; } if ( bProcess ) @@ -2024,7 +1936,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( GetEventHandler()->ProcessEvent(event) ) { - return TRUE; + return true; } } } @@ -2058,45 +1970,89 @@ 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 if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE ) { - // ::IsDialogMessage() can enter in an infinite loop when the - // currently focused window is disabled or hidden and its parent - // has WS_EX_CONTROLPARENT style, so don't call it in this case - bool canSafelyCallIsDlgMsg = TRUE; + // ::IsDialogMessage() is broken and may sometimes hang the + // application by going into an infinite loop, so we try to detect + // [some of] the situatations when this may happen and not call it + // then + + // assume we can call it by default + bool canSafelyCallIsDlgMsg = true; HWND hwndFocus = ::GetFocus(); - while ( hwndFocus ) + + // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter + // an infinite loop, because it will recursively check the child + // windows but not the window itself and so if none of the children + // accepts focus it loops forever (as it only stops when it gets + // back to the window it started from) + // + // while it is very unusual that a window with WS_EX_CONTROLPARENT + // style has the focus, it can happen. One such possibility is if + // all windows are either toplevel, wxDialog, wxPanel or static + // controls and no window can actually accept keyboard input. +#if !defined(__WXWINCE__) + if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT ) { - if ( !::IsWindowEnabled(hwndFocus) || - !::IsWindowVisible(hwndFocus) ) + // passimistic by default + canSafelyCallIsDlgMsg = false; + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) { - // it would enter an infinite loop if we do this! - canSafelyCallIsDlgMsg = FALSE; + wxWindow * const win = node->GetData(); + if ( win->AcceptsFocus() && + !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) & + WS_EX_CONTROLPARENT) ) + { + // it shouldn't hang... + canSafelyCallIsDlgMsg = true; - break; + break; + } } + } +#endif // !__WXWINCE__ - if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) ) + if ( canSafelyCallIsDlgMsg ) + { + // ::IsDialogMessage() can enter in an infinite loop when the + // currently focused window is disabled or hidden and its + // parent has WS_EX_CONTROLPARENT style, so don't call it in + // this case + while ( hwndFocus ) { - // it's a top level window, don't go further -- e.g. even - // if the parent of a dialog is disabled, this doesn't - // break navigation inside the dialog - break; - } + if ( !::IsWindowEnabled(hwndFocus) || + !::IsWindowVisible(hwndFocus) ) + { + // it would enter an infinite loop if we do this! + canSafelyCallIsDlgMsg = false; + + break; + } + + if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) ) + { + // it's a top level window, don't go further -- e.g. even + // if the parent of a dialog is disabled, this doesn't + // break navigation inside the dialog + break; + } - hwndFocus = ::GetParent(hwndFocus); + hwndFocus = ::GetParent(hwndFocus); + } } + // let IsDialogMessage() have the message if it's safe to call it if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) ) { // IsDialogMessage() did something... - return TRUE; + return true; } } } @@ -2112,7 +2068,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } #endif // wxUSE_TOOLTIPS - return FALSE; + return false; } bool wxWindowMSW::MSWTranslateMessage(WXMSG* pMsg) @@ -2121,22 +2077,20 @@ 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; } // --------------------------------------------------------------------------- -// message params unpackers (different for Win16 and Win32) +// message params unpackers // --------------------------------------------------------------------------- -#ifdef __WIN32__ - void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, WORD *id, WXHWND *hwnd, WORD *cmd) { @@ -2164,65 +2118,21 @@ void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd) { -#ifndef __WXMICROWIN__ - *nCtlColor = CTLCOLOR_BTN; - *hwnd = (WXHWND)lParam; - *hdc = (WXHDC)wParam; -#endif -} - -void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, - WXWORD *item, WXWORD *flags, WXHMENU *hmenu) -{ - *item = (WXWORD)wParam; - *flags = HIWORD(wParam); - *hmenu = (WXHMENU)lParam; -} - -#else // Win16 - -void wxWindowMSW::UnpackCommand(WXWPARAM wParam, WXLPARAM lParam, - WXWORD *id, WXHWND *hwnd, WXWORD *cmd) -{ - *id = (WXWORD)wParam; - *hwnd = (WXHWND)LOWORD(lParam); - *cmd = HIWORD(lParam); -} - -void wxWindowMSW::UnpackActivate(WXWPARAM wParam, WXLPARAM lParam, - WXWORD *state, WXWORD *minimized, WXHWND *hwnd) -{ - *state = (WXWORD)wParam; - *minimized = LOWORD(lParam); - *hwnd = (WXHWND)HIWORD(lParam); -} - -void wxWindowMSW::UnpackScroll(WXWPARAM wParam, WXLPARAM lParam, - WXWORD *code, WXWORD *pos, WXHWND *hwnd) -{ - *code = (WXWORD)wParam; - *pos = LOWORD(lParam); - *hwnd = (WXHWND)HIWORD(lParam); -} - -void wxWindowMSW::UnpackCtlColor(WXWPARAM wParam, WXLPARAM lParam, - WXWORD *nCtlColor, WXHDC *hdc, WXHWND *hwnd) -{ - *hwnd = (WXHWND)LOWORD(lParam); - *nCtlColor = (int)HIWORD(lParam); +#ifndef __WXMICROWIN__ + *nCtlColor = CTLCOLOR_BTN; + *hwnd = (WXHWND)lParam; *hdc = (WXHDC)wParam; +#endif } void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, WXWORD *item, WXWORD *flags, WXHMENU *hmenu) { *item = (WXWORD)wParam; - *flags = LOWORD(lParam); - *hmenu = (WXHMENU)HIWORD(lParam); + *flags = HIWORD(wParam); + *hmenu = (WXHMENU)lParam; } -#endif // Win32/16 - // --------------------------------------------------------------------------- // Main wxWindows window proc and the window proc for wxWindow // --------------------------------------------------------------------------- @@ -2248,10 +2158,9 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w { // trace all messages - useful for the debugging #ifdef __WXDEBUG__ -#if wxUSE_LOG - wxLogTrace(wxTraceMessages, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"), - wxGetMessageName(message), (long) wParam, lParam); -#endif // wxUSE_LOG + wxLogTrace(wxTraceMessages, + wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"), + wxGetMessageName(message), (long)hWnd, (long)wParam, lParam); #endif // __WXDEBUG__ wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd); @@ -2276,16 +2185,16 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w return rc; } -long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) { // did we process the message? - bool processed = FALSE; + bool processed = false; // the return value union { bool allow; - long result; + WXLRESULT result; WXHICON hIcon; WXHBRUSH hBrush; } rc; @@ -2308,7 +2217,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam break; case WM_DESTROY: - // never set processed to TRUE and *always* pass WM_DESTROY to + // never set processed to true and *always* pass WM_DESTROY to // DefWindowProc() as Windows may do some internal cleanup when // processing it and failing to pass the message along may cause // memory and resource leaks! @@ -2319,6 +2228,26 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; +#if !defined(__WXWINCE__) + case WM_MOVING: + { + LPRECT pRect = (LPRECT)lParam; + wxRect rc; + rc.SetLeft(pRect->left); + rc.SetTop(pRect->top); + rc.SetRight(pRect->right); + rc.SetBottom(pRect->bottom); + processed = HandleMoving(rc); + if (processed) { + pRect->left = rc.GetLeft(); + pRect->top = rc.GetTop(); + pRect->right = rc.GetRight(); + pRect->bottom = rc.GetBottom(); + } + } + break; +#endif + case WM_SIZE: switch ( wParam ) { @@ -2347,7 +2276,27 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; -#ifndef __WXMICROWIN__ +#if !defined(__WXWINCE__) + case WM_SIZING: + { + LPRECT pRect = (LPRECT)lParam; + wxRect rc; + rc.SetLeft(pRect->left); + rc.SetTop(pRect->top); + rc.SetRight(pRect->right); + rc.SetBottom(pRect->bottom); + processed = HandleSizing(rc); + if (processed) { + pRect->left = rc.GetLeft(); + pRect->top = rc.GetTop(); + pRect->right = rc.GetRight(); + pRect->bottom = rc.GetBottom(); + } + } + break; +#endif + +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) case WM_ACTIVATEAPP: wxTheApp->SetActive(wParam != 0, FindFocus()); break; @@ -2372,20 +2321,47 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam break; case WM_PAINT: - processed = HandlePaint(); + { + if ( wParam ) + { + // cast to wxWindow is needed for wxUniv + wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam); + processed = HandlePaint(); + } + else + { + processed = HandlePaint(); + } + break; + } + +#ifndef __WXWINCE__ + case WM_PRINT: + { + // Don't call the wx handlers in this case + if ( wxIsKindOf(this, wxListCtrl) ) + break; + + if ( lParam & PRF_ERASEBKGND ) + HandleEraseBkgnd((WXHDC)(HDC)wParam); + + wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam); + processed = HandlePaint(); + } break; +#endif case WM_CLOSE: #ifdef __WXUNIVERSAL__ // Universal uses its own wxFrame/wxDialog, so we don't receive // close events unless we have this. Close(); - processed = TRUE; + processed = true; rc.result = TRUE; #else // don't let the DefWindowProc() destroy our window - we'll do it // ourselves in ~wxWindow - processed = TRUE; + processed = true; rc.result = TRUE; #endif break; @@ -2400,6 +2376,62 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam wParam); break; + // Seems to be broken currently +#if 0 // ndef __WXWINCE__ + case WM_MOUSELEAVE: + { + wxASSERT_MSG( !m_mouseInWindow, wxT("the mouse should be in a window to generate this event!") ); + + // only process this message if the mouse is not in the window, + // This can also check for children in composite windows. + // however, this may mean the the wxEVT_LEAVE_WINDOW is never sent + // if the mouse does not enter the window from it's child before + // leaving the scope of the window. ( perhaps this can be picked + // up in the OnIdle code as before, for this special case ) + if ( /*IsComposite() && */ !IsMouseInWindow() ) + { + m_mouseInWindow = false; + + // Unfortunately no mouse state is passed with a WM_MOUSE_LEAVE + int state = 0; + if ( wxIsShiftDown() ) + state |= MK_SHIFT; + if ( wxIsCtrlDown() ) + state |= MK_CONTROL; + if ( GetKeyState( VK_LBUTTON ) ) + state |= MK_LBUTTON; + if ( GetKeyState( VK_MBUTTON ) ) + state |= MK_MBUTTON; + if ( GetKeyState( VK_RBUTTON ) ) + state |= MK_RBUTTON; + + POINT pt; + if ( !::GetCursorPos(&pt) ) + { + wxLogLastError(_T("GetCursorPos")); + } + + // we need to have client coordinates here for symmetry with + // wxEVT_ENTER_WINDOW + RECT rect = wxGetWindowRect(GetHwnd()); + pt.x -= rect.left; + pt.y -= rect.top; + + wxMouseEvent event2(wxEVT_LEAVE_WINDOW); + InitMouseEvent(event2, pt.x, pt.y, state); + + (void)GetEventHandler()->ProcessEvent(event2); + } + // always pass processed back as false, this allows the window + // manager to process the message too. This is needed to ensure + // windows XP themes work properly as the mouse moves over widgets + // like buttons. + processed = false; + } + break; +#endif + // __WXWINCE__ + #if wxUSE_MOUSEWHEEL case WM_MOUSEWHEEL: processed = HandleMouseWheel(wParam, lParam); @@ -2425,7 +2457,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam { if (!win->IsEnabled()) { - processed = TRUE; + processed = true; break; } @@ -2503,13 +2535,24 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; -#ifdef __WIN95__ case WM_NOTIFY: processed = HandleNotify((int)wParam, lParam, &rc.result); break; -#endif // Win95 - // for these messages we must return TRUE if process the message + // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU, + // otherwise DefWindowProc() does it perfectly fine for us, but MSLU + // apparently doesn't always behave properly and needs some help +#if wxUSE_UNICODE_MSLU && defined(NF_QUERY) + case WM_NOTIFYFORMAT: + if ( lParam == NF_QUERY ) + { + processed = true; + rc.result = NFR_UNICODE; + } + break; +#endif // wxUSE_UNICODE_MSLU + + // for these messages we must return true if process the message #ifdef WM_DRAWITEM case WM_DRAWITEM: case WM_MEASUREITEM: @@ -2546,7 +2589,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam DLGC_WANTALLKEYS; } - processed = TRUE; + processed = true; } //else: get the dlg code from the DefWindowProc() break; @@ -2558,7 +2601,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam m_lastKeydownProcessed = HandleKeyDown((WORD) wParam, lParam); if ( m_lastKeydownProcessed ) { - processed = TRUE; + processed = true; } if ( !processed ) @@ -2573,7 +2616,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case VK_CAPITAL: case VK_NUMLOCK: case VK_SCROLL: - processed = TRUE; + processed = true; break; // avoid duplicate messages to OnChar for these ASCII keys: @@ -2599,10 +2642,10 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case VK_OEM_COMMA: case VK_OEM_MINUS: case VK_OEM_PERIOD: - // but set processed to FALSE, not TRUE to still pass them + // but set processed to false, not true to still pass them // to the control's default window proc - otherwise // built-in keyboard handling won't work - processed = FALSE; + processed = false; break; #ifdef VK_APPS @@ -2625,7 +2668,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } } if (message == WM_SYSKEYDOWN) // Let Windows still handle the SYSKEYs - processed = FALSE; + processed = false; break; case WM_SYSKEYUP: @@ -2654,15 +2697,21 @@ 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; +#if wxUSE_HOTKEY + case WM_HOTKEY: + processed = HandleHotKey((WORD)wParam, lParam); + break; +#endif // wxUSE_HOTKEY + case WM_HSCROLL: case WM_VSCROLL: { @@ -2679,7 +2728,6 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam // CTLCOLOR messages are sent by children to query the parent for their // colors#ifndef __WXMICROWIN__ #ifndef __WXMICROWIN__ -#ifdef __WIN32__ case WM_CTLCOLORMSGBOX: case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: @@ -2687,9 +2735,6 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case WM_CTLCOLORDLG: case WM_CTLCOLORSCROLLBAR: case WM_CTLCOLORSTATIC: -#else // Win16 - case WM_CTLCOLOR: -#endif // Win32/16 { WXWORD nCtlColor; WXHDC hdc; @@ -2712,9 +2757,11 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = HandleSysColorChange(); break; +#if !defined(__WXWINCE__) case WM_DISPLAYCHANGE: processed = HandleDisplayChange(); break; +#endif case WM_PALETTECHANGED: processed = HandlePaletteChanged((WXHWND) (HWND) wParam); @@ -2737,9 +2784,11 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; +#if !defined(__WXWINCE__) case WM_DROPFILES: processed = HandleDropFiles(wParam); break; +#endif case WM_INITDIALOG: processed = HandleInitDialog((WXHWND)(HWND)wParam); @@ -2751,6 +2800,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; +#if !defined(__WXWINCE__) case WM_QUERYENDSESSION: processed = HandleQueryEndSession(lParam, &rc.allow); break; @@ -2762,6 +2812,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case WM_GETMINMAXINFO: processed = HandleGetMinMaxInfo((MINMAXINFO*)lParam); break; +#endif case WM_SETCURSOR: processed = HandleSetCursor((WXHWND)(HWND)wParam, @@ -2783,7 +2834,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam //WPARAM dwFlags = (WPARAM) (DWORD) wParam; LPARAM dwObjId = (LPARAM) (DWORD) lParam; - if (dwObjId == OBJID_CLIENT && GetOrCreateAccessible()) + if (dwObjId == (LPARAM)OBJID_CLIENT && GetOrCreateAccessible()) { return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible()); } @@ -2791,21 +2842,29 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } #endif -#if defined(__WIN32__) && defined(WM_HELP) +#if defined(WM_HELP) case WM_HELP: { + // HELPINFO doesn't seem to be supported on WinCE. +#ifndef __WXWINCE__ HELPINFO* info = (HELPINFO*) lParam; // Don't yet process menu help events, just windows if (info->iContextType == HELPINFO_WINDOW) { +#endif wxWindowMSW* subjectOfHelp = this; - bool eventProcessed = FALSE; + bool eventProcessed = false; while (subjectOfHelp && !eventProcessed) { wxHelpEvent helpEvent(wxEVT_HELP, subjectOfHelp->GetId(), - wxPoint(info->MousePos.x, - info->MousePos.y) ); +#ifdef __WXWINCE__ + wxPoint(0, 0) +#else + wxPoint(info->MousePos.x, info->MousePos.y) +#endif + ); + helpEvent.SetEventObject(this); eventProcessed = GetEventHandler()->ProcessEvent(helpEvent); @@ -2816,6 +2875,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } processed = eventProcessed; +#ifndef __WXWINCE__ } else if (info->iContextType == HELPINFO_MENUITEM) { @@ -2824,10 +2884,13 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = GetEventHandler()->ProcessEvent(helpEvent); } - //else: processed is already FALSE + //else: processed is already false +#endif } break; +#endif +#if !defined(__WXWINCE__) case WM_CONTEXTMENU: { // we don't convert from screen to client coordinates as @@ -2835,9 +2898,23 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt); - processed = GetEventHandler()->ProcessEvent(evtCtx); + + // we could have got an event from our child, reflect it back + // to it if this is the case + wxWindowMSW *win = NULL; + if ( (WXHWND)wParam != m_hWnd ) + { + win = FindItemByHWND((WXHWND)wParam); + } + + if ( !win ) + win = this; + + evtCtx.SetEventObject(win); + processed = win->GetEventHandler()->ProcessEvent(evtCtx); } break; +#endif case WM_MENUCHAR: // we're only interested in our own menus, not MF_SYSMENU @@ -2848,20 +2925,17 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam if ( i != wxNOT_FOUND ) { rc.result = MAKELRESULT(i, MNC_EXECUTE); - processed = TRUE; + processed = true; } } break; -#endif // __WIN32__ } if ( !processed ) { #ifdef __WXDEBUG__ -#if wxUSE_LOG wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."), wxGetMessageName(message)); -#endif // wxUSE_LOG #endif // __WXDEBUG__ rc.result = MSWDefWindowProc(message, wParam, lParam); } @@ -2922,15 +2996,15 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, int& x, int& y, int& w, int& h) const { + // yes, those are just some arbitrary hardcoded numbers static const int DEFAULT_Y = 200; - static const int DEFAULT_H = 250; - bool nonDefault = FALSE; + bool nonDefault = false; if ( pos.x == -1 ) { - // if set x to CW_USEDEFAULT, y parameter is ignored anyhow so we can - // just as well set it to CW_USEDEFAULT as well + // if x is set to CW_USEDEFAULT, y parameter is ignored anyhow so we + // can just as well set it to CW_USEDEFAULT as well x = y = CW_USEDEFAULT; } @@ -2942,7 +3016,7 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, x = pos.x; y = pos.y == -1 ? DEFAULT_Y : pos.y; - nonDefault = TRUE; + nonDefault = true; } /* @@ -2961,20 +3035,33 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, this and ignore any attempts to change the window size to the size it already has - so no WM_SIZE would be sent. */ - if ( size.x == -1 ) + + + // we don't use CW_USEDEFAULT here for several reasons: + // + // 1. it results in huge frames on modern screens (1000*800 is not + // uncommon on my 1280*1024 screen) which is way too big for a half + // empty frame of most of wxWindows samples for example) + // + // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which + // the default is for whatever reason 8*8 which breaks client <-> + // window size calculations (it would be nice if it didn't, but it + // does and the simplest way to fix it seemed to change the broken + // default size anyhow) + // + // 3. there is just no advantage in doing it: with x and y it is + // possible that [future versions of] Windows position the new top + // level window in some smart way which we can't do, but we can + // guess a reasonably good size for a new window just as well + // ourselves + if ( size.x == -1 || size.y == -1) { - // as above, h is not used at all in this case anyhow - w = - h = CW_USEDEFAULT; + nonDefault = true; } - else - { - // and, again as above, we can't set the height to CW_USEDEFAULT here - w = size.x; - h = size.y == -1 ? DEFAULT_H : size.y; + w = WidthDefault(size.x); + h = HeightDefault(size.y); - nonDefault = TRUE; - } + AdjustForParentClientOrigin(x, y); return nonDefault; } @@ -3003,7 +3090,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // which is the same but without CS_[HV]REDRAW class styles so using it // ensures that the window is not fully repainted on each resize wxString className(wclass); - if ( GetWindowStyleFlag() & wxNO_FULL_REPAINT_ON_RESIZE ) + if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) ) { className += wxT("NR"); } @@ -3011,31 +3098,49 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // do create the window wxWindowCreationHook hook(this); - m_hWnd = (WXHWND)::CreateWindowEx - ( - extendedStyle, - className, - title ? title : wxT(""), - style, - x, y, w, h, - (HWND)MSWGetParent(), - (HMENU)controlId, - wxGetInstance(), - NULL // no extra data - ); + // VZ: anyonce cares to explain why is this done for CE? +#ifdef __WXWINCE__ + if (extendedStyle == 0) + { + m_hWnd = (WXHWND)::CreateWindow + ( + className, + title ? title : wxEmptyString, + style, + x, y, w, h, + (HWND)MSWGetParent(), + (HMENU)controlId, + wxGetInstance(), + NULL // no extra data + ); + } + else +#endif // __WXWINCE__ + { + m_hWnd = (WXHWND)::CreateWindowEx + ( + extendedStyle, + className, + title ? title : wxEmptyString, + style, + x, y, w, h, + (HWND)MSWGetParent(), + (HMENU)controlId, + wxGetInstance(), + NULL // no extra data + ); + } if ( !m_hWnd ) { wxLogSysError(_("Can't create window of class %s"), wclass); - return FALSE; + return false; } SubclassWin(m_hWnd); - SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); - - return TRUE; + return true; } // =========================================================================== @@ -3069,13 +3174,13 @@ bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // correct button tooltips #if 0 // try all our children - wxWindowList::Node *node = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); while ( node ) { wxWindow *child = node->GetData(); if ( child->MSWOnNotify(idCtrl, lParam, result) ) { - return TRUE; + return true; } node = node->GetNext(); @@ -3085,7 +3190,7 @@ bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // by default, handle it ourselves return MSWOnNotify(idCtrl, lParam, result); #else // __WXMICROWIN__ - return FALSE; + return false; #endif } @@ -3100,35 +3205,72 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code, // this message is supposed to be sent to Unicode programs only) -- hence // we need to handle it as well, otherwise no tooltips will be shown in // this case - - if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) || ttip.empty() ) +#ifndef __WXWINCE__ + if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) + || ttip.empty() ) { // not a tooltip message or no tooltip to show anyhow - return FALSE; + return false; } +#endif LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; + // We don't want to use the szText buffer because it has a limit of 80 + // bytes and this is not enough, especially for Unicode build where it + // limits the tooltip string length to only 40 characters + // + // The best would be, of course, to not impose any length limitations at + // all but then the buffer would have to be dynamic and someone would have + // to free it and we don't have the tooltip owner object here any more, so + // for now use our own static buffer with a higher fixed max length. + // + // Note that using a static buffer should not be a problem as only a single + // tooltip can be shown at the same time anyhow. #if !wxUSE_UNICODE - if ( code == (WXUINT) TTN_NEEDTEXTA ) - { - // we pass just the pointer as we store the string internally anyhow - ttText->lpszText = (char *)ttip.c_str(); + if ( code == (WXUINT) TTN_NEEDTEXTW ) + { + // We need to convert tooltip from multi byte to Unicode on the fly. + static wchar_t buf[513]; + + // Truncate tooltip length if needed as otherwise we might not have + // enough space for it in the buffer and MultiByteToWideChar() would + // return an error + size_t tipLength = wxMin(ttip.Len(), WXSIZEOF(buf) - 1); + + // Convert to WideChar without adding the NULL character. The NULL + // character is added afterwards (this is more efficient). + int len = ::MultiByteToWideChar + ( + CP_ACP, + 0, // no flags + ttip, + tipLength, + buf, + WXSIZEOF(buf) - 1 + ); + + if ( !len ) + { + wxLogLastError(_T("MultiByteToWideChar()")); + } + + buf[len] = L'\0'; + ttText->lpszText = (LPSTR) buf; } - else // TTN_NEEDTEXTW -#endif // !Unicode + else // TTN_NEEDTEXTA +#endif // !wxUSE_UNICODE { -#if wxUSE_UNICODE - // in Unicode mode this is just what we need - ttText->lpszText = (wxChar *)ttip.c_str(); -#else // !Unicode - MultiByteToWideChar(CP_ACP, 0, ttip, ttip.length()+1, - (wchar_t *)ttText->szText, - sizeof(ttText->szText) / sizeof(wchar_t)); -#endif // Unicode/!Unicode + // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or + // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have + // to copy the string we have into the buffer + static wxChar buf[513]; + wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1); + buf[WXSIZEOF(buf) - 1] = _T('\0'); + ttText->lpszText = buf; } - return TRUE; + return true; } #endif // wxUSE_TOOLTIPS @@ -3144,12 +3286,12 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), if ( HandleTooltipNotify(hdr->code, lParam, m_tooltip->GetTip())) { // processed - return TRUE; + return true; } } #endif // wxUSE_TOOLTIPS - return FALSE; + return false; } #endif // __WIN95__ @@ -3160,9 +3302,10 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) { +#ifndef __WXWINCE__ wxCloseEvent event(wxEVT_QUERY_END_SESSION, -1); event.SetEventObject(wxTheApp); - event.SetCanVeto(TRUE); + event.SetCanVeto(true); event.SetLoggingOff(logOff == (long)ENDSESSION_LOGOFF); bool rc = wxTheApp->ProcessEvent(event); @@ -3175,24 +3318,31 @@ bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd) } return rc; +#else + return false; +#endif } bool wxWindowMSW::HandleEndSession(bool endSession, long logOff) { +#ifndef __WXWINCE__ // do nothing if the session isn't ending if ( !endSession ) - return FALSE; + return false; // only send once if ( (this != wxTheApp->GetTopWindow()) ) - return FALSE; + return false; wxCloseEvent event(wxEVT_END_SESSION, -1); event.SetEventObject(wxTheApp); - event.SetCanVeto(FALSE); + event.SetCanVeto(false); event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) ); return wxTheApp->ProcessEvent(event); +#else + return false; +#endif } // --------------------------------------------------------------------------- @@ -3201,38 +3351,21 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff) bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate) { - // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our - // parent as well as otherwise several Win32 functions using - // GetNextDlgTabItem() to iterate over all controls such as - // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, - // all of them iterate over all the controls starting from the focus and - // stop iterating when they get back to the focus but unless all parents - // have WS_EX_CONTROLPARENT bit set, they would never get back to focus + // VZ: why is this commented out for WinCE? If it doesn't support + // WS_EX_CONTROLPARENT at all it should be somehow handled globally, + // not with multiple #ifdef's! +#ifndef __WXWINCE__ if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT ) - { - // there is no need to do anything for the top level windows - const wxWindow *parent = GetParent(); - while ( parent && !parent->IsTopLevel() ) - { - LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE); - if ( !(exStyle & WS_EX_CONTROLPARENT) ) - { - // force the parent to have this style - ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE, - exStyle | WS_EX_CONTROLPARENT); - } - - parent = parent->GetParent(); - } - } + EnsureParentHasControlParentStyle(GetParent()); +#endif // !__WXWINCE__ // TODO: should generate this event from WM_NCCREATE wxWindowCreateEvent event((wxWindow *)this); (void)GetEventHandler()->ProcessEvent(event); - *mayCreate = TRUE; + *mayCreate = true; - return TRUE; + return true; } bool wxWindowMSW::HandleDestroy() @@ -3251,7 +3384,7 @@ bool wxWindowMSW::HandleDestroy() #endif // wxUSE_DRAG_AND_DROP // WM_DESTROY handled - return TRUE; + return true; } // --------------------------------------------------------------------------- @@ -3290,7 +3423,7 @@ bool wxWindowMSW::HandleSetFocus(WXHWND hwnd) // after the control gets to process it from EN_FOCUS handler if ( wxDynamicCastThis(wxTextCtrl) ) { - return FALSE; + return false; } #endif // wxUSE_TEXTCTRL @@ -3319,7 +3452,7 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) wxTextCtrl *ctrl = wxDynamicCastThis(wxTextCtrl); if ( ctrl ) { - return FALSE; + return false; } #endif @@ -3327,7 +3460,7 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) // only cause problems if the event handler tries to access the object. if ( m_isBeingDeleted ) { - return FALSE; + return false; } wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId); @@ -3361,8 +3494,8 @@ bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) { -#if defined (__WXMICROWIN__) - return FALSE; +#if defined (__WXMICROWIN__) || defined(__WXWINCE__) + return false; #else // __WXMICROWIN__ HDROP hFilesInfo = (HDROP) wParam; @@ -3383,9 +3516,7 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) // and now get the file name ::DragQueryFile(hFilesInfo, wIndex, - files[wIndex].GetWriteBuf(len), len); - - files[wIndex].UngetWriteBuf(); + wxStringBuffer(files[wIndex], len), len); } DragFinish (hFilesInfo); @@ -3401,9 +3532,6 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) #endif } -#ifdef __DIGITALMARS__ -extern "C" HCURSOR wxGetCurrentBusyCursor(); -#endif bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), short nHitTest, @@ -3420,7 +3548,7 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), if ( nHitTest != HTCLIENT ) { - return FALSE; + return false; } HCURSOR hcursor = 0; @@ -3428,15 +3556,10 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), // first ask the user code - it may wish to set the cursor in some very // specific way (for example, depending on the current position) POINT pt; -#ifdef __WIN32__ if ( !::GetCursorPos(&pt) ) { wxLogLastError(wxT("GetCursorPos")); } -#else - // In WIN16 it doesn't return a value. - ::GetCursorPos(&pt); -#endif int x = pt.x, y = pt.y; @@ -3486,19 +3609,28 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), ::SetCursor(hcursor); // cursor set, stop here - return TRUE; + return true; } #endif // __WXMICROWIN__ // pass up the window chain - return FALSE; + return false; } // --------------------------------------------------------------------------- // owner drawn stuff // --------------------------------------------------------------------------- -bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) +#if (wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE) || \ + (wxUSE_CONTROLS && !defined(__WXUNIVERSAL__)) + #define WXUNUSED_UNLESS_ODRAWN(param) param +#else + #define WXUNUSED_UNLESS_ODRAWN(param) +#endif + +bool +wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id), + WXDRAWITEMSTRUCT * WXUNUSED_UNLESS_ODRAWN(itemStruct)) { #if wxUSE_OWNER_DRAWN @@ -3509,7 +3641,7 @@ bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) { wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData); - wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); + wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), false ); // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent // the DC from being released @@ -3528,41 +3660,59 @@ bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) } #endif // wxUSE_MENUS_NATIVE -#if wxUSE_CONTROLS - wxWindow *item = FindItem(id); - if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) +#endif // USE_OWNER_DRAWN + +#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); +#endif // USE_OWNER_DRAWN + + if ( item ) { - return ((wxControl *)item)->MSWOnDraw(itemStruct); + return item->MSWOnDraw(itemStruct); } -#endif // wxUSE_CONTROLS -#endif // USE_OWNER_DRAWN +#endif // wxUSE_CONTROLS - return FALSE; + return false; } -bool wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) +bool +wxWindowMSW::MSWOnMeasureItem(int WXUNUSED_UNLESS_ODRAWN(id), + WXMEASUREITEMSTRUCT * + WXUNUSED_UNLESS_ODRAWN(itemStruct)) { -#if wxUSE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN && wxUSE_MENUS_NATIVE // is it a menu item? MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct; if ( id == 0 && pMeasureStruct->CtlType == ODT_MENU ) { wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData); - wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); + wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), false ); - return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth, - &pMeasureStruct->itemHeight); + size_t w, h; + bool rc = pMenuItem->OnMeasureItem(&w, &h); + + pMeasureStruct->itemWidth = w; + pMeasureStruct->itemHeight = h; + + return rc; } - wxWindow *item = FindItem(id); - if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) + wxControl *item = wxDynamicCast(FindItem(id), wxControl); + if ( item ) { - return ((wxControl *)item)->MSWOnMeasure(itemStruct); + return item->MSWOnMeasure(itemStruct); } -#endif // owner-drawn menus - return FALSE; +#endif // wxUSE_OWNER_DRAWN + + return false; } // --------------------------------------------------------------------------- @@ -3578,7 +3728,7 @@ bool wxWindowMSW::HandleSysColorChange() // always let the system carry on the default processing to allow the // native controls to react to the colours update - return FALSE; + return false; } bool wxWindowMSW::HandleDisplayChange() @@ -3600,14 +3750,18 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, #ifndef __WXMICROWIN__ WXHBRUSH hBrush = 0; +#ifdef __WXWINCE__ + if (false) +#else if ( nCtlColor == CTLCOLOR_DLG ) +#endif { hBrush = OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam); } #if wxUSE_CONTROLS else { - wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE); + wxControl *item = (wxControl *)FindItemByHWND(pWnd, true); if ( item ) hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam); } @@ -3618,7 +3772,7 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, return hBrush != 0; #else // __WXMICROWIN__ - return FALSE; + return false; #endif } @@ -3663,7 +3817,7 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange) // now check for the need to redraw if (result > 0) - InvalidateRect((HWND) hWndPalChange, NULL, TRUE); + ::InvalidateRect((HWND) hWndPalChange, NULL, TRUE); } } @@ -3724,9 +3878,9 @@ void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) if ( IsTopLevel() ) { // FIXME-MT - gs_hasStdCmap = FALSE; + gs_hasStdCmap = false; } - wxWindowList::Node *node = GetChildren().GetFirst(); + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); while ( node ) { // Only propagate to non-top-level windows because Windows already @@ -3745,16 +3899,14 @@ void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) // update the colours we use if they were not set explicitly by the user: // this must be done or OnCtlColor() would continue to use the old colours - if ( !m_hasFgCol ) + if ( !m_hasFgCol || !m_hasBgCol ) { - m_foregroundColour = wxSystemSettings:: - GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); - } + wxVisualAttributes attrs = GetDefaultAttributes(); + if ( !m_hasFgCol ) + m_foregroundColour = attrs.colFg; - if ( !m_hasBgCol ) - { - m_backgroundColour = wxSystemSettings:: - GetSystemColour(wxSYS_COLOUR_BTNFACE); + if ( !m_hasBgCol ) + m_backgroundColour = attrs.colBg; } } @@ -3765,7 +3917,7 @@ extern wxCOLORMAP *wxGetStdColourMap() if ( !gs_hasStdCmap ) { - static bool s_coloursInit = FALSE; + static bool s_coloursInit = false; if ( !s_coloursInit ) { @@ -3803,10 +3955,10 @@ extern wxCOLORMAP *wxGetStdColourMap() //s_stdColours[5] = RGB(255,000,255); // magenta } - s_coloursInit = TRUE; + s_coloursInit = true; } - gs_hasStdCmap = TRUE; + gs_hasStdCmap = true; // create the colour map #define INIT_CMAP_ENTRY(col) \ @@ -3830,7 +3982,9 @@ extern wxCOLORMAP *wxGetStdColourMap() bool wxWindowMSW::HandlePaint() { -#ifdef __WIN32__ +// if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) +// return FALSE; + HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle if ( !hRegion ) wxLogLastError(wxT("CreateRectRgn")); @@ -3838,14 +3992,6 @@ bool wxWindowMSW::HandlePaint() wxLogLastError(wxT("GetUpdateRgn")); m_updateRegion = wxRegion((WXHRGN) hRegion); -#else // Win16 - RECT updateRect; - ::GetUpdateRect(GetHwnd(), &updateRect, FALSE); - - m_updateRegion = wxRegion(updateRect.left, updateRect.top, - updateRect.right - updateRect.left, - updateRect.bottom - updateRect.top); -#endif // Win32/16 wxPaintEvent event(m_windowId); event.SetEventObject(this); @@ -3880,7 +4026,30 @@ 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; + } + + if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) + { + if (wxUxThemeEngine::Get()) + { + WXHTHEME hTheme = wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L"TAB"); + if (hTheme) + { + WXURECT rect; + ::GetClientRect((HWND) GetHWND(), (RECT*) & rect); + wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme, hdc, 10 /* TABP_BODY */, 0, &rect, &rect); + wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme); + return true; + } + } + } +#endif wxDCTemp dc(hdc); @@ -3914,11 +4083,16 @@ void wxWindowMSW::OnEraseBackground(wxEraseEvent& event) HDC hdc = (HDC)event.GetDC()->GetHDC(); +#ifndef __WXWINCE__ int mode = ::SetMapMode(hdc, MM_TEXT); +#endif ::FillRect(hdc, &rect, hBrush); ::DeleteObject(hBrush); + +#ifndef __WXWINCE__ ::SetMapMode(hdc, mode); +#endif } // --------------------------------------------------------------------------- @@ -3949,6 +4123,17 @@ bool wxWindowMSW::HandleMove(int x, int y) return GetEventHandler()->ProcessEvent(event); } +bool wxWindowMSW::HandleMoving(wxRect& rect) +{ + wxMoveEvent event(rect, m_windowId); + event.SetEventObject(this); + + bool rc = GetEventHandler()->ProcessEvent(event); + if (rc) + rect = event.GetRect(); + return rc; +} + bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT WXUNUSED(flag)) { @@ -3961,11 +4146,25 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), return GetEventHandler()->ProcessEvent(event); } +bool wxWindowMSW::HandleSizing(wxRect& rect) +{ + wxSizeEvent event(rect, m_windowId); + event.SetEventObject(this); + + bool rc = GetEventHandler()->ProcessEvent(event); + if (rc) + rect = event.GetRect(); + return rc; +} + bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) { +#ifdef __WXWINCE__ + return false; +#else MINMAXINFO *info = (MINMAXINFO *)mmInfo; - bool rc = FALSE; + bool rc = false; int minWidth = GetMinWidth(), minHeight = GetMinHeight(), @@ -3975,28 +4174,29 @@ bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) if ( minWidth != -1 ) { info->ptMinTrackSize.x = minWidth; - rc = TRUE; + rc = true; } if ( minHeight != -1 ) { info->ptMinTrackSize.y = minHeight; - rc = TRUE; + rc = true; } if ( maxWidth != -1 ) { info->ptMaxTrackSize.x = maxWidth; - rc = TRUE; + rc = true; } if ( maxHeight != -1 ) { info->ptMaxTrackSize.y = maxHeight; - rc = TRUE; + rc = true; } return rc; +#endif } // --------------------------------------------------------------------------- @@ -4060,15 +4260,16 @@ bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) // wxSpinCtrl wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control); if ( spin && spin->ProcessTextCommand(cmd, id) ) - return TRUE; + return true; } #endif // wxUSE_SPINCTRL - return FALSE; + return false; } bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam)) { +#ifndef __WXWINCE__ // 4 bits are reserved switch ( wParam & 0xFFFFFFF0 ) { @@ -4078,8 +4279,9 @@ bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam)) case SC_MINIMIZE: return HandleMinimize(); } +#endif - return FALSE; + return false; } // --------------------------------------------------------------------------- @@ -4100,9 +4302,15 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event, event.m_leftDown = (flags & MK_LBUTTON) != 0; event.m_middleDown = (flags & MK_MBUTTON) != 0; event.m_rightDown = (flags & MK_RBUTTON) != 0; - event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; + // event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; + // Returns different negative values on WinME and WinNT, + // so simply test for negative value. + event.m_altDown = ::GetKeyState(VK_MENU) < 0; + +#ifndef __WXWINCE__ + event.SetTimestamp(::GetMessageTime()); +#endif - event.SetTimestamp(s_currentMsg.time); event.m_eventObject = this; event.SetId(GetId()); @@ -4133,7 +4341,13 @@ static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) // HWND hwnd = GetHwndOf(win), hwndUnderMouse; -#ifdef __WIN32__ +#ifdef __WXWINCE__ + hwndUnderMouse = ::ChildWindowFromPoint + ( + hwnd, + pt + ); +#else hwndUnderMouse = ::ChildWindowFromPointEx ( hwnd, @@ -4142,9 +4356,9 @@ static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) // CWP_SKIPDISABLED | CWP_SKIPTRANSPARENT ); +#endif if ( !hwndUnderMouse || hwndUnderMouse == hwnd ) -#endif // __WIN32__ { // now try any child window at all hwndUnderMouse = ::ChildWindowFromPoint(hwnd, pt); @@ -4208,8 +4422,20 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) if ( !HasCapture() || IsMouseInWindow() ) { // Generate an ENTER event - m_mouseInWindow = TRUE; - + m_mouseInWindow = true; +#if _WIN32_WINNT >= 0x0400 +#ifndef __WXWINCE__ + TRACKMOUSEEVENT trackinfo; + + trackinfo.cbSize = sizeof(trackinfo); + trackinfo.dwFlags = TME_LEAVE; + trackinfo.hwndTrack = GetHwnd(); + //Use the commctrl.h _TrackMouseEvent, which will call the + // appropriate TrackMouseEvent or emulate it ( win95 ) + // else we need _WIN32_WINNT >= 0x0400 + _TrackMouseEvent(&trackinfo); +#endif +#endif wxMouseEvent event(wxEVT_ENTER_WINDOW); InitMouseEvent(event, x, y, flags); @@ -4228,7 +4454,7 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) { m_lastMouseEvent = wxEVT_MOTION; - return FALSE; + return false; } #endif // wxUSE_MOUSEEVENT_HACK @@ -4247,7 +4473,6 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam) event.m_wheelRotation = (short)HIWORD(wParam); event.m_wheelDelta = WHEEL_DELTA; -#ifdef __WIN32__ static int s_linesPerRotation = -1; if ( s_linesPerRotation == -1 ) { @@ -4261,10 +4486,6 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam) s_linesPerRotation = 3; } } -#else // Win16 - // no SystemParametersInfo() under Win16 - static const int s_linesPerRotation = 3; -#endif event.m_linesPerAction = s_linesPerRotation; return GetEventHandler()->ProcessEvent(event); @@ -4273,7 +4494,7 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam) (void) wParam; (void) lParam; - return FALSE; + return false; #endif } @@ -4299,7 +4520,9 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, event.m_keyCode = id; event.m_rawCode = (wxUint32) wParam; event.m_rawFlags = (wxUint32) lParam; - event.SetTimestamp(s_currentMsg.time); +#ifndef __WXWINCE__ + event.SetTimestamp(::GetMessageTime()); +#endif // translate the position to client coords POINT pt; @@ -4315,18 +4538,16 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, return event; } -// isASCII is TRUE only when we're called from WM_CHAR handler and not from +// isASCII is true only when we're called from WM_CHAR handler and not from // WM_KEYDOWN one bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) { - bool ctrlDown = FALSE; - int id; if ( isASCII ) { // If 1 -> 26, translate to either special keycode or just set // ctrlDown. IOW, Ctrl-C should result in keycode == 3 and - // ControlDown() == TRUE. + // ControlDown() == true. id = wParam; if ( (id > 0) && (id < 27) ) { @@ -4345,19 +4566,19 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) break; default: - ctrlDown = TRUE; + //ctrlDown = true; break; } } } else // we're called from WM_KEYDOWN { - id = wxCharCodeMSWToWX(wParam); + id = wxCharCodeMSWToWX(wParam, lParam); if ( id == 0 ) { // it's ASCII and will be processed here only when called from - // WM_CHAR (i.e. when isASCII = TRUE), don't process it now - return FALSE; + // WM_CHAR (i.e. when isASCII = true), don't process it now + return false; } } @@ -4373,7 +4594,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) (id >= 32 && id < 256) ) { event.m_controlDown = - event.m_altDown = FALSE; + event.m_altDown = false; } return GetEventHandler()->ProcessEvent(event); @@ -4381,7 +4602,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( !id ) { @@ -4394,16 +4615,16 @@ bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam)); if ( GetEventHandler()->ProcessEvent(event) ) { - return TRUE; + return true; } } - return FALSE; + return false; } bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( !id ) { @@ -4415,16 +4636,17 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) { wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam)); if ( GetEventHandler()->ProcessEvent(event) ) - return TRUE; + return true; } - return FALSE; + return false; } -#ifdef __WIN32__ - int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam) { + // FIXME: implement GetMenuItemCount for WinCE, possibly + // in terms of GetMenuItemInfo +#ifndef __WXWINCE__ const HMENU hmenu = (HMENU)lParam; MENUITEMINFO mii; @@ -4471,19 +4693,17 @@ int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam) } } } - else // failed ot get the menu text? + else // failed to get the menu text? { // it's not fatal, so don't show error, but still log // it wxLogLastError(_T("GetMenuItemInfo")); } } - +#endif return wxNOT_FOUND; } -#endif // __WIN32__ - // --------------------------------------------------------------------------- // joystick // --------------------------------------------------------------------------- @@ -4559,7 +4779,7 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) default: wxFAIL_MSG(wxT("no such joystick event")); - return FALSE; + return false; } wxJoystickEvent event(eventType, buttons, joystick, change); @@ -4568,7 +4788,7 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) return GetEventHandler()->ProcessEvent(event); #else - return FALSE; + return false; #endif } @@ -4578,8 +4798,8 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, WXWORD pos, WXHWND control) -{ - if ( control ) +{ + if ( control && control != m_hWnd ) // Prevent infinite recursion { wxWindow *child = wxFindWinFromHandle(control); if ( child ) @@ -4619,16 +4839,13 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, case SB_THUMBPOSITION: case SB_THUMBTRACK: -#ifdef __WIN32__ // under Win32, the scrollbar range and position are 32 bit integers, // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must // explicitly query the scrollbar for the correct position (this must // be done only for these two SB_ events as they are the only one // carrying the scrollbar position) { - SCROLLINFO scrollInfo; - wxZeroMemory(scrollInfo); - scrollInfo.cbSize = sizeof(SCROLLINFO); + WinStruct scrollInfo; scrollInfo.fMask = SIF_TRACKPOS; if ( !::GetScrollInfo(GetHwnd(), @@ -4636,12 +4853,12 @@ 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); } -#endif // Win32 event.m_eventType = wParam == SB_THUMBPOSITION ? wxEVT_SCROLLWIN_THUMBRELEASE @@ -4649,7 +4866,7 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, break; default: - return FALSE; + return false; } return GetEventHandler()->ProcessEvent(event); @@ -4691,7 +4908,7 @@ void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font) // Returns 0 if was a normal ASCII value, not a special key. This indicates that // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. -int wxCharCodeMSWToWX(int keySym) +int wxCharCodeMSWToWX(int keySym, WXLPARAM lParam) { int id; switch (keySym) @@ -4700,7 +4917,6 @@ int wxCharCodeMSWToWX(int keySym) case VK_BACK: id = WXK_BACK; break; case VK_TAB: id = WXK_TAB; break; case VK_CLEAR: id = WXK_CLEAR; break; - case VK_RETURN: id = WXK_RETURN; break; case VK_SHIFT: id = WXK_SHIFT; break; case VK_CONTROL: id = WXK_CONTROL; break; case VK_MENU : id = WXK_MENU; break; @@ -4782,6 +4998,13 @@ int wxCharCodeMSWToWX(int keySym) case VK_APPS: id = WXK_WINDOWS_MENU; break; #endif // VK_APPS defined + case VK_RETURN: + // the same key is sent for both the "return" key on the main + // keyboard and the numeric keypad but we want to distinguish + // between them: we do this using the "extended" bit (24) of lParam + id = lParam & (1 << 24) ? WXK_NUMPAD_ENTER : WXK_RETURN; + break; + default: id = 0; } @@ -4791,8 +5014,8 @@ int wxCharCodeMSWToWX(int keySym) int wxCharCodeWXToMSW(int id, bool *isVirtual) { - *isVirtual = TRUE; - int keySym = 0; + *isVirtual = true; + int keySym; switch (id) { case WXK_CANCEL: keySym = VK_CANCEL; break; @@ -4858,7 +5081,7 @@ int wxCharCodeWXToMSW(int id, bool *isVirtual) case WXK_SCROLL: keySym = VK_SCROLL; break; default: { - *isVirtual = FALSE; + *isVirtual = false; keySym = id; break; } @@ -4866,6 +5089,18 @@ int wxCharCodeWXToMSW(int id, bool *isVirtual) return keySym; } +bool wxGetKeyState(wxKeyCode key) +{ + bool bVirtual; + int vkey = wxCharCodeWXToMSW(key, &bVirtual); + + //there aren't WXK_ macros for non-virtual key codes + if (bVirtual == false) + return false; + + return GetKeyState(vkey) < 0; +} + wxWindow *wxGetActiveWindow() { HWND hWnd = GetActiveWindow(); @@ -4889,16 +5124,13 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) win = wxFindWinFromHandle((WXHWND)hwnd); if ( !win ) { - // all these hacks only work under Win32 anyhow -#ifdef __WIN32__ - #if wxUSE_RADIOBOX // native radiobuttons return DLGC_RADIOBUTTON here and for any // wxWindow class which overrides WM_GETDLGCODE processing to // 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 @@ -4911,8 +5143,6 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd); } #endif // wxUSE_SPINCTRL - -#endif // Win32 } } @@ -4941,7 +5171,7 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) return win; } -#ifndef __WXMICROWIN__ +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE // in active frames and dialogs, regardless of where the focus is. @@ -4957,23 +5187,13 @@ void wxSetKeyboardHook(bool doIt) wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance()); wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(), -#if defined(__WIN32__) && !defined(__TWIN32__) GetCurrentThreadId() // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? -#else - GetCurrentTask() -#endif ); } else { UnhookWindowsHookEx(wxTheKeyboardHook); - - // avoids warning about statement with no effect (FreeProcInstance - // doesn't do anything under Win32) -#if !defined(__WIN32__) && !defined(__NT__) - FreeProcInstance(wxTheKeyboardHookProc); -#endif } } @@ -4983,19 +5203,20 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam) DWORD hiWord = HIWORD(lParam); if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) ) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( id != 0 ) { wxKeyEvent event(wxEVT_CHAR_HOOK); if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN ) - event.m_altDown = TRUE; + event.m_altDown = true; event.m_eventObject = NULL; event.m_keyCode = id; event.m_shiftDown = wxIsShiftDown(); event.m_controlDown = wxIsCtrlDown(); - event.SetTimestamp(s_currentMsg.time); - +#ifndef __WXWINCE__ + event.SetTimestamp(::GetMessageTime()); +#endif wxWindow *win = wxGetActiveWindow(); wxEvtHandler *handler; if ( win ) @@ -5081,7 +5302,6 @@ const char *wxGetMessageName(int message) case 0x0047: return "WM_WINDOWPOSCHANGED"; case 0x0048: return "WM_POWER"; -#ifdef __WIN32__ case 0x004A: return "WM_COPYDATA"; case 0x004B: return "WM_CANCELJOURNAL"; case 0x004E: return "WM_NOTIFY"; @@ -5097,7 +5317,6 @@ const char *wxGetMessageName(int message) case 0x007E: return "WM_DISPLAYCHANGE"; case 0x007F: return "WM_GETICON"; case 0x0080: return "WM_SETICON"; -#endif //WIN32 case 0x0081: return "WM_NCCREATE"; case 0x0082: return "WM_NCDESTROY"; @@ -5126,11 +5345,9 @@ const char *wxGetMessageName(int message) case 0x0107: return "WM_SYSDEADCHAR"; case 0x0108: return "WM_KEYLAST"; -#ifdef __WIN32__ case 0x010D: return "WM_IME_STARTCOMPOSITION"; case 0x010E: return "WM_IME_ENDCOMPOSITION"; case 0x010F: return "WM_IME_COMPOSITION"; -#endif //WIN32 case 0x0110: return "WM_INITDIALOG"; case 0x0111: return "WM_COMMAND"; @@ -5158,14 +5375,12 @@ const char *wxGetMessageName(int message) case 0x0211: return "WM_ENTERMENULOOP"; case 0x0212: return "WM_EXITMENULOOP"; -#ifdef __WIN32__ case 0x0213: return "WM_NEXTMENU"; case 0x0214: return "WM_SIZING"; case 0x0215: return "WM_CAPTURECHANGED"; case 0x0216: return "WM_MOVING"; case 0x0218: return "WM_POWERBROADCAST"; case 0x0219: return "WM_DEVICECHANGE"; -#endif //WIN32 case 0x0220: return "WM_MDICREATE"; case 0x0221: return "WM_MDIDESTROY"; @@ -5180,7 +5395,6 @@ const char *wxGetMessageName(int message) case 0x0230: return "WM_MDISETMENU"; case 0x0233: return "WM_DROPFILES"; -#ifdef __WIN32__ case 0x0281: return "WM_IME_SETCONTEXT"; case 0x0282: return "WM_IME_NOTIFY"; case 0x0283: return "WM_IME_CONTROL"; @@ -5189,7 +5403,6 @@ const char *wxGetMessageName(int message) case 0x0286: return "WM_IME_CHAR"; case 0x0290: return "WM_IME_KEYDOWN"; case 0x0291: return "WM_IME_KEYUP"; -#endif //WIN32 case 0x0300: return "WM_CUT"; case 0x0301: return "WM_COPY"; @@ -5209,8 +5422,10 @@ const char *wxGetMessageName(int message) case 0x030F: return "WM_QUERYNEWPALETTE"; case 0x0310: return "WM_PALETTEISCHANGING"; case 0x0311: return "WM_PALETTECHANGED"; +#if wxUSE_HOTKEY + case 0x0312: return "WM_HOTKEY"; +#endif -#ifdef __WIN32__ // common controls messages - although they're not strictly speaking // standard, it's nice to decode them nevertheless @@ -5432,8 +5647,6 @@ const char *wxGetMessageName(int message) case WM_USER+61: return "TB_GETTEXTROWS"; case WM_USER+41: return "TB_GETBITMAPFLAGS"; -#endif //WIN32 - default: static char s_szBuf[128]; sprintf(s_szBuf, "", message); @@ -5530,3 +5743,116 @@ wxPoint wxGetMousePosition() return wxPoint(pt.x, pt.y); } +#if wxUSE_HOTKEY + +bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode) +{ + UINT win_modifiers=0; + if ( modifiers & wxMOD_ALT ) + win_modifiers |= MOD_ALT; + if ( modifiers & wxMOD_SHIFT ) + win_modifiers |= MOD_SHIFT; + if ( modifiers & wxMOD_CONTROL ) + win_modifiers |= MOD_CONTROL; + if ( modifiers & wxMOD_WIN ) + win_modifiers |= MOD_WIN; + + if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) ) + { + wxLogLastError(_T("RegisterHotKey")); + + return false; + } + + return true; +} + +bool wxWindowMSW::UnregisterHotKey(int hotkeyId) +{ + if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) ) + { + wxLogLastError(_T("UnregisterHotKey")); + + return false; + } + + return true; +} + +bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) +{ + int hotkeyId = wParam; + int virtualKey = HIWORD(lParam); + int win_modifiers = LOWORD(lParam); + + wxKeyEvent event(CreateKeyEvent(wxEVT_HOTKEY, virtualKey, wParam, lParam)); + event.SetId(hotkeyId); + event.m_shiftDown = (win_modifiers & MOD_SHIFT) != 0; + event.m_controlDown = (win_modifiers & MOD_CONTROL) != 0; + event.m_altDown = (win_modifiers & MOD_ALT) != 0; + event.m_metaDown = (win_modifiers & MOD_WIN) != 0; + + return GetEventHandler()->ProcessEvent(event); +} + +#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__ +