X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ae79d31557ca0c1822bb42709bb143c438455b46..98840d95db7ab85159dc63d523864b2523d48cae:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 2f228c0709..bbca2e056f 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -17,7 +17,7 @@ // headers // --------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "window.h" #endif @@ -29,8 +29,7 @@ #endif #ifndef WX_PRECOMP - #include - #include "wx/msw/winundef.h" + #include "wx/msw/wrapwin.h" #include "wx/window.h" #include "wx/accel.h" #include "wx/setup.h" @@ -50,10 +49,12 @@ #include "wx/statbox.h" #endif -#if wxUSE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__) #include "wx/ownerdrw.h" #endif +#include "wx/module.h" + #if wxUSE_DRAG_AND_DROP #include "wx/dnd.h" #endif @@ -92,10 +93,11 @@ #include "wx/textctrl.h" #include "wx/notebook.h" +#include "wx/listctrl.h" #include -#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__) #include #include #endif @@ -104,63 +106,24 @@ #include #endif -#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__) #ifdef __WIN95__ #include #endif -#elif !defined(__WXMICROWIN__) // broken compiler +#elif !defined(__WXMICROWIN__) && !defined(__WXWINCE__) // broken compiler #include "wx/msw/gnuwin32/extra.h" #endif -#if defined(__GNUG__) #include "wx/msw/missing.h" -#endif - -// ---------------------------------------------------------------------------- -// standard constants not available with all compilers/headers -// ---------------------------------------------------------------------------- - -// This didn't appear in mingw until 2.95.2 -#ifndef SIF_TRACKPOS -#define SIF_TRACKPOS 16 -#endif - -#if wxUSE_MOUSEWHEEL - #ifndef WM_MOUSEWHEEL - #define WM_MOUSEWHEEL 0x020A - #endif - #ifndef WHEEL_DELTA - #define WHEEL_DELTA 120 - #endif - #ifndef SPI_GETWHEELSCROLLLINES - #define SPI_GETWHEELSCROLLLINES 104 - #endif -#endif // wxUSE_MOUSEWHEEL - -#ifndef VK_OEM_1 - #define VK_OEM_1 0xBA - #define VK_OEM_2 0xBF - #define VK_OEM_3 0xC0 - #define VK_OEM_4 0xDB - #define VK_OEM_5 0xDC - #define VK_OEM_6 0xDD - #define VK_OEM_7 0xDE -#endif -#ifndef VK_OEM_COMMA - #define VK_OEM_PLUS 0xBB - #define VK_OEM_COMMA 0xBC - #define VK_OEM_MINUS 0xBD - #define VK_OEM_PERIOD 0xBE +#if defined(__WXWINCE__) +#include "wx/msw/wince/missing.h" #endif // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- -// the last Windows message we got (FIXME-MT) -extern MSG s_currentMsg; - #if wxUSE_MENUS_NATIVE wxMenu *wxCurrentPopupMenu = NULL; #endif // wxUSE_MENUS_NATIVE @@ -217,6 +180,38 @@ static inline void wxBringWindowToTop(HWND hwnd) } } +// ensure that all our parent windows have WS_EX_CONTROLPARENT style +static void EnsureParentHasControlParentStyle(wxWindow *parent) +{ + /* + If we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our + parent as well as otherwise several Win32 functions using + GetNextDlgTabItem() to iterate over all controls such as + IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed, + all of them iterate over all the controls starting from the currently + focused one and stop iterating when they get back to the focus but + unless all parents have WS_EX_CONTROLPARENT bit set, they would never + get back to the initial (focused) window: as we do have this style, + GetNextDlgTabItem() will leave this window and continue in its parent, + but if the parent doesn't have it, it wouldn't recurse inside it later + on and so wouldn't have a chance of getting back to this window neither. + */ +#ifndef __WXWINCE__ + while ( parent && !parent->IsTopLevel() ) + { + LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE); + if ( !(exStyle & WS_EX_CONTROLPARENT) ) + { + // force the parent to have this style + ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE, + exStyle | WS_EX_CONTROLPARENT); + } + + parent = parent->GetParent(); + } +#endif // !__WXWINCE__ +} + // --------------------------------------------------------------------------- // event tables // --------------------------------------------------------------------------- @@ -226,14 +221,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() // =========================================================================== @@ -263,7 +363,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(); @@ -281,7 +381,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(); @@ -324,13 +424,9 @@ bool wxWindowMSW::MSWCommand(WXUINT WXUNUSED(param), WXWORD WXUNUSED(id)) void wxWindowMSW::Init() { - // generic - InitBase(); - // MSW specific m_isBeingDeleted = FALSE; m_oldWndProc = NULL; - m_useCtl3D = FALSE; m_mouseInWindow = FALSE; m_lastKeydownProcessed = FALSE; @@ -343,7 +439,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; @@ -381,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 @@ -451,7 +543,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 @@ -520,7 +612,7 @@ bool wxWindowMSW::Enable(bool enable) // 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() ) { @@ -684,12 +776,6 @@ void wxWindowMSW::WarpPointer (int x, int y) } } -#if WXWIN_COMPATIBILITY -void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const -{ -} -#endif // WXWIN_COMPATIBILITY - // --------------------------------------------------------------------------- // scrolling stuff // --------------------------------------------------------------------------- @@ -700,54 +786,23 @@ static inline int wxDirToWinStyle(int orient) return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT; } -#if WXWIN_COMPATIBILITY -void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh) -{ - int range1 = range; - - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = GetScrollPage(orient); - if ( pageSize > 1 && range > 0) - { - range1 += (pageSize - 1); - } - - WinStruct info; - info.nPage = pageSize; // Have to set this, or scrollbar goes awry - info.nMin = 0; - info.nMax = range1; - info.fMask = SIF_RANGE | SIF_PAGE; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh); -} - -void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh) -{ - WinStruct info; - info.nPage = page; - info.fMask = SIF_PAGE; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh); -} - -int wxWindowMSW::GetScrollPage(int orient) const -{ - return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize; -} - -#endif // WXWIN_COMPATIBILITY - inline int GetScrollPosition(HWND hWnd, int wOrient) { #ifdef __WXMICROWIN__ return ::GetScrollPosWX(hWnd, wOrient); #else - return ::GetScrollPos(hWnd, wOrient); + WinStruct scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + scrollInfo.fMask = SIF_POS; + if ( !::GetScrollInfo(hWnd, + wOrient, + &scrollInfo) ) + { + // Not neccessarily an error, if there are no scrollbars yet. + // wxLogLastError(_T("GetScrollInfo")); + } + return scrollInfo.nPos; +// return ::GetScrollPos(hWnd, wOrient); #endif } @@ -763,13 +818,25 @@ int wxWindowMSW::GetScrollPos(int orient) const // of positions that we can scroll. int wxWindowMSW::GetScrollRange(int orient) const { - int minPos, maxPos; + int maxPos; HWND hWnd = GetHwnd(); if ( !hWnd ) return 0; - +#if 0 ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, &minPos, &maxPos); +#endif + WinStruct scrollInfo; + scrollInfo.fMask = SIF_RANGE; + if ( !::GetScrollInfo(hWnd, + orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &scrollInfo) ) + { + // Most of the time this is not really an error, since the return + // value can also be zero when there is no scrollbar yet. + // wxLogLastError(_T("GetScrollInfo")); + } + maxPos = scrollInfo.nMax; // undo "range - 1" done in SetScrollbar() return maxPos + 1; @@ -790,6 +857,11 @@ void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh) info.nMin = 0; info.nPos = pos; info.fMask = SIF_POS; + if ( HasFlag(wxALWAYS_SHOW_SB) ) + { + // disable scrollbar instead of removing it then + info.fMask |= SIF_DISABLENOSCROLL; + } ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, &info, refresh); @@ -808,6 +880,11 @@ void wxWindowMSW::SetScrollbar(int orient, info.nMax = range - 1; // as both nMax and nMax are inclusive info.nPos = pos; info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; + if ( HasFlag(wxALWAYS_SHOW_SB) ) + { + // disable scrollbar instead of removing it then + info.fMask |= SIF_DISABLENOSCROLL; + } HWND hWnd = GetHwnd(); if ( hWnd ) @@ -836,7 +913,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) @@ -896,7 +978,7 @@ void wxWindowMSW::SubclassWin(WXHWND 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); } @@ -942,6 +1024,28 @@ 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) ) { @@ -951,6 +1055,7 @@ bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc) } return wndProc == (WXFARPROC)cls.lpfnWndProc; +#endif } // ---------------------------------------------------------------------------- @@ -1028,23 +1133,10 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const if ( flags & wxHSCROLL ) style |= WS_HSCROLL; - 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 (border == wxBORDER_DEFAULT && - IsKindOf(CLASSINFO(wxControl)) && - GetParent() && - ((GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS)) - { - border = (wxBorder)((flags & wxBORDER_MASK) | wxBORDER_SUNKEN); - } + const wxBorder border = GetBorder(flags); - // Only give it WS_BORDER for wxBORDER_SIMPLE - if (border & wxBORDER_SIMPLE) + // 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 @@ -1052,18 +1144,20 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const { *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: @@ -1085,7 +1179,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() ) @@ -1098,37 +1192,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() { @@ -1151,7 +1214,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 ) @@ -1164,7 +1227,7 @@ void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event)) 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() ) @@ -1197,7 +1260,8 @@ void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event)) } } - UpdateWindowUI(); + if (wxUpdateUIEvent::CanUpdate(this)) + UpdateWindowUI(wxUPDATE_UI_FROMIDLE); } // Set this window to be the child of 'parent'. @@ -1211,15 +1275,14 @@ bool wxWindowMSW::Reparent(wxWindowBase *parent) ::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) @@ -1270,7 +1333,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(); @@ -1300,9 +1363,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 } // ---------------------------------------------------------------------------- @@ -1625,48 +1690,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 // --------------------------------------------------------------------------- @@ -1683,15 +1706,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) @@ -1706,7 +1735,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() @@ -1947,15 +1980,19 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // style has the focus, it can happen. One such possibility is if // all windows are either toplevel, wxDialog, wxPanel or static // controls and no window can actually accept keyboard input. +#if !defined(__WXWINCE__) if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT ) { // passimistic by default canSafelyCallIsDlgMsg = FALSE; - for ( wxWindowList::Node *node = GetChildren().GetFirst(); + for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext() ) { - if ( node->GetData()->AcceptsFocus() ) + wxWindow * const win = node->GetData(); + if ( win->AcceptsFocus() && + !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) & + WS_EX_CONTROLPARENT) ) { // it shouldn't hang... canSafelyCallIsDlgMsg = TRUE; @@ -1964,6 +2001,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } } } +#endif // !__WXWINCE__ if ( canSafelyCallIsDlgMsg ) { @@ -2034,11 +2072,9 @@ bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* WXUNUSED(pMsg)) } // --------------------------------------------------------------------------- -// 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) { @@ -2081,50 +2117,6 @@ void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, *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); - *hdc = (WXHDC)wParam; -} - -void wxWindowMSW::UnpackMenuSelect(WXWPARAM wParam, WXLPARAM lParam, - WXWORD *item, WXWORD *flags, WXHMENU *hmenu) -{ - *item = (WXWORD)wParam; - *flags = LOWORD(lParam); - *hmenu = (WXHMENU)HIWORD(lParam); -} - -#endif // Win32/16 - // --------------------------------------------------------------------------- // Main wxWindows window proc and the window proc for wxWindow // --------------------------------------------------------------------------- @@ -2220,23 +2212,25 @@ 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(); - } - } + { + 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 ) @@ -2266,6 +2260,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; +#if !defined(__WXWINCE__) case WM_SIZING: { LPRECT pRect = (LPRECT)lParam; @@ -2283,8 +2278,9 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } } break; +#endif -#ifndef __WXMICROWIN__ +#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) case WM_ACTIVATEAPP: wxTheApp->SetActive(wParam != 0, FindFocus()); break; @@ -2309,8 +2305,35 @@ 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__ @@ -2337,6 +2360,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); @@ -2440,11 +2519,9 @@ 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 #ifdef WM_DRAWITEM @@ -2600,6 +2677,12 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; +#if wxUSE_HOTKEY + case WM_HOTKEY: + processed = HandleHotKey((WORD)wParam, lParam); + break; +#endif // wxUSE_HOTKEY + case WM_HSCROLL: case WM_VSCROLL: { @@ -2616,7 +2699,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: @@ -2624,9 +2706,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; @@ -2649,9 +2728,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); @@ -2674,9 +2755,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); @@ -2688,6 +2771,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; +#if !defined(__WXWINCE__) case WM_QUERYENDSESSION: processed = HandleQueryEndSession(lParam, &rc.allow); break; @@ -2699,6 +2783,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, @@ -2720,7 +2805,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()); } @@ -2728,21 +2813,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; 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); @@ -2753,6 +2846,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } processed = eventProcessed; +#ifndef __WXWINCE__ } else if (info->iContextType == HELPINFO_MENUITEM) { @@ -2762,9 +2856,12 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } //else: processed is already FALSE +#endif } break; +#endif +#if !defined(__WXWINCE__) case WM_CONTEXTMENU: { // we don't convert from screen to client coordinates as @@ -2772,9 +2869,11 @@ 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); + evtCtx.SetEventObject(this); processed = GetEventHandler()->ProcessEvent(evtCtx); } break; +#endif case WM_MENUCHAR: // we're only interested in our own menus, not MF_SYSMENU @@ -2789,7 +2888,6 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } } break; -#endif // __WIN32__ } if ( !processed ) @@ -2911,6 +3009,8 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, nonDefault = TRUE; } + AdjustForParentClientOrigin(x, y); + return nonDefault; } @@ -2938,7 +3038,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"); } @@ -2946,18 +3046,37 @@ 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 - ); +#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 + { + 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 ) { @@ -3004,7 +3123,7 @@ 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(); @@ -3035,12 +3154,13 @@ 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 - +#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; } +#endif LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; @@ -3057,9 +3177,33 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code, // 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)); +*/ + // Fix by dimitrishortcut: see patch 771772 + + // FIXME: szText has a max of 80 bytes, so limit the tooltip string + // length accordingly. Ideally lpszText should be used, but who + // would be responsible for freeing the buffer? + + // Maximum length of a tip is 39 characters. 39 is 80/2 minus 1 byte + // needed for NULL character. + size_t tipLength = wxMin(ttip.Len(), 39); + + // Convert to WideChar without adding the NULL character. The NULL + // character is added afterwards (Could have used ttip.Left(tipLength) + // and a cchMultiByte parameter of tipLength+1, but this is more + //efficient. + ::MultiByteToWideChar(CP_ACP, 0, ttip, tipLength, + (wchar_t *)ttText->szText, + sizeof(ttText->szText) / sizeof(wchar_t)); + + // Add the NULL character. + ttText->szText[tipLength*2+0] = '\0'; + ttText->szText[tipLength*2+1] = '\0'; + #endif // Unicode/!Unicode } @@ -3095,6 +3239,7 @@ 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); @@ -3110,10 +3255,14 @@ 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; @@ -3128,6 +3277,9 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff) event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) ); return wxTheApp->ProcessEvent(event); +#else + return FALSE; +#endif } // --------------------------------------------------------------------------- @@ -3136,30 +3288,13 @@ 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); @@ -3296,7 +3431,7 @@ bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) { -#if defined (__WXMICROWIN__) +#if defined (__WXMICROWIN__) || defined(__WXWINCE__) return FALSE; #else // __WXMICROWIN__ HDROP hFilesInfo = (HDROP) wParam; @@ -3318,9 +3453,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); @@ -3360,15 +3493,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; @@ -3430,7 +3558,16 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), // 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 @@ -3462,28 +3599,32 @@ bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) #endif // USE_OWNER_DRAWN -#if wxUSE_CONTROLS +#if wxUSE_CONTROLS && !defined(__WXUNIVERSAL__) #if wxUSE_OWNER_DRAWN - wxWindow *item = FindItem(id); - if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) - return ((wxControl *)item)->MSWOnDraw(itemStruct); -#elif !defined(__WXUNIVERSAL__) + wxControl *item = wxDynamicCast(FindItem(id), wxControl); +#else // !wxUSE_OWNER_DRAWN // we may still have owner-drawn buttons internally because we have to make // them owner-drawn to support colour change - wxWindow *item = FindItem(id); - if ( item && item->IsKindOf(CLASSINFO(wxButton)) ) - return ((wxButton *)item)->MSWOnDraw(itemStruct); + wxControl *item = wxDynamicCast(FindItem(id), wxButton); #endif // USE_OWNER_DRAWN + if ( item ) + { + return item->MSWOnDraw(itemStruct); + } + #endif // wxUSE_CONTROLS return FALSE; } -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 ) @@ -3496,12 +3637,13 @@ bool wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) &pMeasureStruct->itemHeight); } - 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 +#endif // wxUSE_OWNER_DRAWN + return FALSE; } @@ -3540,7 +3682,11 @@ 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); } @@ -3666,7 +3812,7 @@ void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) // FIXME-MT 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 @@ -3773,7 +3919,6 @@ bool wxWindowMSW::HandlePaint() // if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) // return FALSE; -#ifdef __WIN32__ HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle if ( !hRegion ) wxLogLastError(wxT("CreateRectRgn")); @@ -3781,14 +3926,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,11 +4017,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 } // --------------------------------------------------------------------------- @@ -3951,6 +4093,9 @@ bool wxWindowMSW::HandleSizing(wxRect& rect) bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) { +#ifdef __WXWINCE__ + return FALSE; +#else MINMAXINFO *info = (MINMAXINFO *)mmInfo; bool rc = FALSE; @@ -3985,6 +4130,7 @@ bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) } return rc; +#endif } // --------------------------------------------------------------------------- @@ -4057,6 +4203,7 @@ bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam)) { +#ifndef __WXWINCE__ // 4 bits are reserved switch ( wParam & 0xFFFFFFF0 ) { @@ -4066,6 +4213,7 @@ bool wxWindowMSW::HandleSysCommand(WXWPARAM wParam, WXLPARAM WXUNUSED(lParam)) case SC_MINIMIZE: return HandleMinimize(); } +#endif return FALSE; } @@ -4093,7 +4241,10 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event, // so simply test for negative value. event.m_altDown = ::GetKeyState(VK_MENU) < 0; - event.SetTimestamp(s_currentMsg.time); +#ifndef __WXWINCE__ + event.SetTimestamp(::GetMessageTime()); +#endif + event.m_eventObject = this; event.SetId(GetId()); @@ -4124,7 +4275,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, @@ -4133,9 +4290,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); @@ -4200,7 +4357,19 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) { // Generate an ENTER event 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); @@ -4238,7 +4407,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 ) { @@ -4252,10 +4420,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); @@ -4290,7 +4454,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; @@ -4310,8 +4476,6 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, // WM_KEYDOWN one bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) { - bool ctrlDown = FALSE; - int id; if ( isASCII ) { @@ -4336,7 +4500,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) break; default: - ctrlDown = TRUE; + //ctrlDown = TRUE; break; } } @@ -4412,10 +4576,11 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) 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; @@ -4462,19 +4627,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 // --------------------------------------------------------------------------- @@ -4610,7 +4773,6 @@ 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 @@ -4625,12 +4787,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 @@ -4781,7 +4943,7 @@ int wxCharCodeMSWToWX(int keySym) int wxCharCodeWXToMSW(int id, bool *isVirtual) { *isVirtual = TRUE; - int keySym = 0; + int keySym; switch (id) { case WXK_CANCEL: keySym = VK_CANCEL; break; @@ -4855,6 +5017,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(); @@ -4878,9 +5052,6 @@ 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 @@ -4900,8 +5071,6 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd); } #endif // wxUSE_SPINCTRL - -#endif // Win32 } } @@ -4930,7 +5099,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. @@ -4946,23 +5115,13 @@ void wxSetKeyboardHook(bool doIt) wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance()); wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(), -#if defined(__WIN32__) 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,8 +5142,9 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam) 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 ) @@ -5070,7 +5230,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"; @@ -5086,7 +5245,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"; @@ -5115,11 +5273,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"; @@ -5147,14 +5303,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"; @@ -5169,7 +5323,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"; @@ -5178,7 +5331,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"; @@ -5198,8 +5350,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 @@ -5421,8 +5575,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); @@ -5519,3 +5671,108 @@ 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 verified for WinCE +#ifndef __WXWINCE__ +/* + * wxEventFixModule (needs a better name) allows message handling to continute while a menu + * is being shown - ie, to continue processing messages from a worker thread. + * + * Code originally by Jason W. from wx-dev, reworked into a wxModule by Chris Mellon + */ + +class wxEventFixModule : public wxModule { +public: + //base class virtuals + virtual bool OnInit() { + wxEventFixModule::s_hMsgHookProc = SetWindowsHookEx( + WH_GETMESSAGE, + &wxEventFixModule::MsgHookProc, + NULL, + GetCurrentThreadId()); + wxLogDebug(_T("Loaded event fix module")); + return true; + }; + virtual void OnExit() { + UnhookWindowsHookEx(wxEventFixModule::s_hMsgHookProc); + + }; + static LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam) { + MSG *msg = (MSG*)lParam; + switch (msg->message) + { + case WM_NULL: + static bool bInHookProc = false; + if (!bInHookProc) + { + bInHookProc = true; + wxTheApp->ProcessPendingEvents(); + bInHookProc = false; + } + break; + } + return CallNextHookEx(wxEventFixModule::s_hMsgHookProc, nCode, wParam, lParam); + }; +private: + static HHOOK s_hMsgHookProc; +DECLARE_DYNAMIC_CLASS(wxEventFixModule) +}; +HHOOK wxEventFixModule::s_hMsgHookProc = 0; + +IMPLEMENT_DYNAMIC_CLASS(wxEventFixModule, wxModule) +#endif + // __WXWINCE__ +