]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/tbar95.cpp
wxITEM_FOO instead of wxItem_Foo, for the sake of consistency
[wxWidgets.git] / src / msw / tbar95.cpp
index 788c5d36cf0ea6fbdfd9389c3d4b65522e447576..fe3e60ea8e730803bdc00a39e252f650eaf3c943 100644 (file)
@@ -36,6 +36,7 @@
     #include "wx/settings.h"
     #include "wx/bitmap.h"
     #include "wx/dcmemory.h"
+    #include "wx/control.h"
 #endif
 
 #if wxUSE_TOOLBAR && defined(__WIN95__) && wxUSE_TOOLBAR_NATIVE
 #ifndef TBSTYLE_FLAT
     #define TBSTYLE_LIST            0x1000
     #define TBSTYLE_FLAT            0x0800
+#endif
+
+#ifndef TBSTYLE_TRANSPARENT
     #define TBSTYLE_TRANSPARENT     0x8000
 #endif
- // use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT
 
 // Messages
 #ifndef TB_GETSTYLE
@@ -232,8 +235,17 @@ bool wxToolBar::Create(wxWindow *parent,
 
     if (style & wxTB_FLAT)
     {
-        if (wxTheApp->GetComCtl32Version() > 400)
-            msflags |= TBSTYLE_FLAT;
+        // static as it doesn't change during the program lifetime
+        static int s_verComCtl = wxTheApp->GetComCtl32Version();
+
+        // comctl32.dll 4.00 doesn't support the flat toolbars and using this
+        // style with 6.00 (part of Windows XP) leads to the toolbar with
+        // incorrect background colour - and not using it still results in the
+        // correct (flat) toolbar, so don't use it there
+        if ( s_verComCtl > 400 && s_verComCtl < 600 )
+        {
+            msflags |= TBSTYLE_FLAT | TBSTYLE_TRANSPARENT;
+        }
     }
 
     // MSW-specific initialisation
@@ -244,9 +256,7 @@ bool wxToolBar::Create(wxWindow *parent,
     ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
 
     // set up the colors and fonts
-    wxRGBToColour(m_backgroundColour, GetSysColor(COLOR_BTNFACE));
-    m_foregroundColour = *wxBLACK;
-
+    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR));
     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
 
     // position it
@@ -438,12 +448,12 @@ bool wxToolBar::Realize()
         wxToolBarToolBase *tool = node->GetData();
         if ( tool->IsButton() )
         {
-            const wxBitmap& bmp = tool->GetBitmap1();
+            const wxBitmap& bmp = tool->GetNormalBitmap();
             if ( bmp.Ok() )
             {
 #if USE_BITMAP_MASKS
                 // notice the last parameter: do use mask
-                dcAllButtons.DrawBitmap(tool->GetBitmap1(), x, 0, TRUE);
+                dcAllButtons.DrawBitmap(bmp, x, 0, TRUE);
 #else // !USE_BITMAP_MASKS
                 HBITMAP hbmp = GetHbitmapOf(bmp);
                 HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp);
@@ -1030,180 +1040,195 @@ void wxToolBar::OnMouseEvent(wxMouseEvent& event)
     }
 }
 
-long wxToolBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+bool wxToolBar::HandleSize(WXWPARAM wParam, WXLPARAM lParam)
 {
-    if ( nMsg == WM_SIZE )
+    // calculate our minor dimenstion ourselves - we're confusing the standard
+    // logic (TB_AUTOSIZE) with our horizontal toolbars and other hacks
+    RECT r;
+    if ( ::SendMessage(GetHwnd(), TB_GETITEMRECT, 0, (LPARAM)&r) )
     {
-        // calculate our minor dimenstion ourselves - we're confusing the
-        // standard logic (TB_AUTOSIZE) with our horizontal toolbars and other
-        // hacks
-        RECT r;
-        if ( ::SendMessage(GetHwnd(), TB_GETITEMRECT, 0, (LPARAM)&r) )
-        {
-            int w, h;
+        int w, h;
 
-            if ( GetWindowStyle() & wxTB_VERTICAL )
-            {
-                w = r.right - r.left;
-                if ( m_maxRows )
-                {
-                    w *= (m_nButtons + m_maxRows - 1)/m_maxRows;
-                }
-                h = HIWORD(lParam);
-            }
-            else
+        if ( GetWindowStyle() & wxTB_VERTICAL )
+        {
+            w = r.right - r.left;
+            if ( m_maxRows )
             {
-                w = LOWORD(lParam);
-                h = r.bottom - r.top;
-                if ( m_maxRows )
-                {
-                    h += 6; // FIXME: this is the separator line height...
-                    h *= m_maxRows;
-                }
+                w *= (m_nButtons + m_maxRows - 1)/m_maxRows;
             }
-
-            if ( MAKELPARAM(w, h) != lParam )
+            h = HIWORD(lParam);
+        }
+        else
+        {
+            w = LOWORD(lParam);
+            h = r.bottom - r.top;
+            if ( m_maxRows )
             {
-                // size really changed
-                SetSize(w, h);
+                // FIXME: 6 is hardcoded separator line height...
+                h += 6;
+                h *= m_maxRows;
             }
+        }
 
-            // message processed
-            return 0;
+        if ( MAKELPARAM(w, h) != lParam )
+        {
+            // size really changed
+            SetSize(w, h);
         }
+
+        // message processed
+        return TRUE;
     }
-    else if ( nMsg == WM_MOUSEMOVE )
+
+    return FALSE;
+}
+
+bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam)
+{
+    // erase any dummy separators which we used for aligning the controls if
+    // any here
+
+    // first of all, do we have any controls at all?
+    wxToolBarToolsList::Node *node;
+    for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
     {
-        wxCoord x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam);
-        wxToolBarToolBase* tool = FindToolForPosition( x, y );
+        if ( node->GetData()->IsControl() )
+            break;
+    }
 
