]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
Added files for wxNotebook and wxCocoaNSTabView
[wxWidgets.git] / src / msw / window.cpp
index fd309ac757d6eb626d304b54f362506b6697a51d..d0dca74f7918842342244c98625001be7f226846 100644 (file)
@@ -97,7 +97,7 @@
 
 #include <string.h>
 
 
 #include <string.h>
 
-#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__)
+#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
     #include <shellapi.h>
     #include <mmsystem.h>
 #endif
     #include <shellapi.h>
     #include <mmsystem.h>
 #endif
     #include <windowsx.h>
 #endif
 
     #include <windowsx.h>
 #endif
 
-#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)) || defined(__CYGWIN10__)
+#if (!defined(__GNUWIN32_OLD__) && !defined(__WXMICROWIN__) /* && !defined(__WXWINCE__) */ ) || defined(__CYGWIN10__)
     #ifdef __WIN95__
         #include <commctrl.h>
     #endif
     #ifdef __WIN95__
         #include <commctrl.h>
     #endif
@@ -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)
 {
 // 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.
      */
        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);
     while ( parent && !parent->IsTopLevel() )
     {
         LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
@@ -209,9 +210,10 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent)
 
         parent = parent->GetParent();
     }
 
         parent = parent->GetParent();
     }
-#endif // !__WXWINCE__
 }
 
 }
 
+#endif // !__WXWINCE__
+
 // ---------------------------------------------------------------------------
 // event tables
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 // event tables
 // ---------------------------------------------------------------------------
@@ -431,6 +433,7 @@ void wxWindowMSW::Init()
     m_lastKeydownProcessed = false;
 
     m_childrenDisabled = NULL;
     m_lastKeydownProcessed = false;
 
     m_childrenDisabled = NULL;
+    m_frozenness = 0;
 
     // wxWnd
     m_hMenu = 0;
 
     // wxWnd
     m_hMenu = 0;
@@ -440,9 +443,6 @@ void wxWindowMSW::Init()
     m_xThumbSize = 0;
     m_yThumbSize = 0;
 
     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;
 #if wxUSE_MOUSEEVENT_HACK
     m_lastMouseX =
     m_lastMouseY = -1;
@@ -519,14 +519,7 @@ bool wxWindowMSW::Create(wxWindow *parent,
     msflags &= ~WS_BORDER;
 #endif // wxUniversal
 
     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;
     }
     {
         msflags |= WS_VISIBLE;
     }
@@ -1294,16 +1287,24 @@ static inline void SendSetRedraw(HWND hwnd, bool on)
 
 void wxWindowMSW::Freeze()
 {
 
 void wxWindowMSW::Freeze()
 {
-    SendSetRedraw(GetHwnd(), false);
+    if ( !m_frozenness++ )
+    {
+        SendSetRedraw(GetHwnd(), false);
+    }
 }
 
 void wxWindowMSW::Thaw()
 {
 }
 
 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)
 }
 
 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
 // ===========================================================================
 
 // 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);
 {
     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;
 }
 
     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;
 {
     // did we process the message?
     bool processed = false;
@@ -2193,7 +2194,7 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
     union
     {
         bool        allow;
     union
     {
         bool        allow;
-        long        result;
+        WXLRESULT   result;
         WXHICON     hIcon;
         WXHBRUSH    hBrush;
     } rc;
         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;
 
             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:
             // 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;
                 // 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);
                 }
                 {
                     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;
 {
     // 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;
 
 
     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.
      */
           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;
     }
         nonDefault = true;
     }
+    w = WidthDefault(size.x);
+    h = HeightDefault(size.y);
 
     AdjustForParentClientOrigin(x, y);
 
 
     AdjustForParentClientOrigin(x, y);
 
@@ -3091,6 +3098,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     // do create the window
     wxWindowCreationHook hook(this);
 
     // do create the window
     wxWindowCreationHook hook(this);
 
+    // VZ: anyonce cares to explain why is this done for CE?
 #ifdef __WXWINCE__
     if (extendedStyle == 0)
     {
 #ifdef __WXWINCE__
     if (extendedStyle == 0)
     {
@@ -3107,7 +3115,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
             );
     }
     else
             );
     }
     else
-#endif
+#endif // __WXWINCE__
     {
         m_hWnd = (WXHWND)::CreateWindowEx
             (
     {
         m_hWnd = (WXHWND)::CreateWindowEx
             (
@@ -3132,8 +3140,6 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
 
     SubclassWin(m_hWnd);
 
 
     SubclassWin(m_hWnd);
 
-    SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
-
     return true;
 }
 
     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__
     // 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;
     {
         // 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;
 
 
     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 !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).
 
         // 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;
     }
 
     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
 
     // 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
     {
     }
     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
         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)
 {
 
 bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
 {
-    int id = wxCharCodeMSWToWX(wParam);
+    int id = wxCharCodeMSWToWX(wParam, lParam);
 
     if ( !id )
     {
 
     if ( !id )
     {
@@ -4602,7 +4624,7 @@ bool wxWindowMSW::HandleKeyDown(WXWPARAM wParam, WXLPARAM lParam)
 
 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
 {
 
 bool wxWindowMSW::HandleKeyUp(WXWPARAM wParam, WXLPARAM lParam)
 {
-    int id = wxCharCodeMSWToWX(wParam);
+    int id = wxCharCodeMSWToWX(wParam, lParam);
 
     if ( !id )
     {
 
     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.
 
 // 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)
 {
     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_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;
         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_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;
     }
         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) )
     {
     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);
         if ( id != 0 )
         {
             wxKeyEvent event(wxEVT_CHAR_HOOK);