X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d61c1a6f21202a9c9927452574cd5c6939255850..7848088476db284a94f19eeb24411b45d676ac46:/src/msw/window.cpp diff --git a/src/msw/window.cpp b/src/msw/window.cpp index f6ba76104f..d0dca74f79 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -180,6 +180,8 @@ static inline void wxBringWindowToTop(HWND hwnd) } } +#ifndef __WXWINCE__ + // ensure that all our parent windows have WS_EX_CONTROLPARENT style static void EnsureParentHasControlParentStyle(wxWindow *parent) { @@ -196,7 +198,6 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent) but if the parent doesn't have it, it wouldn't recurse inside it later on and so wouldn't have a chance of getting back to this window neither. */ -#ifndef __WXWINCE__ while ( parent && !parent->IsTopLevel() ) { LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE); @@ -209,9 +210,10 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent) parent = parent->GetParent(); } -#endif // !__WXWINCE__ } +#endif // !__WXWINCE__ + // --------------------------------------------------------------------------- // event tables // --------------------------------------------------------------------------- @@ -431,6 +433,7 @@ void wxWindowMSW::Init() m_lastKeydownProcessed = false; m_childrenDisabled = NULL; + m_frozenness = 0; // wxWnd m_hMenu = 0; @@ -440,9 +443,6 @@ void wxWindowMSW::Init() m_xThumbSize = 0; m_yThumbSize = 0; - // as all windows are created with WS_VISIBLE style... - m_isShown = true; - #if wxUSE_MOUSEEVENT_HACK m_lastMouseX = m_lastMouseY = -1; @@ -519,14 +519,7 @@ bool wxWindowMSW::Create(wxWindow *parent, msflags &= ~WS_BORDER; #endif // wxUniversal - // all windows are created visible by default except popup ones (which are - // like the wxTopLevelWindows in this aspect) - if ( style & wxPOPUP_WINDOW ) - { - msflags &= ~WS_VISIBLE; - m_isShown = false; - } - else + if ( IsShown() ) { msflags |= WS_VISIBLE; } @@ -1294,16 +1287,24 @@ static inline void SendSetRedraw(HWND hwnd, bool on) void wxWindowMSW::Freeze() { - SendSetRedraw(GetHwnd(), false); + if ( !m_frozenness++ ) + { + SendSetRedraw(GetHwnd(), false); + } } void wxWindowMSW::Thaw() { - SendSetRedraw(GetHwnd(), true); + wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") ); + + if ( !--m_frozenness ) + { + SendSetRedraw(GetHwnd(), true); - // we need to refresh everything or otherwise he invalidated area is not - // repainted - Refresh(); + // we need to refresh everything or otherwise he invalidated area is not + // repainted + Refresh(); + } } void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect) @@ -1763,7 +1764,7 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) // pre/post message processing // =========================================================================== -long wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +WXLRESULT wxWindowMSW::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) { if ( m_oldWndProc ) return ::CallWindowProc(CASTWNDPROC m_oldWndProc, GetHwnd(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam); @@ -2184,7 +2185,7 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM w return rc; } -long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) { // did we process the message? bool processed = false; @@ -2193,7 +2194,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam union { bool allow; - long result; + WXLRESULT result; WXHICON hIcon; WXHBRUSH hBrush; } rc; @@ -2538,6 +2539,19 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam processed = HandleNotify((int)wParam, lParam, &rc.result); break; + // we only need to reply to WM_NOTIFYFORMAT manually when using MSLU, + // otherwise DefWindowProc() does it perfectly fine for us, but MSLU + // apparently doesn't always behave properly and needs some help +#if wxUSE_UNICODE_MSLU && defined(NF_QUERY) + case WM_NOTIFYFORMAT: + if ( lParam == NF_QUERY ) + { + processed = true; + rc.result = NFR_UNICODE; + } + break; +#endif // wxUSE_UNICODE_MSLU + // for these messages we must return true if process the message #ifdef WM_DRAWITEM case WM_DRAWITEM: @@ -2888,7 +2902,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam // we could have got an event from our child, reflect it back // to it if this is the case wxWindowMSW *win = NULL; - if ( wParam != m_hWnd ) + if ( (WXHWND)wParam != m_hWnd ) { win = FindItemByHWND((WXHWND)wParam); } @@ -2984,8 +2998,6 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, { // yes, those are just some arbitrary hardcoded numbers static const int DEFAULT_Y = 200; - static const int DEFAULT_W = 400; - static const int DEFAULT_H = 250; bool nonDefault = false; @@ -3023,36 +3035,31 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos, this and ignore any attempts to change the window size to the size it already has - so no WM_SIZE would be sent. */ - if ( size.x == -1 ) - { - // we don't use CW_USEDEFAULT here for several reasons: - // - // 1. it results in huge frames on modern screens (1000*800 is not - // uncommon on my 1280*1024 screen) which is way too big for a half - // empty frame of most of wxWindows samples for example) - // - // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which - // the default is for whatever reason 8*8 which breaks client <-> - // window size calculations (it would be nice if it didn't, but it - // does and the simplest way to fix it seemed to change the broken - // default size anyhow) - // - // 3. there is just no advantage in doing it: with x and y it is - // possible that [future versions of] Windows position the new top - // level window in some smart way which we can't do, but we can - // guess a reasonably good size for a new window just as well - // ourselves - w = DEFAULT_W; - h = DEFAULT_H; - } - else - { - // and, again as above, we can't set the height to CW_USEDEFAULT here - w = size.x; - h = size.y == -1 ? DEFAULT_H : size.y; + + // we don't use CW_USEDEFAULT here for several reasons: + // + // 1. it results in huge frames on modern screens (1000*800 is not + // uncommon on my 1280*1024 screen) which is way too big for a half + // empty frame of most of wxWindows samples for example) + // + // 2. it is buggy for frames with wxFRAME_TOOL_WINDOW style for which + // the default is for whatever reason 8*8 which breaks client <-> + // window size calculations (it would be nice if it didn't, but it + // does and the simplest way to fix it seemed to change the broken + // default size anyhow) + // + // 3. there is just no advantage in doing it: with x and y it is + // possible that [future versions of] Windows position the new top + // level window in some smart way which we can't do, but we can + // guess a reasonably good size for a new window just as well + // ourselves + if ( size.x == -1 || size.y == -1) + { nonDefault = true; } + w = WidthDefault(size.x); + h = HeightDefault(size.y); AdjustForParentClientOrigin(x, y); @@ -3091,6 +3098,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, // do create the window wxWindowCreationHook hook(this); + // VZ: anyonce cares to explain why is this done for CE? #ifdef __WXWINCE__ if (extendedStyle == 0) { @@ -3107,7 +3115,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, ); } else -#endif +#endif // __WXWINCE__ { m_hWnd = (WXHWND)::CreateWindowEx ( @@ -3132,8 +3140,6 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass, SubclassWin(m_hWnd); - SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); - return true; } @@ -3200,7 +3206,8 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code, // we need to handle it as well, otherwise no tooltips will be shown in // this case #ifndef __WXWINCE__ - if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) || ttip.empty() ) + if ( !(code == (WXUINT) TTN_NEEDTEXTA || code == (WXUINT) TTN_NEEDTEXTW) + || ttip.empty() ) { // not a tooltip message or no tooltip to show anyhow return false; @@ -3209,41 +3216,58 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code, LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; + // We don't want to use the szText buffer because it has a limit of 80 + // bytes and this is not enough, especially for Unicode build where it + // limits the tooltip string length to only 40 characters + // + // The best would be, of course, to not impose any length limitations at + // all but then the buffer would have to be dynamic and someone would have + // to free it and we don't have the tooltip owner object here any more, so + // for now use our own static buffer with a higher fixed max length. + // + // Note that using a static buffer should not be a problem as only a single + // tooltip can be shown at the same time anyhow. #if !wxUSE_UNICODE - if ( code == (WXUINT) TTN_NEEDTEXTA ) + if ( code == (WXUINT) TTN_NEEDTEXTW ) { - // we pass just the pointer as we store the string internally anyhow - ttText->lpszText = (char *)ttip.c_str(); - } - 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 - // Convert tooltip from multi byte to Unicode. - - // We don't want to use the szText buffer because it has a limit of 80 - // bytes, for now use our own static buffer with a higher fixed max - // length. - // Preferably a dynamic buffer should be used, but who frees the buffer? + // We need to convert tooltip from multi byte to Unicode on the fly. + static wchar_t buf[513]; - static const int MAX_LENGTH = 512; - static wchar_t buf[MAX_LENGTH+1]; - - ttText->lpszText = (LPSTR) buf; - - // Truncate tooltip length if needed - size_t tipLength = wxMin(ttip.Len(), MAX_LENGTH); + // Truncate tooltip length if needed as otherwise we might not have + // enough space for it in the buffer and MultiByteToWideChar() would + // return an error + size_t tipLength = wxMin(ttip.Len(), WXSIZEOF(buf) - 1); // Convert to WideChar without adding the NULL character. The NULL // character is added afterwards (this is more efficient). - ::MultiByteToWideChar(CP_ACP, 0, ttip, tipLength, buf, MAX_LENGTH); - - buf[tipLength] = '\0'; + int len = ::MultiByteToWideChar + ( + CP_ACP, + 0, // no flags + ttip, + tipLength, + buf, + WXSIZEOF(buf) - 1 + ); + + if ( !len ) + { + wxLogLastError(_T("MultiByteToWideChar()")); + } -#endif // Unicode/!Unicode + buf[len] = L'\0'; + ttText->lpszText = (LPSTR) buf; + } + else // TTN_NEEDTEXTA +#endif // !wxUSE_UNICODE + { + // we get here if we got TTN_NEEDTEXTA (only happens in ANSI build) or + // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have + // to copy the string we have into the buffer + static wxChar buf[513]; + wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1); + buf[WXSIZEOF(buf) - 1] = _T('\0'); + ttText->lpszText = buf; } return true; @@ -3875,16 +3899,14 @@ void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) // update the colours we use if they were not set explicitly by the user: // this must be done or OnCtlColor() would continue to use the old colours - if ( !m_hasFgCol ) + if ( !m_hasFgCol || !m_hasBgCol ) { - m_foregroundColour = wxSystemSettings:: - GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); - } + wxVisualAttributes attrs = GetDefaultAttributes(); + if ( !m_hasFgCol ) + m_foregroundColour = attrs.colFg; - if ( !m_hasBgCol ) - { - m_backgroundColour = wxSystemSettings:: - GetSystemColour(wxSYS_COLOUR_BTNFACE); + if ( !m_hasBgCol ) + m_backgroundColour = attrs.colBg; } } @@ -4551,7 +4573,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) } else // we're called from WM_KEYDOWN { - id = wxCharCodeMSWToWX(wParam); + id = wxCharCodeMSWToWX(wParam, lParam); if ( id == 0 ) { // it's ASCII and will be processed here only when called from @@ -4580,7 +4602,7 @@ bool wxWindowMSW::HandleChar(WXWPARAM wParam, WXLPARAM lParam, bool isASCII) bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( !id ) { @@ -4602,7 +4624,7 @@ bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam) bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( !id ) { @@ -4886,7 +4908,7 @@ void wxGetCharSize(WXHWND wnd, int *x, int *y, const wxFont *the_font) // Returns 0 if was a normal ASCII value, not a special key. This indicates that // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead. -int wxCharCodeMSWToWX(int keySym) +int wxCharCodeMSWToWX(int keySym, WXLPARAM lParam) { int id; switch (keySym) @@ -4895,7 +4917,6 @@ int wxCharCodeMSWToWX(int keySym) case VK_BACK: id = WXK_BACK; break; case VK_TAB: id = WXK_TAB; break; case VK_CLEAR: id = WXK_CLEAR; break; - case VK_RETURN: id = WXK_RETURN; break; case VK_SHIFT: id = WXK_SHIFT; break; case VK_CONTROL: id = WXK_CONTROL; break; case VK_MENU : id = WXK_MENU; break; @@ -4977,6 +4998,13 @@ int wxCharCodeMSWToWX(int keySym) case VK_APPS: id = WXK_WINDOWS_MENU; break; #endif // VK_APPS defined + case VK_RETURN: + // the same key is sent for both the "return" key on the main + // keyboard and the numeric keypad but we want to distinguish + // between them: we do this using the "extended" bit (24) of lParam + id = lParam & (1 << 24) ? WXK_NUMPAD_ENTER : WXK_RETURN; + break; + default: id = 0; } @@ -5175,7 +5203,7 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam) DWORD hiWord = HIWORD(lParam); if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) ) { - int id = wxCharCodeMSWToWX(wParam); + int id = wxCharCodeMSWToWX(wParam, lParam); if ( id != 0 ) { wxKeyEvent event(wxEVT_CHAR_HOOK);