X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c358ea4147c4ee2942155ed193c98b7d015a7aaf..b36e08d0867cf3f6a5a286ce145c0fb80746c290:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 0874381013..7691c62d9a 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: src/msw/windows.cpp -// Purpose: wxWindow +// Name: src/msw/window.cpp +// Purpose: wxWindowMSW // Author: Julian Smart // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation // Created: 04/01/98 @@ -24,11 +24,11 @@ #pragma hdrstop #endif +#include "wx/window.h" + #ifndef WX_PRECOMP #include "wx/msw/wrapwin.h" - #include "wx/window.h" #include "wx/accel.h" - #include "wx/setup.h" #include "wx/menu.h" #include "wx/dc.h" #include "wx/dcclient.h" @@ -44,6 +44,8 @@ #include "wx/settings.h" #include "wx/statbox.h" #include "wx/sizer.h" + #include "wx/intl.h" + #include "wx/log.h" #endif #if wxUSE_OWNER_DRAWN && !defined(__WXUNIVERSAL__) @@ -52,6 +54,7 @@ #include "wx/evtloop.h" #include "wx/module.h" +#include "wx/power.h" #include "wx/sysopt.h" #if wxUSE_DRAG_AND_DROP @@ -71,7 +74,6 @@ #endif #include "wx/menuitem.h" -#include "wx/log.h" #include "wx/msw/private.h" @@ -87,9 +89,6 @@ #include "wx/spinctrl.h" #endif // wxUSE_SPINCTRL -#include "wx/intl.h" -#include "wx/log.h" - #include "wx/textctrl.h" #include "wx/notebook.h" #include "wx/listctrl.h" @@ -107,10 +106,20 @@ #include +#ifndef __WXWINCE__ + #include +#endif + #include "wx/msw/missing.h" #if defined(__WXWINCE__) #include "wx/msw/wince/missing.h" +#ifdef __POCKETPC__ + #include + #include + #include + #include +#endif #endif #if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) @@ -121,7 +130,11 @@ // resizing complicated window hierarchies, but this can in theory result in // different behaviour than the old code so we keep the possibility to use it // by setting this to 0 (in the future this should be removed completely) +#ifdef __WXWINCE__ +#define USE_DEFERRED_SIZING 0 +#else #define USE_DEFERRED_SIZING 1 +#endif // set this to 1 to filter out duplicate mouse events, e.g. mouse move events // when mouse position didnd't change @@ -151,7 +164,7 @@ static bool gs_hasStdCmap = false; // last mouse event information we need to filter out the duplicates #if wxUSE_MOUSEEVENT_HACK -static struct +static struct MouseEventInfoDummy { // mouse position (in screen coordinates) wxPoint pos; @@ -220,7 +233,7 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent) 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. + on and so wouldn't have a chance of getting back to this window either. */ while ( parent && !parent->IsTopLevel() ) { @@ -394,7 +407,7 @@ wxWindow *wxWindowMSW::FindItem(long id) const wxControl *item = wxDynamicCastThis(wxControl); if ( item ) { - // is it we or one of our "internal" children? + // is it us or one of our "internal" children? if ( item->GetId() == id #ifndef __WXUNIVERSAL__ || (item->GetSubcontrols().Index(id) != wxNOT_FOUND) @@ -484,6 +497,10 @@ void wxWindowMSW::Init() m_pendingPosition = wxDefaultPosition; m_pendingSize = wxDefaultSize; + +#ifdef __POCKETPC__ + m_contextMenuEnabled = false; +#endif } // Destructor @@ -513,7 +530,7 @@ wxWindowMSW::~wxWindowMSW() #endif // __WXUNIVERSAL__ // VS: destroy children first and _then_ detach *this from its parent. - // If we'd do it the other way around, children wouldn't be able + // If we did it the other way around, children wouldn't be able // find their parent frame (see above). DestroyChildren(); @@ -665,7 +682,7 @@ bool wxWindowMSW::Enable(bool enable) if ( enable ) { - // enable the child back unless it had been disabled before us + // re-enable the child unless it had been disabled before us if ( !m_childrenDisabled || !m_childrenDisabled->Find(child) ) child->Enable(); } @@ -704,12 +721,18 @@ bool wxWindowMSW::Show(bool show) return false; HWND hWnd = GetHwnd(); - int cshow = show ? SW_SHOW : SW_HIDE; - ::ShowWindow(hWnd, cshow); - if ( show && IsTopLevel() ) + // we could be called before the underlying window is created (this is + // actually useful to prevent it from being initially shown), e.g. + // + // wxFoo *foo = new wxFoo; + // foo->Hide(); + // foo->Create(parent, ...); + // + // should work without errors + if ( hWnd ) { - wxBringWindowToTop(hWnd); + ::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE); } return true; @@ -728,16 +751,6 @@ void wxWindowMSW::Lower() SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } -void wxWindowMSW::SetTitle( const wxString& title) -{ - SetWindowText(GetHwnd(), title.c_str()); -} - -wxString wxWindowMSW::GetTitle() const -{ - return wxGetWindowText(GetHWND()); -} - void wxWindowMSW::DoCaptureMouse() { HWND hWnd = GetHwnd(); @@ -789,22 +802,10 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor) return false; } - if ( m_cursor.Ok() ) + // don't "overwrite" busy cursor + if ( m_cursor.Ok() && !wxIsBusy() ) { - HWND hWnd = GetHwnd(); - - // Change the cursor NOW if we're within the correct window - POINT point; -#ifdef __WXWINCE__ - ::GetCursorPosWinCE(&point); -#else - ::GetCursorPos(&point); -#endif - - RECT rect = wxGetWindowRect(hWnd); - - if ( ::PtInRect(&rect, point) && !wxIsBusy() ) - ::SetCursor(GetHcursorOf(m_cursor)); + ::SetCursor(GetHcursorOf(m_cursor)); } return true; @@ -820,9 +821,9 @@ void wxWindowMSW::WarpPointer(int x, int y) } } -void wxWindowMSW::MSWUpdateUIState(int action) +void wxWindowMSW::MSWUpdateUIState(int action, int state) { - // WM_UPDATEUISTATE only appeared in Windows 2000 so it can do us no good + // WM_CHANGEUISTATE only appeared in Windows 2000 so it can do us no good // to use it on older systems -- and could possibly do some harm static int s_needToUpdate = -1; if ( s_needToUpdate == -1 ) @@ -834,11 +835,9 @@ void wxWindowMSW::MSWUpdateUIState(int action) if ( s_needToUpdate ) { - // NB: it doesn't seem to matter what we put in wParam, whether we - // include just one UISF_XXX or both, both are affected, no idea - // why - ::SendMessage(GetHwnd(), WM_UPDATEUISTATE, - MAKEWPARAM(action, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0); + // we send WM_CHANGEUISTATE so if nothing needs changing then the system + // won't send WM_UPDATEUISTATE + ::SendMessage(GetHwnd(), WM_CHANGEUISTATE, MAKEWPARAM(action, state), 0); } } @@ -854,15 +853,10 @@ inline int GetScrollPosition(HWND hWnd, int wOrient) WinStruct scrollInfo; scrollInfo.cbSize = sizeof(SCROLLINFO); scrollInfo.fMask = SIF_POS; - if ( !::GetScrollInfo(hWnd, - wOrient, - &scrollInfo) ) - { - // Not necessarily an error, if there are no scrollbars yet. - // wxLogLastError(_T("GetScrollInfo")); - } + ::GetScrollInfo(hWnd, wOrient, &scrollInfo ); + return scrollInfo.nPos; -// return ::GetScrollPos(hWnd, wOrient); + #endif } @@ -949,11 +943,13 @@ void wxWindowMSW::SetScrollbar(int orient, HWND hWnd = GetHwnd(); if ( hWnd ) { + // We have to set the variables here to make them valid in events + // triggered by ::SetScrollInfo() + *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize; + ::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) @@ -1045,12 +1041,16 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd) } else { - // don't bother restoring it neither: this also makes it easy to + // don't bother restoring it either: this also makes it easy to // implement IsOfStandardClass() method which returns true for the // standard controls and false for the wxWidgets own windows as it can // simply check m_oldWndProc m_oldWndProc = NULL; } + + // we're officially created now, send the event + wxWindowCreateEvent event((wxWindow *)this); + (void)GetEventHandler()->ProcessEvent(event); } void wxWindowMSW::UnsubclassWin() @@ -1099,20 +1099,19 @@ void wxWindowMSW::DissociateHandle() bool wxCheckWindowWndProc(WXHWND hWnd, - WXFARPROC WXUNUSED_IN_WINCE(wndProc)) + WXFARPROC WXUNUSED(wndProc)) { - // Unicows note: the code below works, but only because WNDCLASS contains - // original window handler rather that the unicows fake one. This may not - // be on purpose, though; if it stops working with future versions of - // 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. +// TODO: This list of window class names should be factored out so they can be +// managed in one place and then accessed from here and other places, such as +// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses() - // On WinCE (at least), the wndproc comparison doesn't work, - // so have to use something like this. #ifdef __WXWINCE__ extern wxChar *wxCanvasClassName; extern wxChar *wxCanvasClassNameNR; +#else + extern const wxChar *wxCanvasClassName; + extern const wxChar *wxCanvasClassNameNR; +#endif extern const wxChar *wxMDIFrameClassName; extern const wxChar *wxMDIFrameClassNameNoRedraw; extern const wxChar *wxMDIChildFrameClassName; @@ -1120,6 +1119,10 @@ bool wxCheckWindowWndProc(WXHWND hWnd, wxString str(wxGetWindowClass(hWnd)); if (str == wxCanvasClassName || str == wxCanvasClassNameNR || +#if wxUSE_GLCANVAS + str == _T("wxGLCanvasClass") || + str == _T("wxGLCanvasClassNR") || +#endif // wxUSE_GLCANVAS str == wxMDIFrameClassName || str == wxMDIFrameClassNameNoRedraw || str == wxMDIChildFrameClassName || @@ -1128,17 +1131,6 @@ bool wxCheckWindowWndProc(WXHWND hWnd, 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 wndProc == (WXFARPROC)cls.lpfnWndProc; -#endif } // ---------------------------------------------------------------------------- @@ -1159,6 +1151,9 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) if ( !GetHwnd() ) return; + // we may need to call SetWindowPos() when we change some styles + bool callSWP = false; + WXDWORD exstyle, exstyleOld; long style = MSWGetStyle(flags, &exstyle), styleOld = MSWGetStyle(flagsOld, &exstyleOld); @@ -1174,17 +1169,40 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) styleReal |= style; ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal); + + // If any of the style changes changed any of the frame styles: + // MSDN: SetWindowLong: + // Certain window data is cached, so changes you make using + // SetWindowLong will not take effect until you call the + // SetWindowPos function. Specifically, if you change any of + // the frame styles, you must call SetWindowPos with the + // SWP_FRAMECHANGED flag for the cache to be updated properly. + + callSWP = ((styleOld ^ style ) & (WS_BORDER | + WS_THICKFRAME | + WS_CAPTION | + WS_DLGFRAME | + WS_MAXIMIZEBOX | + WS_MINIMIZEBOX | + WS_SYSMENU) ) != 0; } // and the extended style + long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE); + if ( exstyle != exstyleOld ) { - long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE); exstyleReal &= ~exstyleOld; exstyleReal |= exstyle; ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal); + // ex style changes don't take effect without calling SetWindowPos + callSWP = true; + } + + if ( callSWP ) + { // we must call SetWindowPos() to flush the cached extended style and // also to make the change to wxSTAY_ON_TOP style take effect: just // setting the style simply doesn't work @@ -1192,7 +1210,7 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE) ) + SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED) ) { wxLogLastError(_T("SetWindowPos")); } @@ -1209,7 +1227,7 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const // using this flag results in very significant reduction in flicker, // especially with controls inside the static boxes (as the interior of the - // box is not redrawn twice).but sometimes results in redraw problems, so + // box is not redrawn twice), but sometimes results in redraw problems, so // optionally allow the old code to continue to use it provided a special // system option is turned on if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) @@ -1373,7 +1391,7 @@ void wxWindowMSW::Thaw() { wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") ); - if ( !--m_frozenness ) + if ( --m_frozenness == 0 ) { if ( IsShown() ) { @@ -1438,6 +1456,26 @@ void wxWindowMSW::Update() // drag and drop // --------------------------------------------------------------------------- +// we need to lower the sibling static boxes so controls contained within can be +// a drop target +static inline void AdjustStaticBoxZOrder(wxWindow *parent) +{ + // no sibling static boxes if we have no parent (ie TLW) + if ( !parent ) + return; + + for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + wxStaticBox *statbox = wxDynamicCast(node->GetData(), wxStaticBox); + if ( statbox ) + { + ::SetWindowPos(GetHwndOf(statbox), HWND_BOTTOM, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } + } +} #if wxUSE_DRAG_AND_DROP void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget) @@ -1449,18 +1487,24 @@ void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget) m_dropTarget = pDropTarget; if ( m_dropTarget != 0 ) + { + AdjustStaticBoxZOrder(GetParent()); m_dropTarget->Register(m_hWnd); + } } #endif // wxUSE_DRAG_AND_DROP -// old style file-manager drag&drop support: we retain the old-style +// old-style file manager drag&drop support: we retain the old-style // DragAcceptFiles in parallel with SetDropTarget. void wxWindowMSW::DragAcceptFiles(bool WXUNUSED_IN_WINCE(accept)) { #ifndef __WXWINCE__ HWND hWnd = GetHwnd(); if ( hWnd ) + { + AdjustStaticBoxZOrder(GetParent()); ::DragAcceptFiles(hWnd, (BOOL)accept); + } #endif } @@ -1522,14 +1566,36 @@ void wxWindowMSW::DoGetSize(int *x, int *y) const // Get size *available for subwindows* i.e. excluding menu bar etc. void wxWindowMSW::DoGetClientSize(int *x, int *y) const { - // this is only for top level windows whose resizing is never deferred, so - // we can safely use the current size here - RECT rect = wxGetClientRect(GetHwnd()); +#if USE_DEFERRED_SIZING + if ( IsTopLevel() || m_pendingSize == wxDefaultSize ) +#endif + { // top level windows resizing is never deferred, so we can safely use + // the current size here + RECT rect = wxGetClientRect(GetHwnd()); - if ( x ) - *x = rect.right; - if ( y ) - *y = rect.bottom; + if ( x ) + *x = rect.right; + if ( y ) + *y = rect.bottom; + } +#if USE_DEFERRED_SIZING + else // non top level and using deferred sizing + { + // we need to calculate the *pending* client size here + RECT rect; + rect.left = m_pendingPosition.x; + rect.top = m_pendingPosition.y; + rect.right = rect.left + m_pendingSize.x; + rect.bottom = rect.top + m_pendingSize.y; + + ::SendMessage(GetHwnd(), WM_NCCALCSIZE, FALSE, (LPARAM)&rect); + + if ( x ) + *x = rect.right - rect.left; + if ( y ) + *y = rect.bottom - rect.top; + } +#endif } void wxWindowMSW::DoGetPosition(int *x, int *y) const @@ -1624,7 +1690,7 @@ wxWindowMSW::DoMoveSibling(WXHWND hwnd, int x, int y, int width, int height) if ( hdwp ) { hdwp = ::DeferWindowPos(hdwp, (HWND)hwnd, NULL, x, y, width, height, - SWP_NOZORDER); + SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); if ( !hdwp ) { wxLogLastError(_T("DeferWindowPos")); @@ -1746,11 +1812,12 @@ void wxWindowMSW::DoSetSize(int x, int y, int width, int height, int sizeFlags) void wxWindowMSW::DoSetClientSize(int width, int height) { - // setting the client size is less obvious than it it could have been + // setting the client size is less obvious than it could have been // because in the result of changing the total size the window scrollbar - // may [dis]appear and/or its menubar may [un]wrap and so the client size - // will not be correct as the difference between the total and client size - // changes - so we keep changing it until we get it right + // may [dis]appear and/or its menubar may [un]wrap (and AdjustWindowRect() + // doesn't take neither into account) and so the client size will not be + // correct as the difference between the total and client size changes -- + // so we keep changing it until we get it right // // normally this loop shouldn't take more than 3 iterations (usually 1 but // if scrollbars [dis]appear as the result of the first call, then 2 and it @@ -1791,7 +1858,9 @@ void wxWindowMSW::DoSetClientSize(int width, int height) } // don't call DoMoveWindow() because we want to move window immediately - // and not defer it here + // and not defer it here as otherwise the value returned by + // GetClient/WindowRect() wouldn't change as the window wouldn't be + // really resized if ( !::MoveWindow(GetHwnd(), rectWin.left, rectWin.top, @@ -1910,11 +1979,11 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) #if defined(__WXWINCE__) UINT flags = 0; #else - UINT flags = TPM_RIGHTBUTTON; + UINT flags = TPM_RIGHTBUTTON | TPM_RECURSE; #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 + // we need to do it right now as otherwise the events are never going to be // sent to wxCurrentPopupMenu from HandleCommand() // // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't @@ -2055,6 +2124,12 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) else // no default button #endif // wxUSE_BUTTON { +#ifdef __WXWINCE__ + wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN); + event.SetEventObject(this); + if(GetEventHandler()->ProcessEvent(event)) + return true; +#endif // this is a quick and dirty test for a text // control if ( !(lDlgCode & DLGC_HASSETSEL) ) @@ -2095,9 +2170,8 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) { // as we don't call IsDialogMessage(), which would take of // this by default, we need to manually send this message - // so that controls could change their appearance - // appropriately - MSWUpdateUIState(UIS_CLEAR); + // so that controls can change their UI state if needed + MSWUpdateUIState(UIS_CLEAR, UISF_HIDEFOCUS); return true; } @@ -2112,7 +2186,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) { // ::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 + // [some of] the situations when this may happen and not call it // then // assume we can call it by default @@ -2133,7 +2207,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) #if !defined(__WXWINCE__) if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT ) { - // passimistic by default + // pessimistic by default canSafelyCallIsDlgMsg = false; for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; @@ -2198,7 +2272,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // relay mouse move events to the tooltip control MSG *msg = (MSG *)pMsg; if ( msg->message == WM_MOUSEMOVE ) - m_tooltip->RelayEvent(pMsg); + wxToolTip::RelayEvent(pMsg); } #endif // wxUSE_TOOLTIPS @@ -2400,28 +2474,6 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l break; #endif // !__WXWINCE__ -#if !(defined(_WIN32_WCE) && _WIN32_WCE < 400) - case WM_WINDOWPOSCHANGED: - { - WINDOWPOS *lpPos = (WINDOWPOS *)lParam; - - if ( !(lpPos->flags & SWP_NOSIZE) ) - { - RECT rc; - ::GetClientRect(GetHwnd(), &rc); - - AutoHRGN hrgnClient(::CreateRectRgnIndirect(&rc)); - AutoHRGN hrgnNew(::CreateRectRgn(lpPos->x, lpPos->y, - lpPos->cx, lpPos->cy)); - - // we need to invalidate any new exposed areas here - // to force them to repaint - if ( ::CombineRgn(hrgnNew, hrgnNew, hrgnClient, RGN_DIFF) != NULLREGION ) - ::InvalidateRgn(GetHwnd(), hrgnNew, TRUE); - } - } - break; -#endif #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) case WM_ACTIVATEAPP: // This implicitly sends a wxEVT_ACTIVATE_APP event @@ -2562,6 +2614,36 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l wxCHECK_MSG( win, 0, _T("FindWindowForMouseEvent() returned NULL") ); } +#ifdef __POCKETPC__ + if (IsContextMenuEnabled() && message == WM_LBUTTONDOWN) + { + SHRGINFO shrgi = {0}; + + shrgi.cbSize = sizeof(SHRGINFO); + shrgi.hwndClient = (HWND) GetHWND(); + shrgi.ptDown.x = x; + shrgi.ptDown.y = y; + + shrgi.dwFlags = SHRG_RETURNCMD; + // shrgi.dwFlags = SHRG_NOTIFYPARENT; + + if (GN_CONTEXTMENU == ::SHRecognizeGesture(&shrgi)) + { + wxPoint pt(x, y); + pt = ClientToScreen(pt); + + wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt); + + evtCtx.SetEventObject(this); + if (GetEventHandler()->ProcessEvent(evtCtx)) + { + processed = true; + return true; + } + } + } +#endif + #else // !__WXWINCE__ wxWindowMSW *win = this; #endif // __WXWINCE__/!__WXWINCE__ @@ -2683,7 +2765,7 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l { switch ( wParam ) { - // we consider these message "not interesting" to OnChar, so + // we consider these messages "not interesting" to OnChar, so // just don't do anything more with them case VK_SHIFT: case VK_CONTROL: @@ -2706,6 +2788,16 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l case VK_SUBTRACT: case VK_MULTIPLY: case VK_DIVIDE: + case VK_NUMPAD0: + case VK_NUMPAD1: + case VK_NUMPAD2: + case VK_NUMPAD3: + case VK_NUMPAD4: + case VK_NUMPAD5: + case VK_NUMPAD6: + case VK_NUMPAD7: + case VK_NUMPAD8: + case VK_NUMPAD9: case VK_OEM_1: case VK_OEM_2: case VK_OEM_3: @@ -2829,6 +2921,10 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l processed = HandleCaptureChanged((WXHWND) (HWND) lParam); break; + case WM_SETTINGCHANGE: + processed = HandleSettingChange(wParam, lParam); + break; + case WM_QUERYNEWPALETTE: processed = HandleQueryNewPalette(); break; @@ -2987,6 +3083,16 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l } } break; + +#ifndef __WXWINCE__ + case WM_POWERBROADCAST: + { + bool vetoed; + processed = HandlePower(wParam, lParam, &vetoed); + rc.result = processed && vetoed ? BROADCAST_QUERY_DENY : TRUE; + } + break; +#endif // __WXWINCE__ } if ( !processed ) @@ -3203,8 +3309,6 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // WM_NOTIFY // --------------------------------------------------------------------------- -#ifdef __WIN95__ - bool wxWindowMSW::HandleNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { #ifndef __WXMICROWIN__ @@ -3348,8 +3452,6 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl), return false; } -#endif // __WIN95__ - // --------------------------------------------------------------------------- // end session messages // --------------------------------------------------------------------------- @@ -3418,10 +3520,6 @@ bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED_IN_WINCE(cs), EnsureParentHasControlParentStyle(GetParent()); #endif // !__WXWINCE__ - // TODO: should generate this event from WM_NCCREATE - wxWindowCreateEvent event((wxWindow *)this); - (void)GetEventHandler()->ProcessEvent(event); - *mayCreate = true; return true; @@ -3538,6 +3636,20 @@ bool wxWindowMSW::HandleKillFocus(WXHWND hwnd) return GetEventHandler()->ProcessEvent(event); } +// --------------------------------------------------------------------------- +// labels +// --------------------------------------------------------------------------- + +void wxWindowMSW::SetLabel( const wxString& label) +{ + SetWindowText(GetHwnd(), label.c_str()); +} + +wxString wxWindowMSW::GetLabel() const +{ + return wxGetWindowText(GetHWND()); +} + // --------------------------------------------------------------------------- // miscellaneous // --------------------------------------------------------------------------- @@ -3688,6 +3800,69 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), return false; } +bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam), + WXLPARAM WXUNUSED(lParam), + bool *WXUNUSED_IN_WINCE(vetoed)) +{ +#ifdef __WXWINCE__ + // FIXME + return false; +#else + wxEventType evtType; + switch ( wParam ) + { + case PBT_APMQUERYSUSPEND: + evtType = wxEVT_POWER_SUSPENDING; + break; + + case PBT_APMQUERYSUSPENDFAILED: + evtType = wxEVT_POWER_SUSPEND_CANCEL; + break; + + case PBT_APMSUSPEND: + evtType = wxEVT_POWER_SUSPENDED; + break; + + case PBT_APMRESUMESUSPEND: + evtType = wxEVT_POWER_RESUME; + break; + + default: + wxLogDebug(_T("Unknown WM_POWERBROADCAST(%d) event"), wParam); + // fall through + + // these messages are currently not mapped to wx events + case PBT_APMQUERYSTANDBY: + case PBT_APMQUERYSTANDBYFAILED: + case PBT_APMSTANDBY: + case PBT_APMRESUMESTANDBY: + case PBT_APMBATTERYLOW: + case PBT_APMPOWERSTATUSCHANGE: + case PBT_APMOEMEVENT: +#ifdef PBT_APMRESUMEAUTOMATIC + case PBT_APMRESUMEAUTOMATIC: +#endif + case PBT_APMRESUMECRITICAL: + evtType = wxEVT_NULL; + break; + } + + // don't handle unknown messages + if ( evtType == wxEVT_NULL ) + return false; + + // TODO: notify about PBTF_APMRESUMEFROMFAILURE in case of resume events? + + wxPowerEvent event(evtType); + if ( !GetEventHandler()->ProcessEvent(event) ) + return false; + + *vetoed = event.IsVetoed(); + + return true; +#endif +} + // --------------------------------------------------------------------------- // owner drawn stuff // --------------------------------------------------------------------------- @@ -3903,6 +4078,30 @@ bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture) return GetEventHandler()->ProcessEvent(event); } +bool wxWindowMSW::HandleSettingChange(WXWPARAM wParam, WXLPARAM lParam) +{ + // despite MSDN saying "(This message cannot be sent directly to a window.)" + // we need to send this to child windows (it is only sent to top-level + // windows) so {list,tree}ctrls can adjust their font size if necessary + // this is exactly how explorer does it to enable the font size changes + + wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); + while ( node ) + { + // top-level windows already get this message from the system + wxWindow *win = node->GetData(); + if ( !win->IsTopLevel() ) + { + ::SendMessage(GetHwndOf(win), WM_SETTINGCHANGE, wParam, lParam); + } + + node = node->GetNext(); + } + + // let the system handle it + return false; +} + bool wxWindowMSW::HandleQueryNewPalette() { @@ -4079,14 +4278,11 @@ bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc) dc.SetHDC(hdc); dc.SetWindow((wxWindow *)this); - dc.BeginDrawing(); wxEraseEvent event(m_windowId, &dc); event.SetEventObject(this); bool rc = GetEventHandler()->ProcessEvent(event); - dc.EndDrawing(); - // must be called manually as ~wxDC doesn't do anything for wxDCTemp dc.SelectOldObjects(hdc); @@ -4645,7 +4841,7 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags) GenerateMouseLeave(); } } -#endif // HAVE_TRACKMOUSEEVENT +#endif // HAVE_TRACKMOUSEEVENT #if wxUSE_MOUSEEVENT_HACK // Windows often generates mouse events even if mouse position hasn't @@ -4803,35 +4999,14 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) 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. id = wParam; - if ( (id > 0) && (id < 27) ) - { - switch (id) - { - case 13: - id = WXK_RETURN; - break; - - case 8: - id = WXK_BACK; - break; - - case 9: - id = WXK_TAB; - break; - - default: - //ctrlDown = true; - break; - } - } } else // we're called from WM_KEYDOWN { - id = wxCharCodeMSWToWX(wParam, lParam); + // don't pass lParam to wxCharCodeMSWToWX() here because we don't want + // to get numpad key codes: CHAR events should use the logical keys + // such as WXK_HOME instead of WXK_NUMPAD_HOME which is for KEY events + id = wxCharCodeMSWToWX(wParam); if ( id == 0 ) { // it's ASCII and will be processed here only when called from @@ -4868,16 +5043,8 @@ bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) id = wParam; } - if ( id != -1 ) // VZ: does this ever happen (FIXME)? - { - wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam)); - if ( GetEventHandler()->ProcessEvent(event) ) - { - return true; - } - } - - return false; + wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam)); + return GetEventHandler()->ProcessEvent(event); } bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) @@ -4890,14 +5057,8 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) id = wParam; } - if ( id != -1 ) // VZ: does this ever happen (FIXME)? - { - wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam)); - if ( GetEventHandler()->ProcessEvent(event) ) - return true; - } - - return false; + wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam)); + return GetEventHandler()->ProcessEvent(event); } int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), @@ -4911,12 +5072,20 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), MENUITEMINFO mii; wxZeroMemory(mii); mii.cbSize = sizeof(MENUITEMINFO); + + // we could use MIIM_FTYPE here as we only need to know if the item is + // ownerdrawn or not and not dwTypeData which MIIM_TYPE also returns, but + // MIIM_FTYPE is not supported under Win95 mii.fMask = MIIM_TYPE | MIIM_DATA; // find if we have this letter in any owner drawn item const int count = ::GetMenuItemCount(hmenu); for ( int i = 0; i < count; i++ ) { + // previous loop iteration could modify it, reset it back before + // calling GetMenuItemInfo() to prevent it from overflowing dwTypeData + mii.cch = 0; + if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) ) { if ( mii.fType == MFT_OWNERDRAW ) @@ -4954,8 +5123,7 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), } else // failed to get the menu text? { - // it's not fatal, so don't show error, but still log - // it + // it's not fatal, so don't show error, but still log it wxLogLastError(_T("GetMenuItemInfo")); } } @@ -4963,6 +5131,18 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel), return wxNOT_FOUND; } +bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg ) +{ + const wxEventType type = ( nMsg == WM_CUT ) ? wxEVT_COMMAND_TEXT_CUT : + ( nMsg == WM_COPY ) ? wxEVT_COMMAND_TEXT_COPY : + /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE; + wxClipboardTextEvent evt(type, GetId()); + + evt.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(evt); +} + // --------------------------------------------------------------------------- // joystick // --------------------------------------------------------------------------- @@ -5166,6 +5346,18 @@ void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont& the_font) // the_font.ReleaseResource(); } +// use the "extended" bit (24) of lParam to distinguish extended keys +// from normal keys as the same key is sent +static inline +int ChooseNormalOrExtended(int lParam, int keyNormal, int keyExtended) +{ + // except that if lParam is 0, it means we don't have real lParam from + // WM_KEYDOWN but are just translating just a VK constant (e.g. done from + // msw/treectrl.cpp when processing TVN_KEYDOWN) -- then assume this is a + // non-numpad (hence extended) key as this is a more common case + return !lParam || (lParam & (1 << 24)) ? keyExtended : keyNormal; +} + // 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, WXLPARAM lParam) @@ -5184,19 +5376,9 @@ int wxCharCodeMSWToWX(int keySym, WXLPARAM lParam) case VK_CAPITAL: id = WXK_CAPITAL; break; case VK_SPACE: id = WXK_SPACE; break; case VK_ESCAPE: id = WXK_ESCAPE; break; - case VK_PRIOR: id = WXK_PRIOR; break; - case VK_NEXT : id = WXK_NEXT; break; - case VK_END: id = WXK_END; break; - case VK_HOME : id = WXK_HOME; break; - case VK_LEFT : id = WXK_LEFT; break; - case VK_UP: id = WXK_UP; break; - case VK_RIGHT: id = WXK_RIGHT; break; - case VK_DOWN : id = WXK_DOWN; break; case VK_SELECT: id = WXK_SELECT; break; case VK_PRINT: id = WXK_PRINT; break; case VK_EXECUTE: id = WXK_EXECUTE; break; - case VK_INSERT: id = WXK_INSERT; break; - case VK_DELETE: id = WXK_DELETE; break; case VK_HELP : id = WXK_HELP; break; case VK_NUMPAD0: id = WXK_NUMPAD0; break; case VK_NUMPAD1: id = WXK_NUMPAD1; break; @@ -5260,11 +5442,41 @@ int wxCharCodeMSWToWX(int keySym, WXLPARAM lParam) case VK_APPS: id = WXK_WINDOWS_MENU; break; #endif // VK_APPS defined + // handle extended keys + case VK_PRIOR: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEUP, WXK_PAGEUP); + break; + case VK_NEXT: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_PAGEDOWN, WXK_PAGEDOWN); + break; + case VK_END: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_END, WXK_END); + break; + case VK_HOME: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_HOME, WXK_HOME); + break; + case VK_LEFT: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_LEFT, WXK_LEFT); + break; + case VK_UP: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_UP, WXK_UP); + break; + case VK_RIGHT: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_RIGHT, WXK_RIGHT); + break; + case VK_DOWN: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DOWN, WXK_DOWN); + break; + case VK_INSERT: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_INSERT, WXK_INSERT); + break; + case VK_DELETE: + id = ChooseNormalOrExtended(lParam, WXK_NUMPAD_DELETE, WXK_DELETE); + break; 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; + // don't use ChooseNormalOrExtended() here as the keys are reversed + // here: numpad enter is the extended one + id = lParam && (lParam & (1 << 24)) ? WXK_NUMPAD_ENTER : WXK_RETURN; break; default: @@ -5287,8 +5499,8 @@ WXWORD wxCharCodeWXToMSW(int id, bool *isVirtual) case WXK_ALT: keySym = VK_MENU; break; case WXK_PAUSE: keySym = VK_PAUSE; break; case WXK_CAPITAL: keySym = VK_CAPITAL; break; - case WXK_PRIOR: keySym = VK_PRIOR; break; - case WXK_NEXT : keySym = VK_NEXT; break; + case WXK_PAGEUP: keySym = VK_PRIOR; break; + case WXK_PAGEDOWN: keySym = VK_NEXT; break; case WXK_END: keySym = VK_END; break; case WXK_HOME : keySym = VK_HOME; break; case WXK_LEFT : keySym = VK_LEFT; break; @@ -5386,6 +5598,28 @@ bool wxGetKeyState(wxKeyCode key) #endif } + +wxMouseState wxGetMouseState() +{ + wxMouseState ms; + POINT pt; + GetCursorPos( &pt ); + + ms.SetX(pt.x); + ms.SetY(pt.y); + ms.SetLeftDown( (GetAsyncKeyState(VK_LBUTTON) & (1<<15)) != 0 ); + ms.SetMiddleDown( (GetAsyncKeyState(VK_MBUTTON) & (1<<15)) != 0 ); + ms.SetRightDown( (GetAsyncKeyState(VK_RBUTTON) & (1<<15)) != 0 ); + + ms.SetControlDown( (GetAsyncKeyState(VK_CONTROL) & (1<<15)) != 0 ); + ms.SetShiftDown( (GetAsyncKeyState(VK_SHIFT) & (1<<15)) != 0 ); + ms.SetAltDown( (GetAsyncKeyState(VK_MENU) & (1<<15)) != 0 ); +// ms.SetMetaDown(); + + return ms; +} + + wxWindow *wxGetActiveWindow() { HWND hWnd = GetActiveWindow(); @@ -6194,4 +6428,3 @@ void wxWindowMSW::OnInitDialog( wxInitDialogEvent& event ) event.Skip(); } #endif -