-        // cursor left current tool
-        if( tool != m_pInTool && !tool )
-        {
-            m_pInTool = 0;
-            OnMouseEnter( -1 );
-        }
+    if ( !node )
+    {
+        // no controls, nothing to erase
+        return FALSE;
+    }
 
-        // cursor entered a tool
-        if( tool != m_pInTool && tool )
-        {
-            m_pInTool = tool;
-            OnMouseEnter( tool->GetId() );
-        }
+    // prepare the DC on which we'll be drawing
+    wxClientDC dc(this);
+    dc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID));
+    dc.SetPen(*wxTRANSPARENT_PEN);
 
-        // we don't handle mouse moves, so fall through
-        // to wxControl::MSWWindowProc
+    RECT r;
+    if ( !GetUpdateRect(GetHwnd(), &r, FALSE) )
+    {
+        // nothing to redraw anyhow
+        return FALSE;
     }
 
-    return wxControl::MSWWindowProc(nMsg, wParam, lParam);
-}
+    wxRect rectUpdate;
+    wxCopyRECTToRect(r, rectUpdate);
 
-// ----------------------------------------------------------------------------
-// private functions
-// ----------------------------------------------------------------------------
+    dc.SetClippingRegion(rectUpdate);
 
-// VZ: we use a separate function to do the actual colour mapping because
-//     otherwise VC++ optimizer seems to mangle the code in MapBitmap(): with
-//     optimization on, the code produces incorrect result (but it's ok in
-//     debug mode, i.e. globally without optimizations or if you insert a
-//     #pragma optimize("", off) just before the function!)
-//
-//     This will also make it simpler to replace MapColours() later with
-//     something more efficient...
-static void MapColours(HDC hdc, int width, int height,
-                       size_t numColours, COLORMAP *cmap)
-{
-    for ( int i = 0; i < width; i++ )
+    // draw the toolbar tools, separators &c normally
+    wxControl::MSWWindowProc(WM_PAINT, wParam, lParam);
+
+    // for each control in the toolbar find all the separators intersecting it
+    // and erase them
+    //
+    // NB: this is really the only way to do it as we don't know if a separator
+    //     corresponds to a control (i.e. is a dummy one) or a real one
+    //     otherwise
+    for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
     {
-        for ( int j = 0; j < height; j++ )
+        wxToolBarToolBase *tool = node->GetData();
+        if ( tool->IsControl() )
         {
-            COLORREF pixel = ::GetPixel(hdc, i, j);
+            // get the control rect in our client coords
+            wxControl *control = tool->GetControl();
+            wxRect rectCtrl = control->GetRect();
 
-            for ( size_t k = 0; k < numColours; k++ )
+            // iterate over all buttons
+            TBBUTTON tbb;
+            int count = ::SendMessage(GetHwnd(), TB_BUTTONCOUNT, 0, 0);
+            for ( int n = 0; n < count; n++ )
             {
-                COLORREF col = cmap[k].from;
-                if ( abs(GetRValue(pixel) - GetRValue(col)) < 10 &&
-                     abs(GetGValue(pixel) - GetGValue(col)) < 10 &&
-                     abs(GetBValue(pixel) - GetBValue(col)) < 10 )
+                // is it a separator?
+                if ( !::SendMessage(GetHwnd(), TB_GETBUTTON,
+                                    n, (LPARAM)&tbb) )
                 {
-                    ::SetPixel(hdc, i, j, cmap[k].to);
-                    break;
+                    wxLogDebug(_T("TB_GETBUTTON failed?"));
+
+                    continue;
+                }
+
+                if ( tbb.fsStyle != TBSTYLE_SEP )
+                    continue;
+
+                // get the bounding rect of the separator
+                RECT r;
+                if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT,
+                                    n, (LPARAM)&r) )
+                {
+                    wxLogDebug(_T("TB_GETITEMRECT failed?"));
+
+                    continue;
+                }
+
+                // does it intersect the control?
+                wxRect rectItem;
+                wxCopyRECTToRect(r, rectItem);
+                if ( rectCtrl.Intersects(rectItem) )
+                {
+                    // yes, do erase it!
+                    dc.DrawRectangle(rectItem);
                 }
             }
         }
     }
+
+    return TRUE;
 }
 
-WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height)
+void wxToolBar::HandleMouseMove(WXWPARAM wParam, WXLPARAM lParam)
 {
-    // number of the colours we map: if you change this, update
-    // wxBITMAP_STD_COLOURS in the resources as well: it must have the same number
-    // of pixels
-    static const size_t NUM_OF_MAPPED_COLOURS = 4;
-
-    static bool s_coloursInit = FALSE;
-    long s_stdColours[NUM_OF_MAPPED_COLOURS];
+    wxCoord x = GET_X_LPARAM(lParam),
+            y = GET_Y_LPARAM(lParam);
+    wxToolBarToolBase* tool = FindToolForPosition( x, y );
 
-    if (!s_coloursInit)
+    // cursor left current tool
+    if( tool != m_pInTool && !tool )
     {
-        // When a bitmap is loaded, the RGB values can change (apparently
-        // because Windows adjusts them to care for the old programs always
-        // using 0xc0c0c0 while the transparent colour for the new Windows
-        // versions is different). But we do this adjustment ourselves so we
-        // want to avoid Windows' "help" and for this we need to have a
-        // reference bitmap which can tell us what the RGB values change to.
-        wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS"));
-        if (stdColourBitmap.Ok())
-        {
-            wxMemoryDC memDC;
-            memDC.SelectObject(stdColourBitmap);
-
-            wxColour colour;
-            for ( size_t i = 0; i < WXSIZEOF(s_stdColours); i++ )
-            {
-                memDC.GetPixel(i, 0, &colour);
-                s_stdColours[i] = wxColourToRGB(colour);
-            }
-        }
-        else
-        {
-            s_stdColours[0] = RGB(000,000,000) ;
-            s_stdColours[1] = RGB(128,128,128) ;
-            s_stdColours[2] = RGB(192,192,192) ;
-            s_stdColours[3] = RGB(255,255,255) ;
-            //s_stdColours[4] = RGB(000,000,255) ;
-            //s_stdColours[5] = RGB(255,000,255) ;
-        }
+        m_pInTool = 0;
+        OnMouseEnter( -1 );
+    }
 
-        s_coloursInit = TRUE;
+    // cursor entered a tool
+    if( tool != m_pInTool && tool )
+    {
+        m_pInTool = tool;
+        OnMouseEnter( tool->GetId() );
     }
+}
 
-    COLORMAP ColorMap[NUM_OF_MAPPED_COLOURS];
-
-    // black        (0, 0 0)
-    ColorMap[0].from = s_stdColours[0];
-    ColorMap[0].to = COLOR_BTNTEXT;
-    // dark grey    (128, 128, 128)
-    ColorMap[1].from = s_stdColours[1];
-    ColorMap[1].to = COLOR_BTNSHADOW;
-    // bright grey  (192, 192, 192)
-    ColorMap[2].from = s_stdColours[2];
-    ColorMap[2].to = COLOR_BTNFACE;
-    // white        (255, 255, 255)
-    ColorMap[3].from = s_stdColours[3];
-    ColorMap[3].to = COLOR_BTNHIGHLIGHT;
-    // blue         (0, 0, 255)
-    //  ColorMap[4].from = s_stdColours[4];
-    //  ColorMap[4].to = COLOR_HIGHLIGHT;
-    // magenta      (255, 0, 255)
-    //  ColorMap[4].from = s_stdColours[5];
-    //  ColorMap[4].to = COLOR_WINDOW;
-
-    for ( size_t n = 0; n < WXSIZEOF(ColorMap); n++ )
+long wxToolBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+{
+    switch ( nMsg )
     {
-        ColorMap[n].to = ::GetSysColor(ColorMap[n].to);
+        case WM_SIZE:
+            if ( HandleSize(wParam, lParam) )
+                return 0;
+            break;
+
+        case WM_MOUSEMOVE:
+            // we don't handle mouse moves, so always pass the message to
+            // wxControl::MSWWindowProc
+            HandleMouseMove(wParam, lParam);
+            break;
+
+        case WM_PAINT:
+            if ( HandlePaint(wParam, lParam) )
+                return 0;
     }
 
+    return wxControl::MSWWindowProc(nMsg, wParam, lParam);
+}
+
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height)
+{
     MemoryHDC hdcMem;
 
     if ( !hdcMem )
@@ -1222,7 +1247,27 @@ WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height)
         return bitmap;
     }
 
-    MapColours(hdcMem, width, height, WXSIZEOF(ColorMap), ColorMap);
+    wxCOLORMAP *cmap = wxGetStdColourMap();
+
+    for ( int i = 0; i < width; i++ )
+    {
+        for ( int j = 0; j < height; j++ )
+        {
+            COLORREF pixel = ::GetPixel(hdcMem, i, j);
+
+            for ( size_t k = 0; k < wxSTD_COL_MAX; k++ )
+            {
+                COLORREF col = cmap[k].from;
+                if ( abs(GetRValue(pixel) - GetRValue(col)) < 10 &&
+                     abs(GetGValue(pixel) - GetGValue(col)) < 10 &&
+                     abs(GetBValue(pixel) - GetBValue(col)) < 10 )
+                {
+                    ::SetPixel(hdcMem, i, j, cmap[k].to);
+                    break;
+                }
+            }
+        }
+    }
 
     return bitmap;