X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e731cb64e66a11ab34b2c7a00a583c77055c7433..5819f832e6fc616ea3e365376ce71ed3c69e023a:/src/msw/tbar95.cpp?ds=sidebyside diff --git a/src/msw/tbar95.cpp b/src/msw/tbar95.cpp index 7bc8e9589d..8dff81d4f9 100644 --- a/src/msw/tbar95.cpp +++ b/src/msw/tbar95.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/tbar95.cpp +// Name: src/msw/tbar95.cpp // Purpose: wxToolBar // Author: Julian Smart // Modified by: @@ -24,22 +24,24 @@ #pragma hdrstop #endif +#if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE && !defined(__SMARTPHONE__) + +#include "wx/toolbar.h" + #ifndef WX_PRECOMP + #include "wx/dynarray.h" #include "wx/frame.h" #include "wx/log.h" #include "wx/intl.h" - #include "wx/dynarray.h" #include "wx/settings.h" #include "wx/bitmap.h" #include "wx/dcmemory.h" #include "wx/control.h" + #include "wx/app.h" // for GetComCtl32Version + #include "wx/image.h" #endif -#if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE && !defined(__SMARTPHONE__) - -#include "wx/toolbar.h" #include "wx/sysopt.h" -#include "wx/image.h" #include "wx/msw/private.h" @@ -50,7 +52,14 @@ // include "properly" #include "wx/msw/wrapcctl.h" -#include "wx/app.h" // for GetComCtl32Version +// this define controls whether the code for button colours remapping (only +// useful for 16 or 256 colour images) is active at all, it's always turned off +// for CE where it doesn't compile (and is probably not needed anyhow) and may +// also be turned off for other systems if you always use 24bpp images and so +// never need it +#ifndef __WXWINCE__ + #define wxREMAP_BUTTON_COLOURS +#endif // !__WXWINCE__ // ---------------------------------------------------------------------------- // constants @@ -173,7 +182,6 @@ private: DECLARE_NO_COPY_CLASS(wxToolBarTool) }; - // ============================================================================ // implementation // ============================================================================ @@ -234,16 +242,12 @@ bool wxToolBar::Create(wxWindow *parent, wxSetCCUnicodeFormat(GetHwnd()); - // set up the colors and fonts - SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); - SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); - // workaround for flat toolbar on Windows XP classic style: we have to set // the style after creating the control; doing it at creation time doesn't work #if wxUSE_UXTHEME if ( style & wxTB_FLAT ) { - LRESULT style = ::SendMessage(GetHwnd(), TB_GETSTYLE, 0, 0L); + LRESULT style = GetMSWToolbarStyle(); if ( !(style & TBSTYLE_FLAT) ) ::SendMessage(GetHwnd(), TB_SETSTYLE, 0, style | TBSTYLE_FLAT); @@ -372,14 +376,13 @@ WXDWORD wxToolBar::MSWGetStyle(long style, WXDWORD *exstyle) const (style & ~wxBORDER_MASK) | wxBORDER_NONE, exstyle ); - // always include this one, it never hurts and setting it later - // only if we do have tooltips wouldn't work - msStyle |= TBSTYLE_TOOLTIPS; + if ( !(style & wxTB_NO_TOOLTIPS) ) + msStyle |= TBSTYLE_TOOLTIPS; if ( style & (wxTB_FLAT | wxTB_HORZ_LAYOUT) ) { // static as it doesn't change during the program lifetime - static int s_verComCtl = wxApp::GetComCtl32Version(); + static const int s_verComCtl = wxApp::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 @@ -459,6 +462,7 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) { nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount(); width *= nButtonsToDelete; + tool->GetControl()->Destroy(); } // do delete all buttons @@ -504,7 +508,7 @@ void wxToolBar::CreateDisabledImageList() // as we can't use disabled image list with older versions of comctl32.dll, // don't even bother creating it - if ( wxTheApp->GetComCtl32Version() >= 470 ) + if ( wxApp::GetComCtl32Version() >= 470 ) { // search for the first disabled button img in the toolbar, if any for ( wxToolBarToolsList::compatibility_iterator @@ -538,22 +542,27 @@ bool wxToolBar::Realize() const bool isVertical = HasFlag(wxTB_VERTICAL); - bool doRemap, doRemapBg, doTransparent; - doRemapBg = doRemap = doTransparent = false; - -#ifndef __WXWINCE__ - int remapValue = (-1); - const wxChar *remapOptionStr = wxT("msw.remap"); - if (wxSystemOptions::HasOption( remapOptionStr )) - remapValue = wxSystemOptions::GetOptionInt( remapOptionStr ); - - doTransparent = (remapValue == 2); - if (!doTransparent) +#ifdef wxREMAP_BUTTON_COLOURS + // don't change the values of these constants, they can be set from the + // user code via wxSystemOptions + enum { - doRemap = (remapValue != 0); - doRemapBg = !doRemap; - } -#endif + Remap_None = -1, + Remap_Bg, + Remap_Buttons, + Remap_TransparentBg + }; + + // the user-specified option overrides anything, but if it wasn't set, only + // remap the buttons on 8bpp displays as otherwise the bitmaps usually look + // much worse after remapping + static const wxChar *remapOption = wxT("msw.remap"); + const int remapValue = wxSystemOptions::HasOption(remapOption) + ? wxSystemOptions::GetOptionInt(remapOption) + : wxDisplayDepth() <= 8 ? Remap_Buttons + : Remap_None; + +#endif // wxREMAP_BUTTON_COLOURS // delete all old buttons, if any for ( size_t pos = 0; pos < m_nButtons; pos++ ) @@ -595,21 +604,26 @@ bool wxToolBar::Realize() wxBitmap bitmap(totalBitmapWidth, totalBitmapHeight); dcAllButtons.SelectObject(bitmap); -#ifndef __WXWINCE__ - if (doTransparent) - dcAllButtons.SetBackground(*wxTRANSPARENT_BRUSH); - else - dcAllButtons.SetBackground(wxBrush(GetBackgroundColour())); -#else - dcAllButtons.SetBackground(wxBrush(wxColour(192,192,192))); -#endif - dcAllButtons.Clear(); +#ifdef wxREMAP_BUTTON_COLOURS + if ( remapValue != Remap_TransparentBg ) +#endif // wxREMAP_BUTTON_COLOURS + { + // VZ: why do we hardcode grey colour for CE? + dcAllButtons.SetBackground(wxBrush( +#ifdef __WXWINCE__ + wxColour(0xc0, 0xc0, 0xc0) +#else // !__WXWINCE__ + GetBackgroundColour() +#endif // __WXWINCE__/!__WXWINCE__ + )); + dcAllButtons.Clear(); + } m_hBitmap = bitmap.GetHBITMAP(); HBITMAP hBitmap = (HBITMAP)m_hBitmap; -#ifndef __WXWINCE__ - if (doRemapBg) +#ifdef wxREMAP_BUTTON_COLOURS + if ( remapValue == Remap_Bg ) { dcAllButtons.SelectObject(wxNullBitmap); @@ -620,7 +634,7 @@ bool wxToolBar::Realize() dcAllButtons.SelectObject(bitmap); } -#endif // !__WXWINCE__ +#endif // wxREMAP_BUTTON_COLOURS // the button position wxCoord x = 0; @@ -665,7 +679,8 @@ bool wxToolBar::Realize() wxImage imgGreyed; wxCreateGreyedImage(bmp.ConvertToImage(), imgGreyed); - if (doRemap) +#ifdef wxREMAP_BUTTON_COLOURS + if ( remapValue == Remap_Buttons ) { // we need to have light grey background colour for // MapBitmap() to work correctly @@ -681,13 +696,16 @@ bool wxToolBar::Realize() } } } +#endif // wxREMAP_BUTTON_COLOURS bmpDisabled = wxBitmap(imgGreyed); } #endif // wxUSE_IMAGE - if (doRemap) +#ifdef wxREMAP_BUTTON_COLOURS + if ( remapValue == Remap_Buttons ) MapBitmap(bmpDisabled.GetHBITMAP(), w, h); +#endif // wxREMAP_BUTTON_COLOURS m_disabledImgList->Add(bmpDisabled); } @@ -705,12 +723,14 @@ bool wxToolBar::Realize() // don't delete this HBITMAP! bitmap.SetHBITMAP(0); - if (doRemap) +#ifdef wxREMAP_BUTTON_COLOURS + if ( remapValue == Remap_Buttons ) { // Map to system colours hBitmap = (HBITMAP)MapBitmap((WXHBITMAP) hBitmap, - totalBitmapWidth, totalBitmapHeight); + totalBitmapWidth, totalBitmapHeight); } +#endif // wxREMAP_BUTTON_COLOURS bool addBitmap = true; @@ -1097,33 +1117,34 @@ bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *WXUNUSED(result)) { + if( !HasFlag(wxTB_NO_TOOLTIPS) ) + { #if wxUSE_TOOLTIPS - // First check if this applies to us - NMHDR *hdr = (NMHDR *)lParam; - - // the tooltips control created by the toolbar is sometimes Unicode, even - // in an ANSI application - this seems to be a bug in comctl32.dll v5 - UINT code = hdr->code; - if ( (code != (UINT) TTN_NEEDTEXTA) && (code != (UINT) TTN_NEEDTEXTW) ) - return false; + // First check if this applies to us + NMHDR *hdr = (NMHDR *)lParam; - HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0); - if ( toolTipWnd != hdr->hwndFrom ) - return false; + // the tooltips control created by the toolbar is sometimes Unicode, even + // in an ANSI application - this seems to be a bug in comctl32.dll v5 + UINT code = hdr->code; + if ( (code != (UINT) TTN_NEEDTEXTA) && (code != (UINT) TTN_NEEDTEXTW) ) + return false; - LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; - int id = (int)ttText->hdr.idFrom; + HWND toolTipWnd = (HWND)::SendMessage(GetHwnd(), TB_GETTOOLTIPS, 0, 0); + if ( toolTipWnd != hdr->hwndFrom ) + return false; - wxToolBarToolBase *tool = FindById(id); - if ( !tool ) - return false; + LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; + int id = (int)ttText->hdr.idFrom; - return HandleTooltipNotify(code, lParam, tool->GetShortHelp()); + wxToolBarToolBase *tool = FindById(id); + if ( tool ) + return HandleTooltipNotify(code, lParam, tool->GetShortHelp()); #else - wxUnusedVar(lParam); + wxUnusedVar(lParam); +#endif + } return false; -#endif } // ---------------------------------------------------------------------------- @@ -1230,17 +1251,19 @@ wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const void wxToolBar::UpdateSize() { + wxPoint pos = GetPosition(); + ::SendMessage(GetHwnd(), TB_AUTOSIZE, 0, 0); + if (pos != GetPosition()) + Move(pos); + // In case Realize is called after the initial display (IOW the programmer // may have rebuilt the toolbar) give the frame the option of resizing the // toolbar to full width again, but only if the parent is a frame and the // toolbar is managed by the frame. Otherwise assume that some other // layout mechanism is controlling the toolbar size and leave it alone. - wxFrame *frame = wxDynamicCast(GetParent(), wxFrame); if ( frame && frame->GetToolBar() == this ) { - // the toolbar size changed - ::SendMessage(GetHwnd(), TB_AUTOSIZE, 0, 0); frame->SendSizeEvent(); } } @@ -1249,6 +1272,12 @@ void wxToolBar::UpdateSize() // toolbar styles // --------------------------------------------------------------------------- +// get the TBSTYLE of the given toolbar window +long wxToolBar::GetMSWToolbarStyle() const +{ + return ::SendMessage(GetHwnd(), TB_GETSTYLE, 0, 0L); +} + void wxToolBar::SetWindowStyleFlag(long style) { // the style bits whose changes force us to recreate the toolbar @@ -1329,7 +1358,7 @@ void wxToolBar::OnMouseEvent(wxMouseEvent& event) if ( event.RightDown() ) { // find the tool under the mouse - wxCoord x,y; + wxCoord x = 0, y = 0; event.GetPosition(&x, &y); wxToolBarToolBase *tool = FindToolForPosition(x, y); @@ -1345,34 +1374,48 @@ void wxToolBar::OnMouseEvent(wxMouseEvent& event) // colour: for example, when it must blend in with a notebook page. void wxToolBar::OnEraseBackground(wxEraseEvent& event) { - wxColour bgCol = GetBackgroundColour(); - if (!bgCol.Ok()) - { - event.Skip(); - return; - } - - // notice that this 'dumb' implementation may cause flicker for some of the - // controls in which case they should intercept wxEraseEvent and process it - // themselves somehow - - RECT rect; - ::GetClientRect(GetHwnd(), &rect); - - HBRUSH hBrush = ::CreateSolidBrush(wxColourToRGB(bgCol)); - + RECT rect = wxGetClientRect(GetHwnd()); HDC hdc = GetHdcOf((*event.GetDC())); -#ifndef __WXWINCE__ - int mode = ::SetMapMode(hdc, MM_TEXT); -#endif +#if wxUSE_UXTHEME + // we may need to draw themed colour so that we appear correctly on + // e.g. notebook page under XP with themes but only do it if the parent + // draws themed background itself + if ( !UseBgCol() && !GetParent()->UseBgCol() ) + { + wxUxThemeEngine *theme = wxUxThemeEngine::GetIfActive(); + if ( theme ) + { + HRESULT + hr = theme->DrawThemeParentBackground(GetHwnd(), hdc, &rect); + if ( hr == S_OK ) + return; + + // it can also return S_FALSE which seems to simply say that it + // didn't draw anything but no error really occurred + if ( FAILED(hr) ) + wxLogApiError(_T("DrawThemeParentBackground(toolbar)"), hr); + } + } +#endif // wxUSE_UXTHEME - ::FillRect(hdc, &rect, hBrush); - ::DeleteObject(hBrush); + if ( UseBgCol() || (GetMSWToolbarStyle() & TBSTYLE_TRANSPARENT) ) + { + // do draw our background + // + // notice that this 'dumb' implementation may cause flicker for some of + // the controls in which case they should intercept wxEraseEvent and + // process it themselves somehow + AutoHBRUSH hBrush(wxColourToRGB(GetBackgroundColour())); -#ifndef __WXWINCE__ - ::SetMapMode(hdc, mode); -#endif + wxCHANGE_HDC_MAP_MODE(hdc, MM_TEXT); + ::FillRect(hdc, &rect, hBrush); + } + else // we have no non default background colour + { + // let the system do it for us + event.Skip(); + } } bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam) @@ -1570,6 +1613,8 @@ WXLRESULT wxToolBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam // private functions // ---------------------------------------------------------------------------- +#ifdef wxREMAP_BUTTON_COLOURS + WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height) { MemoryHDC hdcMem; @@ -1605,7 +1650,8 @@ WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height) abs(GetGValue(pixel) - GetGValue(col)) < 10 && abs(GetBValue(pixel) - GetBValue(col)) < 10 ) { - ::SetPixel(hdcMem, i, j, cmap[k].to); + if ( cmap[k].to != pixel ) + ::SetPixel(hdcMem, i, j, cmap[k].to); break; } } @@ -1613,68 +1659,8 @@ WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height) } return bitmap; - - // VZ: I leave here my attempts to map the bitmap to the system colours - // faster by using BitBlt() even though it's broken currently - but - // maybe someone else can finish it? It should be faster than iterating - // over all pixels... -#if 0 - MemoryHDC hdcMask, hdcDst; - if ( !hdcMask || !hdcDst ) - { - wxLogLastError(_T("CreateCompatibleDC")); - - return bitmap; - } - - // create the target bitmap - HBITMAP hbmpDst = ::CreateCompatibleBitmap(hdcDst, width, height); - if ( !hbmpDst ) - { - wxLogLastError(_T("CreateCompatibleBitmap")); - - return bitmap; - } - - // create the monochrome mask bitmap - HBITMAP hbmpMask = ::CreateBitmap(width, height, 1, 1, 0); - if ( !hbmpMask ) - { - wxLogLastError(_T("CreateBitmap(mono)")); - - ::DeleteObject(hbmpDst); - - return bitmap; - } - - SelectInHDC bmpInDst(hdcDst, hbmpDst), - bmpInMask(hdcMask, hbmpMask); - - // for each colour: - for ( n = 0; n < NUM_OF_MAPPED_COLOURS; n++ ) - { - // create the mask for this colour - ::SetBkColor(hdcMem, ColorMap[n].from); - ::BitBlt(hdcMask, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY); - - // replace this colour with the target one in the dst bitmap - HBRUSH hbr = ::CreateSolidBrush(ColorMap[n].to); - HGDIOBJ hbrOld = ::SelectObject(hdcDst, hbr); - - ::MaskBlt(hdcDst, 0, 0, width, height, - hdcMem, 0, 0, - hbmpMask, 0, 0, - MAKEROP4(PATCOPY, SRCCOPY)); - - (void)::SelectObject(hdcDst, hbrOld); - ::DeleteObject(hbr); - } - - ::DeleteObject((HBITMAP)bitmap); - - return (WXHBITMAP)hbmpDst; -#endif // 0 } -#endif // wxUSE_TOOLBAR +#endif // wxREMAP_BUTTON_COLOURS +#endif // wxUSE_TOOLBAR