X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e7dda1ffa3db91707f2a554fc3c8dffa34e0e510..2d956b58023a4955313a1c1531bc70a0deb0b831:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index d414c9dc3d..77589902e5 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -102,6 +102,10 @@ #endif #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 @@ -117,6 +121,20 @@ #ifndef SPI_GETWHEELSCROLLLINES #define SPI_GETWHEELSCROLLLINES 104 #endif +#endif // wxUSE_MOUSEWHEEL + +#ifndef VK_OEM_1 + #define VK_OEM_1 0xBA + #define VK_OEM_PLUS 0xBB + #define VK_OEM_COMMA 0xBC + #define VK_OEM_MINUS 0xBD + #define VK_OEM_PERIOD 0xBE + #define VK_OEM_2 0xBF + #define VK_OEM_3 0xC0 + #define VK_OEM_4 0xDB + #define VK_OEM_5 0xDC + #define VK_OEM_6 0xDD + #define VK_OEM_7 0xDE #endif // --------------------------------------------------------------------------- @@ -297,6 +315,7 @@ void wxWindowMSW::Init() m_oldWndProc = 0; m_useCtl3D = FALSE; m_mouseInWindow = FALSE; + m_lastKeydownProcessed = FALSE; // wxWnd m_hMenu = 0; @@ -386,45 +405,27 @@ bool wxWindowMSW::Create(wxWindow *parent, parent->AddChild(this); - // all windows are created visible - DWORD msflags = WS_CHILD | WS_VISIBLE; + // note that all windows are created visible by default + WXDWORD exstyle; + DWORD msflags = WS_VISIBLE | MSWGetCreateWindowFlags(&exstyle); #ifdef __WXUNIVERSAL__ - // no 3d effects, we draw them ourselves - WXDWORD exStyle = 0; -#else // !wxUniversal - if ( style & wxCLIP_CHILDREN ) - msflags |= WS_CLIPCHILDREN; - if ( style & wxCLIP_SIBLINGS ) - msflags |= WS_CLIPSIBLINGS; - - bool want3D; - WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D); - - // Even with extended styles, need to combine with WS_BORDER - // for them to look right. - if ( want3D || - (m_windowStyle & (wxBORDER | - wxSIMPLE_BORDER | - wxRAISED_BORDER | - wxSUNKEN_BORDER | - wxDOUBLE_BORDER)) ) - { - msflags |= WS_BORDER; - } -#endif // wxUniversal/!wxUniversal + // no borders, we draw them ourselves + exstyle = 0; + msflags &= ~WS_BORDER; +#endif // wxUniversal if ( style & wxPOPUP_WINDOW ) { // a popup window floats on top of everything - exStyle |= WS_EX_TOPMOST | WS_EX_TOOLWINDOW; + exstyle |= WS_EX_TOPMOST | WS_EX_TOOLWINDOW; // it is also created hidden as other top level windows msflags &= ~WS_VISIBLE; m_isShown = FALSE; } - return MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exStyle); + return MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle); } // --------------------------------------------------------------------------- @@ -962,7 +963,7 @@ void wxWindowMSW::SubclassWin(WXHWND hWnd) wxAssociateWinWithHandle(hwnd, this); m_oldWndProc = (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC); - + // we don't need to subclass the window of our own class (in the Windows // sense of the word) if ( !wxCheckWindowWndProc(hWnd, (WXFARPROC)wxWndProc) ) @@ -1017,17 +1018,134 @@ bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc) // FIXME: Doesn't handle wnd procs set by SetWindowLong, only these set // with RegisterClass!! - static wxChar buffer[512]; - WNDCLASS cls; + if ( wxUsingUnicowsDll() ) + { + static wxChar buffer[512]; + WNDCLASS cls; - ::GetClassName((HWND)hWnd, buffer, 512); - ::GetClassInfo(wxGetInstance(), buffer, &cls); - return wndProc == (WXFARPROC)cls.lpfnWndProc; -#else - return wndProc == (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC); + ::GetClassName((HWND)hWnd, buffer, 512); + ::GetClassInfo(wxGetInstance(), buffer, &cls); + return wndProc == (WXFARPROC)cls.lpfnWndProc; + } + else #endif + { + return wndProc == (WXFARPROC)::GetWindowLong((HWND)hWnd, GWL_WNDPROC); + } +} + +// ---------------------------------------------------------------------------- +// Style handling +// ---------------------------------------------------------------------------- + +void wxWindowMSW::SetWindowStyleFlag(long flags) +{ + long flagsOld = GetWindowStyleFlag(); + if ( flags == flagsOld ) + return; + + // update the internal variable + wxWindowBase::SetWindowStyleFlag(flags); + + // now update the Windows style as well if needed - and if the window had + // been already created + if ( !GetHwnd() ) + return; + + WXDWORD exstyle, exstyleOld; + long style = MSWGetStyle(flags, &exstyle), + styleOld = MSWGetStyle(flagsOld, &exstyleOld); + + if ( style != styleOld ) + { + // some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by + // this function so instead of simply setting the style to the new + // value we clear the bits which were set in styleOld but are set in + // the new one and set the ones which were not set before + long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE); + styleReal &= ~styleOld; + styleReal |= style; + + ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal); + } + + // and the extended style + if ( exstyle != exstyleOld ) + { + long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE); + exstyleReal &= ~exstyleOld; + exstyleReal |= exstyle; + + ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal); + + // we must call SetWindowPos() to flash 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 + if ( !::SetWindowPos(GetHwnd(), + exstyleReal & WS_EX_TOPMOST ? HWND_TOPMOST + : HWND_NOTOPMOST, + 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE) ) + { + wxLogLastError(_T("SetWindowPos")); + } + } } +WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const +{ + // translate the style + WXDWORD style = WS_CHILD; + + if ( flags & wxCLIP_CHILDREN ) + style |= WS_CLIPCHILDREN; + + if ( flags & wxCLIP_SIBLINGS ) + style |= WS_CLIPSIBLINGS; + + wxBorder border = (wxBorder)(flags & wxBORDER_MASK); + if ( border != wxBORDER_NONE && border != wxBORDER_DEFAULT ) + style |= WS_BORDER; + + // now deal with ext style if the caller wants it + if ( exstyle ) + { + *exstyle = 0; + + if ( flags & wxTRANSPARENT_WINDOW ) + *exstyle |= WS_EX_TRANSPARENT; + + switch ( flags & wxBORDER_MASK ) + { + default: + wxFAIL_MSG( _T("unknown border style") ); + // fall through + + case wxBORDER_NONE: + case wxBORDER_SIMPLE: + case wxBORDER_DEFAULT: + break; + + case wxBORDER_STATIC: + *exstyle |= WS_EX_STATICEDGE; + break; + + case wxBORDER_RAISED: + *exstyle |= WS_EX_WINDOWEDGE; + break; + + case wxBORDER_SUNKEN: + *exstyle |= WS_EX_CLIENTEDGE; + break; + + case wxBORDER_DOUBLE: + *exstyle |= WS_EX_DLGMODALFRAME; + break; + } + } + + return style; +} // Make a Windows extended style from the given wxWindows window style WXDWORD wxWindowMSW::MakeExtendedStyle(long style, bool eliminateBorders) @@ -1175,7 +1293,9 @@ void wxWindowMSW::OnIdle(wxIdleEvent& WXUNUSED(event)) // Check if we need to send a LEAVE event if ( m_mouseInWindow ) { - if ( !IsMouseInWindow() && !HasCapture()) + // note that we should generate the leave event whether the window has + // or doesn't have mouse capture + if ( !IsMouseInWindow() ) { // Generate a LEAVE event m_mouseInWindow = FALSE; @@ -1544,15 +1664,6 @@ void wxWindowMSW::DoSetClientSize(int width, int height) break; } - if ( i == 3 ) - { - // how did it happen? maybe OnSize() handler does something really - // strange in this class? - wxFAIL_MSG( _T("logic error in DoSetClientSize") ); - - break; - } - int widthClient = width, heightClient = height; @@ -1925,10 +2036,18 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } #endif // 1/0 - if ( ::IsDialogMessage(GetHwnd(), msg) ) + // we handle VK_ESCAPE ourselves in wxDialog::OnCharHook() and we + // shouldn't let IsDialogMessage() get it as it _always_ eats the + // message even when there is no cancel button and when the message is + // needed by the control itself: in particular, it prevents the tree in + // place edit control from being closed with Escape in a dialog + if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE ) { - // IsDialogMessage() did something... - return TRUE; + if ( ::IsDialogMessage(GetHwnd(), msg) ) + { + // IsDialogMessage() did something... + return TRUE; + } } } #endif // __WXUNIVERSAL__ @@ -2371,27 +2490,31 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case WM_SYSKEYDOWN: case WM_KEYDOWN: - // If this has been processed by an event handler, - // return 0 now (we've handled it). - if ( HandleKeyDown((WORD) wParam, lParam) ) + // If this has been processed by an event handler, return 0 now + // (we've handled it). + m_lastKeydownProcessed = HandleKeyDown((WORD) wParam, lParam); + if ( m_lastKeydownProcessed ) { processed = TRUE; - - break; - } - - // we consider these message "not interesting" to OnChar - if ( wParam == VK_SHIFT || wParam == VK_CONTROL ) - { - processed = TRUE; - break; } switch ( wParam ) { - // avoid duplicate messages to OnChar for these ASCII keys: they - // will be translated by TranslateMessage() and received in WM_CHAR + // 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: @@ -2399,9 +2522,22 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case VK_TAB: case VK_ADD: case VK_SUBTRACT: - // 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 + 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; @@ -2420,12 +2556,10 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam break; #endif // VK_APPS - case VK_LEFT: - case VK_RIGHT: - case VK_DOWN: - case VK_UP: default: + // do generate a CHAR event processed = HandleChar((WORD)wParam, lParam); + } break; @@ -2450,7 +2584,18 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam case WM_SYSCHAR: case WM_CHAR: // Always an ASCII character - processed = HandleChar((WORD)wParam, lParam, TRUE); + if ( m_lastKeydownProcessed ) + { + // The key was handled in the EVT_KEY_DOWN and handling + // a key in an EVT_KEY_DOWN handler is meant, by + // design, to prevent EVT_CHARs from happening + m_lastKeydownProcessed = FALSE; + processed = TRUE; + } + else + { + processed = HandleChar((WORD)wParam, lParam, TRUE); + } break; case WM_HSCROLL: @@ -2510,6 +2655,10 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = HandlePaletteChanged((WXHWND) (HWND) wParam); break; + case WM_CAPTURECHANGED: + processed = HandleCaptureChanged((WXHWND) (HWND) lParam); + break; + case WM_QUERYNEWPALETTE: processed = HandleQueryNewPalette(); break; @@ -2611,21 +2760,6 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam } break; #endif // __WIN32__ - - // unfortunately this doesn't really work as then window which - // doesn't accept focus doesn't get any mouse events neither which - // means it can't get any input at all -#if 0 //def __WXUNIVERSAL__ - case WM_NCHITTEST: - // we shouldn't allow the windows which don't want to get focus to - // get it - if ( !AcceptsFocus() ) - { - rc.result = HTTRANSPARENT; - processed = TRUE; - } - break; -#endif // __WXUNIVERSAL__ } if ( !processed ) @@ -3389,6 +3523,14 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange) return GetEventHandler()->ProcessEvent(event); } +bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture) +{ + wxMouseCaptureChangedEvent event(GetId(), wxFindWinFromHandle(hWndGainedCapture)); + event.SetEventObject(this); + + return GetEventHandler()->ProcessEvent(event); +} + bool wxWindowMSW::HandleQueryNewPalette() { @@ -3654,9 +3796,13 @@ bool wxWindowMSW::HandleMove(int x, int y) return GetEventHandler()->ProcessEvent(event); } -bool wxWindowMSW::HandleSize(int w, int h, WXUINT WXUNUSED(flag)) +bool wxWindowMSW::HandleSize(int WXUNUSED(w), int WXUNUSED(h), + WXUINT WXUNUSED(flag)) { - wxSizeEvent event(wxSize(w, h), m_windowId); + // don't use w and h parameters as they specify the client size while + // according to the docs EVT_SIZE handler is supposed to receive the total + // size + wxSizeEvent event(GetSize(), m_windowId); event.SetEventObject(this); return GetEventHandler()->ProcessEvent(event); @@ -3667,7 +3813,7 @@ bool wxWindowMSW::HandleGetMinMaxInfo(void *mmInfo) MINMAXINFO *info = (MINMAXINFO *)mmInfo; bool rc = FALSE; - + int minWidth = GetMinWidth(), minHeight = GetMinHeight(), maxWidth = GetMaxWidth(), @@ -3928,7 +4074,8 @@ bool wxWindowMSW::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam) // HandleChar and HandleKeyDown/Up wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, int id, - WXLPARAM lParam) const + WXLPARAM lParam, + WXWPARAM wParam) const { wxKeyEvent event(evType); event.SetId(GetId()); @@ -3938,6 +4085,8 @@ wxKeyEvent wxWindowMSW::CreateKeyEvent(wxEventType evType, event.m_eventObject = (wxWindow *)this; // const_cast event.m_keyCode = id; + event.m_rawCode = (wxUint32) wParam; + event.m_rawFlags = (wxUint32) lParam; event.SetTimestamp(s_currentMsg.time); // translate the position to client coords @@ -3983,30 +4132,28 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) default: ctrlDown = TRUE; - id = id + 96; + id = id + 'a' - 1; } } } - else if ( (id = wxCharCodeMSWToWX(wParam)) == 0 ) - { - // it's ASCII and will be processed here only when called from - // WM_CHAR (i.e. when isASCII = TRUE), don't process it now - id = -1; - } - - if ( id != -1 ) + else // we're called from WM_KEYDOWN { - wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam)); - if ( ctrlDown ) + id = wxCharCodeMSWToWX(wParam); + if ( id == 0 ) { - event.m_controlDown = TRUE; + // it's ASCII and will be processed here only when called from + // WM_CHAR (i.e. when isASCII = TRUE), don't process it now + return FALSE; } + } - if ( GetEventHandler()->ProcessEvent(event) ) - return TRUE; + wxKeyEvent event(CreateKeyEvent(wxEVT_CHAR, id, lParam, wParam)); + if ( ctrlDown ) + { + event.m_controlDown = TRUE; } - return FALSE; + return GetEventHandler()->ProcessEvent(event); } bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) @@ -4021,7 +4168,7 @@ bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) if ( id != -1 ) // VZ: does this ever happen (FIXME)? { - wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam)); + wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_DOWN, id, lParam, wParam)); if ( GetEventHandler()->ProcessEvent(event) ) { return TRUE; @@ -4043,7 +4190,7 @@ bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) if ( id != -1 ) // VZ: does this ever happen (FIXME)? { - wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam)); + wxKeyEvent event(CreateKeyEvent(wxEVT_KEY_UP, id, lParam, wParam)); if ( GetEventHandler()->ProcessEvent(event) ) return TRUE; } @@ -4144,7 +4291,7 @@ bool wxWindowMSW::HandleJoystickEvent(WXUINT msg, int x, int y, WXUINT flags) // --------------------------------------------------------------------------- bool wxWindowMSW::MSWOnScroll(int orientation, WXWORD wParam, - WXWORD pos, WXHWND control) + WXWORD pos, WXHWND control) { if ( control ) { @@ -4272,6 +4419,7 @@ int wxCharCodeMSWToWX(int keySym) case VK_CONTROL: id = WXK_CONTROL; break; case VK_MENU : id = WXK_MENU; break; case VK_PAUSE: id = WXK_PAUSE; break; + 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; @@ -4329,6 +4477,19 @@ int wxCharCodeMSWToWX(int keySym) case VK_F24: id = WXK_F24; break; case VK_NUMLOCK: id = WXK_NUMLOCK; break; case VK_SCROLL: id = WXK_SCROLL; break; + + case VK_OEM_1: id = ';'; break; + case VK_OEM_PLUS: id = '+'; break; + case VK_OEM_COMMA: id = ','; break; + case VK_OEM_MINUS: id = '-'; break; + case VK_OEM_PERIOD: id = '.'; break; + case VK_OEM_2: id = '/'; break; + case VK_OEM_3: id = '~'; break; + case VK_OEM_4: id = '['; break; + case VK_OEM_5: id = '\\'; break; + case VK_OEM_6: id = ']'; break; + case VK_OEM_7: id = '\''; break; + default: id = 0; } @@ -5072,6 +5233,7 @@ wxPoint wxGetMousePosition() { POINT pt; GetCursorPos( & pt ); + return wxPoint(pt.x, pt.y); }