X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8a0681f9338345d0ef32b2ad809d49fd20861119..28be2e8a170979d476a5ea4f585505b8a2f5af27:/src/msw/tbar95.cpp diff --git a/src/msw/tbar95.cpp b/src/msw/tbar95.cpp index 77bc8885dc..589df6cf67 100644 --- a/src/msw/tbar95.cpp +++ b/src/msw/tbar95.cpp @@ -35,6 +35,7 @@ #include "wx/dynarray.h" #include "wx/settings.h" #include "wx/bitmap.h" + #include "wx/dcmemory.h" #endif #if wxUSE_TOOLBAR && defined(__WIN95__) && wxUSE_TOOLBAR_NATIVE @@ -60,6 +61,18 @@ #include "wx/msw/dib.h" #include "wx/app.h" // for GetComCtl32Version +// ---------------------------------------------------------------------------- +// conditional compilation +// ---------------------------------------------------------------------------- + +// wxWindows previously always considered that toolbar buttons have light grey +// (0xc0c0c0) background and so ignored any bitmap masks - however, this +// doesn't work with XPMs which then appear to have black background. To make +// this work, we must respect the bitmap masks - which we do now. This should +// be ok in any case, but to restore 100% compatible with the old version +// behaviour, you can set this to 0. +#define USE_BITMAP_MASKS 1 + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -95,13 +108,14 @@ // private function prototypes // ---------------------------------------------------------------------------- +// adjust toolbar bitmap colours static void wxMapBitmap(HBITMAP hBitmap, int width, int height); // ---------------------------------------------------------------------------- // wxWin macros // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxControl) +IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase) BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent) @@ -192,14 +206,17 @@ bool wxToolBar::Create(wxWindow *parent, const wxString& name) { // common initialisation - if ( !CreateControl(parent, id, pos, size, style, name) ) + if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) ) return FALSE; // prepare flags DWORD msflags = 0; // WS_VISIBLE | WS_CHILD always included if (style & wxBORDER) msflags |= WS_BORDER; + +#ifdef TBSTYLE_TOOLTIPS msflags |= TBSTYLE_TOOLTIPS; +#endif if (style & wxTB_FLAT) { @@ -242,7 +259,18 @@ bool wxToolBar::Create(wxWindow *parent, wxToolBar::~wxToolBar() { - if (m_hBitmap) + // we must refresh the frame size when the toolbar is deleted but the frame + // is not - otherwise toolbar leaves a hole in the place it used to occupy + // + // NB: a frame is being deleted only if it is not any longer in + // wxTopLevelWindows list + wxFrame *frame = wxDynamicCast(GetParent(), wxFrame); + if ( frame && wxTopLevelWindows.Find(frame) ) + { + frame->SendSizeEvent(); + } + + if ( m_hBitmap ) { ::DeleteObject((HBITMAP) m_hBitmap); } @@ -264,8 +292,32 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos), bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) { - // normally, we only delete one button, but we use several separators to - // cover the space used by one control sometimes (with old comctl32.dll) + // the main difficulty we have here is with the controls in the toolbars: + // as we (sometimes) use several separators to cover up the space used by + // them, the indices are not the same for us and the toolbar + + // first determine the position of the first button to delete: it may be + // different from pos if we use several separators to cover the space used + // by a control + wxToolBarToolsList::Node *node; + for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) + { + wxToolBarToolBase *tool2 = node->GetData(); + if ( tool2 == tool ) + { + // let node point to the next node in the list + node = node->GetNext(); + + break; + } + + if ( tool2->IsControl() ) + { + pos += ((wxToolBarTool *)tool2)->GetSeparatorsCount(); + } + } + + // now determine the number of buttons to delete and the area taken by them size_t nButtonsToDelete = 1; // get the size of the button we're going to delete @@ -284,11 +336,13 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) width *= nButtonsToDelete; } + // do delete all buttons + m_nButtons -= nButtonsToDelete; while ( nButtonsToDelete-- > 0 ) { if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) ) { - wxLogLastError("TB_DELETEBUTTON"); + wxLogLastError(wxT("TB_DELETEBUTTON")); return FALSE; } @@ -296,11 +350,9 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) tool->Detach(); - m_nButtons -= nButtonsToDelete; - - // reposition all the controls after this button - wxToolBarToolsList::Node *node = m_tools.Item(pos); - for ( node = node->GetNext(); node; node = node->GetNext() ) + // and finally reposition all the controls after this button (the toolbar + // takes care of all normal items) + for ( /* node -> first after deleted */ ; node; node = node->GetNext() ) { wxToolBarToolBase *tool2 = node->GetData(); if ( tool2->IsControl() ) @@ -336,7 +388,17 @@ bool wxToolBar::Realize() int totalBitmapWidth = (int)(m_defaultWidth * nTools); int totalBitmapHeight = (int)m_defaultHeight; - // Create a bitmap for all the tool bitmaps + // Create a bitmap and copy all the tool bitmaps to it +#if USE_BITMAP_MASKS + wxMemoryDC dcAllButtons; + wxBitmap bitmap(totalBitmapWidth, totalBitmapHeight); + dcAllButtons.SelectObject(bitmap); + dcAllButtons.SetBackground(*wxLIGHT_GREY_BRUSH); + dcAllButtons.Clear(); + + m_hBitmap = bitmap.GetHBITMAP(); + HBITMAP hBitmap = (HBITMAP)m_hBitmap; +#else // !USE_BITMAP_MASKS HBITMAP hBitmap = ::CreateCompatibleBitmap(ScreenHDC(), totalBitmapWidth, totalBitmapHeight); @@ -349,11 +411,11 @@ bool wxToolBar::Realize() m_hBitmap = (WXHBITMAP)hBitmap; - // Now blit all the tools onto this bitmap HDC memoryDC = ::CreateCompatibleDC(NULL); HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, hBitmap); HDC memoryDC2 = ::CreateCompatibleDC(NULL); +#endif // USE_BITMAP_MASKS/!USE_BITMAP_MASKS // the button position wxCoord x = 0; @@ -367,17 +429,23 @@ bool wxToolBar::Realize() wxToolBarToolBase *tool = node->GetData(); if ( tool->IsButton() ) { - HBITMAP hbmp = GetHbitmapOf(tool->GetBitmap1()); - if ( hbmp ) + const wxBitmap& bmp = tool->GetBitmap1(); + if ( bmp.Ok() ) { +#if USE_BITMAP_MASKS + // notice the last parameter: do use mask + dcAllButtons.DrawBitmap(tool->GetBitmap1(), x, 0, TRUE); +#else // !USE_BITMAP_MASKS + HBITMAP hbmp = GetHbitmapOf(bmp); HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp); if ( !BitBlt(memoryDC, x, 0, m_defaultWidth, m_defaultHeight, memoryDC2, 0, 0, SRCCOPY) ) { - wxLogLastError("BitBlt"); + wxLogLastError(wxT("BitBlt")); } ::SelectObject(memoryDC2, oldBitmap2); +#endif // USE_BITMAP_MASKS/!USE_BITMAP_MASKS } else { @@ -394,39 +462,69 @@ bool wxToolBar::Realize() node = node->GetNext(); } +#if USE_BITMAP_MASKS + dcAllButtons.SelectObject(wxNullBitmap); + + // don't delete this HBITMAP! + bitmap.SetHBITMAP(0); +#else // !USE_BITMAP_MASKS ::SelectObject(memoryDC, oldBitmap); ::DeleteDC(memoryDC); ::DeleteDC(memoryDC2); +#endif // USE_BITMAP_MASKS/!USE_BITMAP_MASKS // Map to system colours wxMapBitmap(hBitmap, totalBitmapWidth, totalBitmapHeight); + int bitmapId = 0; + + bool addBitmap = TRUE; + if ( oldToolBarBitmap ) { - TBREPLACEBITMAP replaceBitmap; - replaceBitmap.hInstOld = NULL; - replaceBitmap.hInstNew = NULL; - replaceBitmap.nIDOld = (UINT) oldToolBarBitmap; - replaceBitmap.nIDNew = (UINT) hBitmap; - replaceBitmap.nButtons = nButtons; - if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP, - 0, (LPARAM) &replaceBitmap) ) +#ifdef TB_REPLACEBITMAP + if ( wxTheApp->GetComCtl32Version() >= 400 ) { - wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); + TBREPLACEBITMAP replaceBitmap; + replaceBitmap.hInstOld = NULL; + replaceBitmap.hInstNew = NULL; + replaceBitmap.nIDOld = (UINT) oldToolBarBitmap; + replaceBitmap.nIDNew = (UINT) hBitmap; + replaceBitmap.nButtons = nButtons; + if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP, + 0, (LPARAM) &replaceBitmap) ) + { + wxFAIL_MSG(wxT("Could not replace the old bitmap")); + } + + ::DeleteObject(oldToolBarBitmap); + + // already done + addBitmap = FALSE; } + else +#endif // TB_REPLACEBITMAP + { + // we can't replace the old bitmap, so we will add another one + // (awfully inefficient, but what else to do?) and shift the bitmap + // indices accordingly + addBitmap = TRUE; - ::DeleteObject(oldToolBarBitmap); + bitmapId = m_nButtons; + } // Now delete all the buttons for ( size_t pos = 0; pos < m_nButtons; pos++ ) { if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, 0, 0) ) { - wxLogLastError("TB_DELETEBUTTON"); + wxLogLastError(wxT("TB_DELETEBUTTON")); } } + } - else // no old bitmap + + if ( addBitmap ) // no old bitmap or we can't replace it { TBADDBITMAP addBitmap; addBitmap.hInst = 0; @@ -447,8 +545,6 @@ bool wxToolBar::Realize() wxArrayInt controlIds; int i = 0; - int bitmapId = 0; - for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) { wxToolBarToolBase *tool = node->GetData(); @@ -494,7 +590,7 @@ bool wxToolBar::Realize() if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS, (WPARAM)i, (LPARAM)buttons) ) { - wxLogLastError("TB_ADDBUTTONS"); + wxLogLastError(wxT("TB_ADDBUTTONS")); } delete [] buttons; @@ -523,7 +619,7 @@ bool wxToolBar::Realize() if ( !SendMessage(GetHwnd(), TB_GETITEMRECT, index, (LPARAM)(LPRECT)&r) ) { - wxLogLastError("TB_GETITEMRECT"); + wxLogLastError(wxT("TB_GETITEMRECT")); } // TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+ @@ -542,9 +638,8 @@ bool wxToolBar::Realize() tool->GetId(), (LPARAM)&tbbi) ) { // the id is probably invalid? - wxLogLastError("TB_SETBUTTONINFO"); + wxLogLastError(wxT("TB_SETBUTTONINFO")); } - } else #endif // comctl32.dll 4.71 @@ -566,7 +661,7 @@ bool wxToolBar::Realize() if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON, index, (LPARAM)&tbb) ) { - wxLogLastError("TB_INSERTBUTTON"); + wxLogLastError(wxT("TB_INSERTBUTTON")); } index++; @@ -631,7 +726,7 @@ bool wxToolBar::MSWCommand(WXUINT cmd, WXWORD id) if ( tool->CanBeToggled() ) { LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0); - tool->SetToggle((state & TBSTATE_CHECKED) != 0); + tool->Toggle((state & TBSTATE_CHECKED) != 0); } bool toggled = tool->IsToggled(); @@ -682,11 +777,17 @@ bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl), { ttText->lpszText = (wxChar *)help.c_str(); } -#if (_WIN32_IE >= 0x0300) else { - // FIXME this is a temp hack only until I understand better what - // must be done in both ANSI and Unicode builds +#if wxUSE_UNICODE + ttText->lpszText = (wxChar *)help.c_str(); +#else + // VZ: I don't know why it happens, but the versions of + // comctl32.dll starting from 4.70 sometimes send TTN_NEEDTEXTW + // even to ANSI programs (normally, this message is supposed + // to be sent to Unicode programs only) - hence we need to + // handle it as well, otherwise no tooltips will be shown in + // this case size_t lenAnsi = help.Len(); #ifdef __MWERKS__ @@ -707,8 +808,8 @@ bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl), dst[lenUnicode] = 0; delete [] pwz; +#endif } -#endif // _WIN32_IE >= 0x0300 } // For backward compatibility... @@ -784,21 +885,15 @@ wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const void wxToolBar::UpdateSize() { - // we must refresh the frame after the toolbar size (possibly) changed + // the toolbar size changed + SendMessage(GetHwnd(), TB_AUTOSIZE, 0, 0); + + // we must also refresh the frame after the toolbar size (possibly) changed wxFrame *frame = wxDynamicCast(GetParent(), wxFrame); if ( frame ) { - // don't change the size, we just need to generate a WM_SIZE - RECT r; - if ( !GetWindowRect(GetHwndOf(frame), &r) ) - { - wxLogLastError(_T("GetWindowRect")); - } - - (void)::SendMessage(GetHwndOf(frame), WM_SIZE, SIZE_RESTORED, - MAKELPARAM(r.right - r.left, r.bottom - r.top)); + frame->SendSizeEvent(); } - } // ---------------------------------------------------------------------------- @@ -915,7 +1010,7 @@ long wxToolBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) #define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey #define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey #define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white -#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue +#define BGR_BACKGROUNDSEL (RGB(000,000,255)) // blue #define BGR_BACKGROUND (RGB(255,000,255)) // magenta void wxMapBitmap(HBITMAP hBitmap, int width, int height) @@ -926,7 +1021,7 @@ void wxMapBitmap(HBITMAP hBitmap, int width, int height) {BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey {BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white - {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue +/* {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue */ {BGR_BACKGROUND, COLOR_WINDOW} // magenta };