]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
Implemented Enable for wxMenuBar to avoid assert
[wxWidgets.git] / src / msw / window.cpp
index d58cf40d7eb20966f1818b5bdbc0983a5f0e7818..a8191c4e4342a5674deb1bc0b8c1a0218d242109 100644 (file)
@@ -431,6 +431,7 @@ void wxWindowMSW::Init()
     m_lastKeydownProcessed = false;
 
     m_childrenDisabled = NULL;
+    m_frozenness = 0;
 
     // wxWnd
     m_hMenu = 0;
@@ -440,9 +441,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 +517,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 +1285,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()") );
 
-    // we need to refresh everything or otherwise he invalidated area is not
-    // repainted
-    Refresh();
+    if ( !--m_frozenness )
+    {
+        SendSetRedraw(GetHwnd(), true);
+
+        // we need to refresh everything or otherwise he invalidated area is not
+        // repainted
+        Refresh();
+    }
 }
 
 void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
@@ -2538,6 +2537,19 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
             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:
@@ -2984,8 +2996,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 +3033,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);
 
@@ -3132,8 +3137,6 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
 
     SubclassWin(m_hWnd);
 
-    SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
-
     return true;
 }
 
@@ -3200,7 +3203,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 +3213,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?
-
-        static const int MAX_LENGTH = 512;
-        static wchar_t buf[MAX_LENGTH+1];
-
-        ttText->lpszText = (LPSTR) buf;
+        // We need to convert tooltip from multi byte to Unicode on the fly.
+        static wchar_t buf[513];
 
-        // 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 +3896,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 +4570,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 +4599,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 +4621,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 +4905,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 +4914,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 +4995,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 +5200,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);