X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3bce6687f47dfa5fb8d4bab92702a5b5b1eb3485..57fd9bb2394e62823417e6068f81a5afdbd47d92:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 5186088642..df95abf3a7 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -5,8 +5,8 @@ // Modified by: VZ on 13.05.99: no more Default(), MSWOnXXX() reorganisation // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Julian Smart +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // =========================================================================== @@ -58,6 +58,18 @@ #include "wx/dnd.h" #endif +#if wxUSE_ACCESSIBILITY + #include "wx/access.h" + #include + #include + #ifndef WM_GETOBJECT + #define WM_GETOBJECT 0x003D + #endif + #ifndef OBJID_CLIENT + #define OBJID_CLIENT 0xFFFFFFFC + #endif +#endif + #include "wx/menuitem.h" #include "wx/log.h" @@ -92,14 +104,16 @@ #include #endif -#if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) +#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__)) || defined(__CYGWIN10__) #ifdef __WIN95__ #include #endif #elif !defined(__WXMICROWIN__) // broken compiler - #ifndef __TWIN32__ - #include "wx/msw/gnuwin32/extra.h" - #endif + #include "wx/msw/gnuwin32/extra.h" +#endif + +#if defined(__GNUG__) +#include "wx/msw/missing.h" #endif // ---------------------------------------------------------------------------- @@ -125,10 +139,6 @@ #ifndef VK_OEM_1 #define VK_OEM_1 0xBA - #define VK_OEM_PLUS 0xBB - #define VK_OEM_COMMA 0xBC - #define VK_OEM_MINUS 0xBD - #define VK_OEM_PERIOD 0xBE #define VK_OEM_2 0xBF #define VK_OEM_3 0xC0 #define VK_OEM_4 0xDB @@ -137,6 +147,13 @@ #define VK_OEM_7 0xDE #endif +#ifndef VK_OEM_COMMA + #define VK_OEM_PLUS 0xBB + #define VK_OEM_COMMA 0xBC + #define VK_OEM_MINUS 0xBD + #define VK_OEM_PERIOD 0xBE +#endif + // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- @@ -162,12 +179,13 @@ static bool gs_hasStdCmap = FALSE; LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + #ifdef __WXDEBUG__ const char *wxGetMessageName(int message); #endif //__WXDEBUG__ void wxRemoveHandleAssociation(wxWindowMSW *win); -void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win); +extern void wxAssociateWinWithHandle(HWND hWnd, wxWindowMSW *win); wxWindow *wxFindWinFromHandle(WXHWND hWnd); // this magical function is used to translate VK_APPS key presses to right @@ -190,15 +208,13 @@ static inline void wxBringWindowToTop(HWND hwnd) // activate (set focus to) specified window ::SetFocus(hwnd); +#endif // raise top level parent to top of z order - ::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); -#else // !__WXMICROWIN__ - if ( !::BringWindowToTop(hwnd) ) + if (!::SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)) { - wxLogLastError(_T("BringWindowToTop")); + wxLogLastError(_T("SetWindowPos")); } -#endif // __WXMICROWIN__/!__WXMICROWIN__ } // --------------------------------------------------------------------------- @@ -217,7 +233,6 @@ 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() // =========================================================================== @@ -314,7 +329,6 @@ void wxWindowMSW::Init() // MSW specific m_isBeingDeleted = FALSE; m_oldWndProc = NULL; - m_useCtl3D = FALSE; m_mouseInWindow = FALSE; m_lastKeydownProcessed = FALSE; @@ -327,7 +341,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; @@ -394,17 +407,6 @@ bool wxWindowMSW::Create(wxWindow *parent, { wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") ); -#if wxUSE_STATBOX - // wxGTK doesn't allow to create controls with static box as the parent so - // this will result in a crash when the program is ported to wxGTK - warn - // about it - // - // the correct solution is to create the controls as siblings of the - // static box - wxASSERT_MSG( !wxDynamicCast(parent, wxStaticBox), - _T("wxStaticBox can't be used as a window parent!") ); -#endif // wxUSE_STATBOX - if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) return FALSE; @@ -469,8 +471,6 @@ void wxWindowMSW::SetFocus() void wxWindowMSW::SetFocusFromKbd() { - wxWindowBase::SetFocusFromKbd(); - // when the focus is given to the control with DLGC_HASSETSEL style from // keyboard its contents should be entirely selected: this is what // ::IsDialogMessage() does and so we should do it as well to provide the @@ -479,6 +479,11 @@ void wxWindowMSW::SetFocusFromKbd() { ::SendMessage(GetHwnd(), EM_SETSEL, 0, -1); } + + // do this after (maybe) setting the selection as like this when + // wxEVT_SET_FOCUS handler is called, the selection would have been already + // set correctly -- this may be important + wxWindowBase::SetFocusFromKbd(); } // Get the window with the focus @@ -502,6 +507,12 @@ bool wxWindowMSW::Enable(bool enable) if ( hWnd ) ::EnableWindow(hWnd, (BOOL)enable); + // the logic below doesn't apply to the top level windows -- otherwise + // showing a modal dialog would result in total greying out (and ungreying + // out later) of everything which would be really ugly + if ( IsTopLevel() ) + return TRUE; + // when the parent is disabled, all of its children should be disabled as // well but when it is enabled back, only those of the children which // hadn't been already disabled in the beginning should be enabled again, @@ -561,7 +572,7 @@ bool wxWindowMSW::Show(bool show) int cshow = show ? SW_SHOW : SW_HIDE; ::ShowWindow(hWnd, cshow); - if ( show ) + if ( show && IsTopLevel() ) { wxBringWindowToTop(hWnd); } @@ -680,11 +691,15 @@ void wxWindowMSW::MSWDeviceToLogical (float *x, float *y) const // scrolling stuff // --------------------------------------------------------------------------- +// convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT +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) { -#if defined(__WIN95__) - int range1 = range; // Try to adjust the range to cope with page size > 1 @@ -695,106 +710,31 @@ void wxWindowMSW::SetScrollRange(int orient, int range, bool refresh) range1 += (pageSize - 1); } - SCROLLINFO info; - int dir; - - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - } else { - dir = SB_VERT; - } - - info.cbSize = sizeof(SCROLLINFO); + WinStruct info; info.nPage = pageSize; // Have to set this, or scrollbar goes awry info.nMin = 0; info.nMax = range1; - info.nPos = 0; info.fMask = SIF_RANGE | SIF_PAGE; HWND hWnd = GetHwnd(); if ( hWnd ) - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollRange(hWnd, wOrient, 0, range, refresh); -#endif + ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh); } void wxWindowMSW::SetScrollPage(int orient, int page, bool refresh) { -#if defined(__WIN95__) - SCROLLINFO info; - int dir; - - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - m_xThumbSize = page; - } else { - dir = SB_VERT; - m_yThumbSize = page; - } - - info.cbSize = sizeof(SCROLLINFO); + WinStruct info; info.nPage = page; - info.nMin = 0; info.fMask = SIF_PAGE; HWND hWnd = GetHwnd(); if ( hWnd ) - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else - if ( orient == wxHORIZONTAL ) - m_xThumbSize = page; - else - m_yThumbSize = page; -#endif -} - -int wxWindowMSW::OldGetScrollRange(int orient) const -{ - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - -#if __WATCOMC__ && defined(__WINDOWS_386__) - short minPos, maxPos; -#else - int minPos, maxPos; -#endif - HWND hWnd = GetHwnd(); - if ( hWnd ) - { - ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos); -#if defined(__WIN95__) - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = GetScrollPage(orient); - if ( pageSize > 1 ) - { - maxPos -= (pageSize - 1); - } -#endif - return maxPos; - } - else - return 0; + ::SetScrollInfo(hWnd, wxDirToWinStyle(orient), &info, refresh); } int wxWindowMSW::GetScrollPage(int orient) const { - if ( orient == wxHORIZONTAL ) - return m_xThumbSize; - else - return m_yThumbSize; + return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize; } #endif // WXWIN_COMPATIBILITY @@ -810,61 +750,31 @@ inline int GetScrollPosition(HWND hWnd, int wOrient) int wxWindowMSW::GetScrollPos(int orient) const { - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - HWND hWnd = GetHwnd(); wxCHECK_MSG( hWnd, 0, _T("no HWND in GetScrollPos") ); - return GetScrollPosition(hWnd, wOrient); + return GetScrollPosition(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT); } // This now returns the whole range, not just the number // of positions that we can scroll. int wxWindowMSW::GetScrollRange(int orient) const { - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; - -#if __WATCOMC__ && defined(__WINDOWS_386__) - short minPos, maxPos; -#else int minPos, maxPos; -#endif HWND hWnd = GetHwnd(); - if ( hWnd ) - { - ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos); -#if defined(__WIN95__) - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = GetScrollThumb(orient); - if ( pageSize > 1 ) - { - maxPos -= (pageSize - 1); - } - // October 10th: new range concept. - maxPos += pageSize; -#endif - - return maxPos; - } - else + if ( !hWnd ) return 0; + + ::GetScrollRange(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &minPos, &maxPos); + + // undo "range - 1" done in SetScrollbar() + return maxPos + 1; } int wxWindowMSW::GetScrollThumb(int orient) const { - if ( orient == wxHORIZONTAL ) - return m_xThumbSize; - else - return m_yThumbSize; + return orient == wxHORIZONTAL ? m_xThumbSize : m_yThumbSize; } void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh) @@ -872,77 +782,48 @@ void wxWindowMSW::SetScrollPos(int orient, int pos, bool refresh) HWND hWnd = GetHwnd(); wxCHECK_RET( hWnd, _T("SetScrollPos: no HWND") ); - int dir = orient == wxHORIZONTAL ? SB_HORZ : SB_VERT; - -#if defined(__WIN95__) - SCROLLINFO info; - info.cbSize = sizeof(SCROLLINFO); + WinStruct info; info.nPage = 0; info.nMin = 0; info.nPos = pos; info.fMask = SIF_POS; - - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else // !__WIN95__ - ::SetScrollPos(hWnd, dir, pos, refresh); -#endif // __WIN95__/!__WIN95__ -} - -// New function that will replace some of the above. -void wxWindowMSW::SetScrollbar(int orient, int pos, int thumbVisible, - int range, bool refresh) -{ -#if defined(__WIN95__) - int oldRange = range - thumbVisible; - - int range1 = oldRange; - - // Try to adjust the range to cope with page size > 1 - // - a Windows API quirk - int pageSize = thumbVisible; - if ( pageSize > 1 && range > 0) + if ( HasFlag(wxALWAYS_SHOW_SB) ) { - range1 += (pageSize - 1); + // disable scrollbar instead of removing it then + info.fMask |= SIF_DISABLENOSCROLL; } - SCROLLINFO info; - int dir; - - if ( orient == wxHORIZONTAL ) { - dir = SB_HORZ; - } else { - dir = SB_VERT; - } + ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &info, refresh); +} - info.cbSize = sizeof(SCROLLINFO); - info.nPage = pageSize; // Have to set this, or scrollbar goes awry - info.nMin = 0; - info.nMax = range1; +// New function that will replace some of the above. +void wxWindowMSW::SetScrollbar(int orient, + int pos, + int pageSize, + int range, + bool refresh) +{ + WinStruct info; + info.nPage = pageSize; + info.nMin = 0; // range is nMax - nMin + 1 + info.nMax = range - 1; // as both nMax and nMax are inclusive info.nPos = pos; info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; - - HWND hWnd = GetHwnd(); - if ( hWnd ) - ::SetScrollInfo(hWnd, dir, &info, refresh); -#else - int wOrient; - if ( orient == wxHORIZONTAL ) - wOrient = SB_HORZ; - else - wOrient = SB_VERT; + if ( HasFlag(wxALWAYS_SHOW_SB) ) + { + // disable scrollbar instead of removing it then + info.fMask |= SIF_DISABLENOSCROLL; + } HWND hWnd = GetHwnd(); if ( hWnd ) { - ::SetScrollRange(hWnd, wOrient, 0, range, FALSE); - ::SetScrollPos(hWnd, wOrient, pos, refresh); - } -#endif - if ( orient == wxHORIZONTAL ) { - m_xThumbSize = thumbVisible; - } else { - m_yThumbSize = thumbVisible; + ::SetScrollInfo(hWnd, orient == wxHORIZONTAL ? SB_HORZ : SB_VERT, + &info, refresh); } + + *(orient == wxHORIZONTAL ? &m_xThumbSize : &m_yThumbSize) = pageSize; } void wxWindowMSW::ScrollWindow(int dx, int dy, const wxRect *prect) @@ -1140,7 +1021,7 @@ void wxWindowMSW::SetWindowStyleFlag(long flags) WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const { // translate the style - WXDWORD style = WS_CHILD; + WXDWORD style = WS_CHILD | WS_VISIBLE; if ( flags & wxCLIP_CHILDREN ) style |= WS_CLIPCHILDREN; @@ -1148,8 +1029,16 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const if ( flags & wxCLIP_SIBLINGS ) style |= WS_CLIPSIBLINGS; - wxBorder border = (wxBorder)(flags & wxBORDER_MASK); - if ( border != wxBORDER_NONE && border != wxBORDER_DEFAULT ) + if ( flags & wxVSCROLL ) + style |= WS_VSCROLL; + + if ( flags & wxHSCROLL ) + style |= WS_HSCROLL; + + const wxBorder border = GetBorder(flags); + + // WS_BORDER is only required for wxBORDER_SIMPLE + if ( border == wxBORDER_SIMPLE ) style |= WS_BORDER; // now deal with ext style if the caller wants it @@ -1160,15 +1049,15 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const if ( flags & wxTRANSPARENT_WINDOW ) *exstyle |= WS_EX_TRANSPARENT; - switch ( flags & wxBORDER_MASK ) + 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: @@ -1176,11 +1065,12 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const break; case wxBORDER_RAISED: - *exstyle |= WS_EX_WINDOWEDGE; + *exstyle |= WS_EX_DLGMODALFRAME; break; case wxBORDER_SUNKEN: *exstyle |= WS_EX_CLIENTEDGE; + style &= ~WS_BORDER; break; case wxBORDER_DOUBLE: @@ -1202,94 +1092,6 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const return style; } -// Make a Windows extended style from the given wxWindows window style -WXDWORD wxWindowMSW::MakeExtendedStyle(long style, bool eliminateBorders) -{ - WXDWORD exStyle = 0; - if ( style & wxTRANSPARENT_WINDOW ) - exStyle |= WS_EX_TRANSPARENT; - - if ( !eliminateBorders ) - { - if ( style & wxSUNKEN_BORDER ) - exStyle |= WS_EX_CLIENTEDGE; - if ( style & wxDOUBLE_BORDER ) - exStyle |= WS_EX_DLGMODALFRAME; -#if defined(__WIN95__) - if ( style & wxRAISED_BORDER ) - // It seems that WS_EX_WINDOWEDGE doesn't work, but WS_EX_DLGMODALFRAME does - exStyle |= WS_EX_DLGMODALFRAME; /* WS_EX_WINDOWEDGE */; - if ( style & wxSTATIC_BORDER ) - exStyle |= WS_EX_STATICEDGE; -#endif - } - - return exStyle; -} - -// Determines whether native 3D effects or CTL3D should be used, -// applying a default border style if required, and returning an extended -// style to pass to CreateWindowEx. -WXDWORD wxWindowMSW::Determine3DEffects(WXDWORD defaultBorderStyle, - bool *want3D) const -{ - // If matches certain criteria, then assume no 3D effects - // unless specifically requested (dealt with in MakeExtendedStyle) - if ( !GetParent() -#if wxUSE_CONTROLS - || !IsKindOf(CLASSINFO(wxControl)) -#endif // wxUSE_CONTROLS - || (m_windowStyle & wxNO_BORDER) ) - { - *want3D = FALSE; - return MakeExtendedStyle(m_windowStyle); - } - - // Determine whether we should be using 3D effects or not. - bool nativeBorder = FALSE; // by default, we don't want a Win95 effect - - // 1) App can specify global 3D effects - *want3D = wxTheApp->GetAuto3D(); - - // 2) If the parent is being drawn with user colours, or simple border specified, - // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D - if ( GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) || (m_windowStyle & wxSIMPLE_BORDER) ) - *want3D = FALSE; - - // 3) Control can override this global setting by defining - // a border style, e.g. wxSUNKEN_BORDER - if ( m_windowStyle & wxSUNKEN_BORDER ) - *want3D = TRUE; - - // 4) If it's a special border, CTL3D can't cope so we want a native border - if ( (m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER) || - (m_windowStyle & wxSTATIC_BORDER) ) - { - *want3D = TRUE; - nativeBorder = TRUE; - } - - // 5) If this isn't a Win95 app, and we are using CTL3D, remove border - // effects from extended style -#if wxUSE_CTL3D - if ( *want3D ) - nativeBorder = FALSE; -#endif - - DWORD exStyle = MakeExtendedStyle(m_windowStyle, !nativeBorder); - - // If we want 3D, but haven't specified a border here, - // apply the default border style specified. - // TODO what about non-Win95 WIN32? Does it have borders? -#if defined(__WIN95__) && !wxUSE_CTL3D - if ( defaultBorderStyle && (*want3D) && ! ((m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER ) || - (m_windowStyle & wxSTATIC_BORDER) || (m_windowStyle & wxSIMPLE_BORDER) )) - exStyle |= defaultBorderStyle; // WS_EX_CLIENTEDGE; -#endif - - return exStyle; -} - #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 @@ -1343,7 +1145,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 ) @@ -1356,7 +1158,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() ) @@ -1389,7 +1191,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'. @@ -1457,16 +1260,12 @@ void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect) void wxWindowMSW::Update() { -#ifdef __WXWINE__ - ::UpdateWindow(GetHwnd()); -#else if ( !::UpdateWindow(GetHwnd()) ) { wxLogLastError(_T("UpdateWindow")); } -#endif - -#if defined(__WIN32__) && !defined(__WXMICROWIN__) + +#if !defined(__WXMICROWIN__) // just calling UpdateWindow() is not enough, what we did in our WM_PAINT // handler needs to be really drawn right now (void)::GdiFlush(); @@ -1477,8 +1276,8 @@ void wxWindowMSW::Update() // drag and drop // --------------------------------------------------------------------------- -#if wxUSE_DRAG_AND_DROP +#if wxUSE_DRAG_AND_DROP void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget) { if ( m_dropTarget != 0 ) { @@ -1490,7 +1289,6 @@ void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget) if ( m_dropTarget != 0 ) m_dropTarget->Register(m_hWnd); } - #endif // wxUSE_DRAG_AND_DROP // old style file-manager drag&drop support: we retain the old-style @@ -1513,7 +1311,7 @@ void wxWindowMSW::DoSetToolTip(wxToolTip *tooltip) wxWindowBase::DoSetToolTip(tooltip); if ( m_tooltip ) - m_tooltip->SetWindow(this); + m_tooltip->SetWindow((wxWindow *)this); } #endif // wxUSE_TOOLTIPS @@ -1885,6 +1683,10 @@ static void wxYieldForCommandsOnly() { wxTheApp->DoMessage((WXMSG *)&msg); } + + // If we retrieved a WM_QUIT, insert back into the message queue. + if (msg.message == WM_QUIT) + ::PostQuitMessage(0); } bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) @@ -1955,6 +1757,14 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) if ( !bCtrlDown ) { lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0); + + // surprizingly, DLGC_WANTALLKEYS bit mask doesn't contain the + // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, + // it, of course, implies them + if ( lDlgCode & DLGC_WANTALLKEYS ) + { + lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS; + } } bool bForward = TRUE, @@ -2044,6 +1854,12 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // eat the Enter events sometimes return FALSE; } + else if (!IsTopLevel()) + { + // if not a top level window, let parent + // handle it + return FALSE; + } //else: treat Enter as TAB: pass to the next // control as this is the best thing to do // if the text doesn't handle Enter itself @@ -2106,34 +1922,74 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) // place edit control from being closed with Escape in a dialog if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE ) { - // ::IsDialogMessage() can enter in an infinite loop when the - // currently focused window is disabled or hidden and its parent - // has WS_EX_CONTROLPARENT style, so don't call it in this case + // ::IsDialogMessage() is broken and may sometimes hang the + // application by going into an infinite loop, so we try to detect + // [some of] the situatations when this may happen and not call it + // then + + // assume we can call it by default bool canSafelyCallIsDlgMsg = TRUE; HWND hwndFocus = ::GetFocus(); - while ( hwndFocus ) + + // if the currently focused window itself has WS_EX_CONTROLPARENT style, ::IsDialogMessage() will also enter + // an infinite loop, because it will recursively check the child + // windows but not the window itself and so if none of the children + // accepts focus it loops forever (as it only stops when it gets + // back to the window it started from) + // + // while it is very unusual that a window with WS_EX_CONTROLPARENT + // style has the focus, it can happen. One such possibility is if + // all windows are either toplevel, wxDialog, wxPanel or static + // controls and no window can actually accept keyboard input. + if ( ::GetWindowLong(hwndFocus, GWL_EXSTYLE) & WS_EX_CONTROLPARENT ) { - if ( !::IsWindowEnabled(hwndFocus) || - !::IsWindowVisible(hwndFocus) ) + // passimistic by default + canSafelyCallIsDlgMsg = FALSE; + for ( wxWindowList::Node *node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) { - // it would enter an infinite loop if we do this! - canSafelyCallIsDlgMsg = FALSE; + if ( node->GetData()->AcceptsFocus() ) + { + // it shouldn't hang... + canSafelyCallIsDlgMsg = TRUE; - break; + break; + } } + } - if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) ) + if ( canSafelyCallIsDlgMsg ) + { + // ::IsDialogMessage() can enter in an infinite loop when the + // currently focused window is disabled or hidden and its + // parent has WS_EX_CONTROLPARENT style, so don't call it in + // this case + while ( hwndFocus ) { - // it's a top level window, don't go further -- e.g. even - // if the parent of a dialog is disabled, this doesn't - // break navigation inside the dialog - break; - } + if ( !::IsWindowEnabled(hwndFocus) || + !::IsWindowVisible(hwndFocus) ) + { + // it would enter an infinite loop if we do this! + canSafelyCallIsDlgMsg = FALSE; - hwndFocus = ::GetParent(hwndFocus); + break; + } + + if ( !(::GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD) ) + { + // it's a top level window, don't go further -- e.g. even + // if the parent of a dialog is disabled, this doesn't + // break navigation inside the dialog + break; + } + + hwndFocus = ::GetParent(hwndFocus); + } } + // let IsDialogMessage() have the message if it's safe to call it if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) ) { // IsDialogMessage() did something... @@ -2173,11 +2029,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) { @@ -2220,50 +2074,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 // --------------------------------------------------------------------------- @@ -2289,8 +2099,9 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w { // trace all messages - useful for the debugging #ifdef __WXDEBUG__ - wxLogTrace(wxTraceMessages, wxT("Processing %s(wParam=%8lx, lParam=%8lx)"), - wxGetMessageName(message), (long) wParam, lParam); + wxLogTrace(wxTraceMessages, + wxT("Processing %s(hWnd=%08lx, wParam=%8lx, lParam=%8lx)"), + wxGetMessageName(message), (long)hWnd, (long)wParam, lParam); #endif // __WXDEBUG__ wxWindowMSW *wnd = wxFindWinFromHandle((WXHWND) hWnd); @@ -2358,6 +2169,24 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = HandleMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; + case WM_MOVING: + { + LPRECT pRect = (LPRECT)lParam; + wxRect rc; + rc.SetLeft(pRect->left); + rc.SetTop(pRect->top); + rc.SetRight(pRect->right); + rc.SetBottom(pRect->bottom); + processed = HandleMoving(rc); + if (processed) { + pRect->left = rc.GetLeft(); + pRect->top = rc.GetTop(); + pRect->right = rc.GetRight(); + pRect->bottom = rc.GetBottom(); + } + } + break; + case WM_SIZE: switch ( wParam ) { @@ -2386,6 +2215,24 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; + case WM_SIZING: + { + LPRECT pRect = (LPRECT)lParam; + wxRect rc; + rc.SetLeft(pRect->left); + rc.SetTop(pRect->top); + rc.SetRight(pRect->right); + rc.SetBottom(pRect->bottom); + processed = HandleSizing(rc); + if (processed) { + pRect->left = rc.GetLeft(); + pRect->top = rc.GetTop(); + pRect->right = rc.GetRight(); + pRect->bottom = rc.GetBottom(); + } + } + break; + #ifndef __WXMICROWIN__ case WM_ACTIVATEAPP: wxTheApp->SetActive(wParam != 0, FindFocus()); @@ -2477,14 +2324,6 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam break; #endif // __WXMICROWIN__ - // VZ: if you find a situation when this is needed, tell - // me about it, do *not* uncomment this code as it - // causes other strange problems -#if 0 - if ( message == WM_LBUTTONDOWN && AcceptsFocus() ) - SetFocus(); -#endif // 0 - int x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam); @@ -2500,6 +2339,20 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam else { win = FindWindowForMouseEvent(this, &x, &y); + + // this should never happen + wxCHECK_MSG( win, 0, + _T("FindWindowForMouseEvent() returned NULL") ); + + // for the standard classes their WndProc sets the focus to + // them anyhow and doing it from here results in some weird + // problems, but for our windows we want them to acquire + // focus when clicked + if ( !win->IsOfStandardClass() ) + { + if ( message == WM_LBUTTONDOWN && win->AcceptsFocus() ) + win->SetFocus(); + } } processed = win->HandleMouseEvent(message, x, y, wParam); @@ -2592,71 +2445,73 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam if ( m_lastKeydownProcessed ) { processed = TRUE; - break; } - switch ( wParam ) + if ( !processed ) { - // we consider these message "not interesting" to OnChar, so - // just don't do anything more with them - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - case VK_CAPITAL: - case VK_NUMLOCK: - case VK_SCROLL: - processed = TRUE; - break; - - // avoid duplicate messages to OnChar for these ASCII keys: - // they will be translated by TranslateMessage() and received - // in WM_CHAR - case VK_ESCAPE: - case VK_SPACE: - case VK_RETURN: - case VK_BACK: - case VK_TAB: - case VK_ADD: - case VK_SUBTRACT: - case VK_MULTIPLY: - case VK_DIVIDE: - case VK_OEM_1: - case VK_OEM_2: - case VK_OEM_3: - case VK_OEM_4: - case VK_OEM_5: - case VK_OEM_6: - case VK_OEM_7: - case VK_OEM_PLUS: - case VK_OEM_COMMA: - case VK_OEM_MINUS: - case VK_OEM_PERIOD: - // but set processed to FALSE, not TRUE to still pass them - // to the control's default window proc - otherwise - // built-in keyboard handling won't work - processed = FALSE; + switch ( wParam ) + { + // we consider these message "not interesting" to OnChar, so + // just don't do anything more with them + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + case VK_CAPITAL: + case VK_NUMLOCK: + case VK_SCROLL: + processed = TRUE; + break; - break; + // avoid duplicate messages to OnChar for these ASCII keys: + // they will be translated by TranslateMessage() and received + // in WM_CHAR + case VK_ESCAPE: + case VK_SPACE: + case VK_RETURN: + case VK_BACK: + case VK_TAB: + case VK_ADD: + case VK_SUBTRACT: + case VK_MULTIPLY: + case VK_DIVIDE: + case VK_OEM_1: + case VK_OEM_2: + case VK_OEM_3: + case VK_OEM_4: + case VK_OEM_5: + case VK_OEM_6: + case VK_OEM_7: + case VK_OEM_PLUS: + case VK_OEM_COMMA: + case VK_OEM_MINUS: + case VK_OEM_PERIOD: + // but set processed to FALSE, not TRUE to still pass them + // to the control's default window proc - otherwise + // built-in keyboard handling won't work + processed = FALSE; + break; #ifdef VK_APPS - // special case of VK_APPS: treat it the same as right mouse - // click because both usually pop up a context menu - case VK_APPS: - { - WPARAM flags; - int x, y; + // special case of VK_APPS: treat it the same as right mouse + // click because both usually pop up a context menu + case VK_APPS: + { + WPARAM flags; + int x, y; - TranslateKbdEventToMouse(this, &x, &y, &flags); - processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags); - } - break; + TranslateKbdEventToMouse(this, &x, &y, &flags); + processed = HandleMouseEvent(WM_RBUTTONDOWN, x, y, flags); + } + break; #endif // VK_APPS - default: - // do generate a CHAR event - processed = HandleChar((WORD)wParam, lParam); - + default: + // do generate a CHAR event + processed = HandleChar((WORD)wParam, lParam); + } } + if (message == WM_SYSKEYDOWN) // Let Windows still handle the SYSKEYs + processed = FALSE; break; case WM_SYSKEYUP: @@ -2694,6 +2549,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: { @@ -2710,7 +2571,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: @@ -2718,9 +2578,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; @@ -2808,7 +2665,21 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; -#if defined(__WIN32__) && defined(WM_HELP) +#if wxUSE_ACCESSIBILITY + case WM_GETOBJECT: + { + //WPARAM dwFlags = (WPARAM) (DWORD) wParam; + LPARAM dwObjId = (LPARAM) (DWORD) lParam; + + if (dwObjId == OBJID_CLIENT && GetOrCreateAccessible()) + { + return LresultFromObject(IID_IAccessible, wParam, (IUnknown*) GetAccessible()->GetIAccessible()); + } + break; + } +#endif + +#if defined(WM_HELP) case WM_HELP: { HELPINFO* info = (HELPINFO*) lParam; @@ -2855,7 +2726,21 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = GetEventHandler()->ProcessEvent(evtCtx); } break; -#endif // __WIN32__ + + case WM_MENUCHAR: + // we're only interested in our own menus, not MF_SYSMENU + if ( HIWORD(wParam) == MF_POPUP ) + { + // handle menu chars for ownerdrawn menu items + int i = HandleMenuChar(toupper(LOWORD(wParam)), lParam); + if ( i != wxNOT_FOUND ) + { + rc.result = MAKELRESULT(i, MNC_EXECUTE); + processed = TRUE; + } + } + break; +#endif } if ( !processed ) @@ -3016,7 +2901,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, ( extendedStyle, className, - title ? title : wxT(""), + title ? title : wxEmptyString, style, x, y, w, h, (HWND)MSWGetParent(), @@ -3110,36 +2995,22 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code, LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; +#if !wxUSE_UNICODE if ( code == (WXUINT) TTN_NEEDTEXTA ) { - ttText->lpszText = (wxChar *)ttip.c_str(); + // we pass just the pointer as we store the string internally anyhow + ttText->lpszText = (char *)ttip.c_str(); } - else + else // TTN_NEEDTEXTW +#endif // !Unicode { #if wxUSE_UNICODE + // in Unicode mode this is just what we need ttText->lpszText = (wxChar *)ttip.c_str(); #else // !Unicode - size_t lenAnsi = ttip.length(); - - // some compilers (MetroWerks and Cygwin) don't like calling mbstowcs - // with NULL argument - #if defined( __MWERKS__ ) || defined( __CYGWIN__ ) - size_t lenUnicode = 2*lenAnsi; - #else - size_t lenUnicode = mbstowcs(NULL, ttip, lenAnsi); - #endif - - // using the pointer of right type avoids us doing all sorts of - // pointer arithmetics ourselves - wchar_t *dst = (wchar_t *)ttText->szText, - *pwz = new wchar_t[lenUnicode + 1]; - mbstowcs(pwz, ttip, lenAnsi + 1); - memcpy(dst, pwz, lenUnicode*sizeof(wchar_t)); - - // put the terminating wide NUL - dst[lenUnicode] = L'\0'; - - delete [] pwz; + MultiByteToWideChar(CP_ACP, 0, ttip, ttip.length()+1, + (wchar_t *)ttText->szText, + sizeof(ttText->szText) / sizeof(wchar_t)); #endif // Unicode/!Unicode } @@ -3252,8 +3123,7 @@ bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate) bool wxWindowMSW::HandleDestroy() { - wxWindowDestroyEvent event((wxWindow *)this); - (void)GetEventHandler()->ProcessEvent(event); + SendDestroyEvent(); // delete our drop target if we've got one #if wxUSE_DRAG_AND_DROP @@ -3377,7 +3247,9 @@ bool wxWindowMSW::HandleInitDialog(WXHWND WXUNUSED(hWndFocus)) bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) { -#ifndef __WXMICROWIN__ +#if defined (__WXMICROWIN__) + return FALSE; +#else // __WXMICROWIN__ HDROP hFilesInfo = (HDROP) wParam; // Get the total number of files dropped @@ -3412,11 +3284,10 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam) event.m_pos.y = dropPoint.y; return GetEventHandler()->ProcessEvent(event); -#else // __WXMICROWIN__ - return FALSE; #endif } + bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), short nHitTest, int WXUNUSED(mouseMsg)) @@ -3440,15 +3311,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; @@ -3493,6 +3359,8 @@ bool wxWindowMSW::HandleSetCursor(WXHWND WXUNUSED(hWnd), if ( hcursor ) { +// wxLogDebug("HandleSetCursor: Setting cursor %ld", (long) hcursor); + ::SetCursor(hcursor); // cursor set, stop here @@ -3538,16 +3406,24 @@ bool wxWindowMSW::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct) } #endif // wxUSE_MENUS_NATIVE +#endif // USE_OWNER_DRAWN + #if wxUSE_CONTROLS + +#if wxUSE_OWNER_DRAWN wxWindow *item = FindItem(id); if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) - { return ((wxControl *)item)->MSWOnDraw(itemStruct); - } -#endif // wxUSE_CONTROLS - +#elif !defined(__WXUNIVERSAL__) + // 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); #endif // USE_OWNER_DRAWN +#endif // wxUSE_CONTROLS + return FALSE; } @@ -3840,7 +3716,9 @@ extern wxCOLORMAP *wxGetStdColourMap() bool wxWindowMSW::HandlePaint() { -#ifdef __WIN32__ +// if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) +// return FALSE; + HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle if ( !hRegion ) wxLogLastError(wxT("CreateRectRgn")); @@ -3848,14 +3726,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); @@ -3892,6 +3762,29 @@ bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc) if ( ::IsIconic(GetHwnd()) ) return TRUE; +#if 0 + if (GetParent() && GetParent()->GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) + { + return FALSE; + } + + if (GetExtraStyle() & wxWS_EX_THEMED_BACKGROUND) + { + if (wxUxThemeEngine::Get()) + { + WXHTHEME hTheme = wxUxThemeEngine::Get()->m_pfnOpenThemeData(GetHWND(), L"TAB"); + if (hTheme) + { + WXURECT rect; + ::GetClientRect((HWND) GetHWND(), (RECT*) & rect); + wxUxThemeEngine::Get()->m_pfnDrawThemeBackground(hTheme, hdc, 10 /* TABP_BODY */, 0, &rect, &rect); + wxUxThemeEngine::Get()->m_pfnCloseThemeData(hTheme); + return TRUE; + } + } + } +#endif + wxDCTemp dc(hdc); dc.SetHDC(hdc); @@ -3959,6 +3852,17 @@ bool wxWindowMSW::HandleMove(int x, int y) return GetEventHandler()->ProcessEvent(event); } +bool wxWindowMSW::HandleMoving(wxRect& rect) +{ + wxMoveEvent event(rect, m_windowId); + event.SetEventObject(this); + + bool rc = GetEventHandler()->ProcessEvent(event); + if (rc) + rect = event.GetRect(); + return rc; +} + bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), WXUINT WXUNUSED(flag)) { @@ -3971,6 +3875,17 @@ bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), return GetEventHandler()->ProcessEvent(event); } +bool wxWindowMSW::HandleSizing(wxRect& rect) +{ + wxSizeEvent event(rect, m_windowId); + event.SetEventObject(this); + + bool rc = GetEventHandler()->ProcessEvent(event); + if (rc) + rect = event.GetRect(); + return rc; +} + bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) { MINMAXINFO *info = (MINMAXINFO *)mmInfo; @@ -4110,7 +4025,10 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event, event.m_leftDown = (flags & MK_LBUTTON) != 0; event.m_middleDown = (flags & MK_MBUTTON) != 0; event.m_rightDown = (flags & MK_RBUTTON) != 0; - event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; + // event.m_altDown = (::GetKeyState(VK_MENU) & 0x80000000) != 0; + // Returns different negative values on WinME and WinNT, + // so simply test for negative value. + event.m_altDown = ::GetKeyState(VK_MENU) < 0; event.SetTimestamp(s_currentMsg.time); event.m_eventObject = this; @@ -4143,7 +4061,6 @@ static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) // HWND hwnd = GetHwndOf(win), hwndUnderMouse; -#ifdef __WIN32__ hwndUnderMouse = ::ChildWindowFromPointEx ( hwnd, @@ -4154,7 +4071,6 @@ static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) // ); if ( !hwndUnderMouse || hwndUnderMouse == hwnd ) -#endif // __WIN32__ { // now try any child window at all hwndUnderMouse = ::ChildWindowFromPoint(hwnd, pt); @@ -4257,7 +4173,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 ) { @@ -4271,10 +4186,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); @@ -4372,9 +4283,18 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) } wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam, wParam)); - if ( ctrlDown ) + + // the alphanumeric keys produced by pressing AltGr+something on European + // keyboards have both Ctrl and Alt modifiers which may confuse the user + // code as, normally, keys with Ctrl and/or Alt don't result in anything + // alphanumeric, so pretend that there are no modifiers at all (the + // KEY_DOWN event would still have the correct modifiers if they're really + // needed) + if ( event.m_controlDown && event.m_altDown && + (id >= 32 && id < 256) ) { - event.m_controlDown = TRUE; + event.m_controlDown = + event.m_altDown = FALSE; } return GetEventHandler()->ProcessEvent(event); @@ -4422,6 +4342,65 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) return FALSE; } +int wxWindowMSW::HandleMenuChar(int chAccel, WXLPARAM lParam) +{ + const HMENU hmenu = (HMENU)lParam; + + MENUITEMINFO mii; + wxZeroMemory(mii); + mii.cbSize = sizeof(MENUITEMINFO); + 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++ ) + { + if ( ::GetMenuItemInfo(hmenu, i, TRUE, &mii) ) + { + if ( mii.fType == MFT_OWNERDRAW ) + { + // dwItemData member of the MENUITEMINFO is a + // pointer to the associated wxMenuItem -- see the + // menu creation code + wxMenuItem *item = (wxMenuItem*)mii.dwItemData; + + const wxChar *p = wxStrchr(item->GetText(), _T('&')); + while ( p++ ) + { + if ( *p == _T('&') ) + { + // this is not the accel char, find the real one + p = wxStrchr(p + 1, _T('&')); + } + else // got the accel char + { + // FIXME-UNICODE: this comparison doesn't risk to work + // for non ASCII accelerator characters I'm afraid, but + // what can we do? + if ( wxToupper(*p) == chAccel ) + { + return i; + } + else + { + // this one doesn't match + break; + } + } + } + } + } + else // failed to get the menu text? + { + // it's not fatal, so don't show error, but still log + // it + wxLogLastError(_T("GetMenuItemInfo")); + } + } + + return wxNOT_FOUND; +} + // --------------------------------------------------------------------------- // joystick // --------------------------------------------------------------------------- @@ -4557,16 +4536,13 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, case SB_THUMBPOSITION: case SB_THUMBTRACK: -#ifdef __WIN32__ // under Win32, the scrollbar range and position are 32 bit integers, // but WM_[HV]SCROLL only carry the low 16 bits of them, so we must // explicitly query the scrollbar for the correct position (this must // be done only for these two SB_ events as they are the only one // carrying the scrollbar position) { - SCROLLINFO scrollInfo; - wxZeroMemory(scrollInfo); - scrollInfo.cbSize = sizeof(SCROLLINFO); + WinStruct scrollInfo; scrollInfo.fMask = SIF_TRACKPOS; if ( !::GetScrollInfo(GetHwnd(), @@ -4579,7 +4555,6 @@ bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, event.SetPosition(scrollInfo.nTrackPos); } -#endif // Win32 event.m_eventType = wParam == SB_THUMBPOSITION ? wxEVT_SCROLLWIN_THUMBRELEASE @@ -4714,6 +4689,12 @@ int wxCharCodeMSWToWX(int keySym) case VK_OEM_6: id = ']'; break; case VK_OEM_7: id = '\''; break; +#ifdef VK_APPS + case VK_LWIN: id = WXK_WINDOWS_LEFT; break; + case VK_RWIN: id = WXK_WINDOWS_RIGHT; break; + case VK_APPS: id = WXK_WINDOWS_MENU; break; +#endif // VK_APPS defined + default: id = 0; } @@ -4821,9 +4802,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 @@ -4843,8 +4821,6 @@ extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd) win = wxSpinCtrl::GetSpinForTextCtrl((WXHWND)hwnd); } #endif // wxUSE_SPINCTRL - -#endif // Win32 } } @@ -4889,23 +4865,13 @@ void wxSetKeyboardHook(bool doIt) wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance()); wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(), -#if defined(__WIN32__) && !defined(__TWIN32__) GetCurrentThreadId() // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right? -#else - GetCurrentTask() -#endif ); } else { UnhookWindowsHookEx(wxTheKeyboardHook); - - // avoids warning about statement with no effect (FreeProcInstance - // doesn't do anything under Win32) -#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32__) && !defined(__NT__) && !defined(__GNUWIN32__) - FreeProcInstance(wxTheKeyboardHookProc); -#endif } } @@ -5013,7 +4979,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"; @@ -5029,7 +4994,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"; @@ -5058,11 +5022,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"; @@ -5090,14 +5052,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"; @@ -5112,7 +5072,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"; @@ -5121,7 +5080,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"; @@ -5141,8 +5099,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 @@ -5364,8 +5324,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); @@ -5428,9 +5386,10 @@ static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win) // Find the wxWindow at the current mouse position, returning the mouse // position. -wxWindow* wxFindWindowAtPointer(wxPoint& WXUNUSED(pt)) +wxWindow* wxFindWindowAtPointer(wxPoint& pt) { - return wxFindWindowAtPoint(wxGetMousePosition()); + pt = wxGetMousePosition(); + return wxFindWindowAtPoint(pt); } wxWindow* wxFindWindowAtPoint(const wxPoint& pt) @@ -5461,3 +5420,57 @@ 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 +