X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/de85a884d77ad5a29b418b343d4d3cc99c127b5e..a174f139e105c38ae852104eb6a894b3a0d88e07:/src/msw/tbar95.cpp diff --git a/src/msw/tbar95.cpp b/src/msw/tbar95.cpp index afa81726ae..749aa2bd52 100644 --- a/src/msw/tbar95.cpp +++ b/src/msw/tbar95.cpp @@ -115,13 +115,6 @@ #define DEFAULTBUTTONY 24 #define DEFAULTBARHEIGHT 27 -// ---------------------------------------------------------------------------- -// private function prototypes -// ---------------------------------------------------------------------------- - -// adjust toolbar bitmap colours -// static void wxMapBitmap(HBITMAP hBitmap, int width, int height); - // ---------------------------------------------------------------------------- // wxWin macros // ---------------------------------------------------------------------------- @@ -218,14 +211,17 @@ bool wxToolBar::Create(wxWindow *parent, long style, const wxString& name) { + // toolbars never have border, giving one to them results in broken + // appearance + style &= ~wxBORDER_MASK; + style |= wxBORDER_NONE; + // common initialisation 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; if ( style & wxCLIP_SIBLINGS ) msflags |= WS_CLIPSIBLINGS; @@ -487,7 +483,8 @@ bool wxToolBar::Realize() #endif // USE_BITMAP_MASKS/!USE_BITMAP_MASKS // Map to system colours - MapBitmap((WXHBITMAP) hBitmap, totalBitmapWidth, totalBitmapHeight); + hBitmap = (HBITMAP)MapBitmap((WXHBITMAP) hBitmap, + totalBitmapWidth, totalBitmapHeight); int bitmapId = 0; @@ -612,19 +609,18 @@ bool wxToolBar::Realize() // ------------------------------ // adjust the controls size to fit nicely in the toolbar + int y = 0; size_t index = 0; for ( node = m_tools.GetFirst(); node; node = node->GetNext(), index++ ) { wxToolBarToolBase *tool = node->GetData(); - if ( !tool->IsControl() ) - continue; - wxControl *control = tool->GetControl(); - - wxSize size = control->GetSize(); - - // the position of the leftmost controls corner - int left = -1; + // we calculate the running y coord for vertical toolbars so we need to + // get the items size for all items but for the horizontal ones we + // don't need to deal with the non controls + bool isControl = tool->IsControl(); + if ( !isControl && !isVertical ) + continue; // note that we use TB_GETITEMRECT and not TB_GETRECT because the // latter only appeared in v4.70 of comctl32.dll @@ -635,60 +631,75 @@ bool wxToolBar::Realize() wxLogLastError(wxT("TB_GETITEMRECT")); } + if ( !isControl ) + { + // can only be control if isVertical + y += r.bottom - r.top; + + continue; + } + + wxControl *control = tool->GetControl(); + + wxSize size = control->GetSize(); + + // the position of the leftmost controls corner + int left = -1; + // TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+ - #if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 ) - // available in headers, now check whether it is available now - // (during run-time) - if ( wxTheApp->GetComCtl32Version() >= 471 ) +#if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 ) + // available in headers, now check whether it is available now + // (during run-time) + if ( wxTheApp->GetComCtl32Version() >= 471 ) + { + // set the (underlying) separators width to be that of the + // control + TBBUTTONINFO tbbi; + tbbi.cbSize = sizeof(tbbi); + tbbi.dwMask = TBIF_SIZE; + tbbi.cx = size.x; + if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO, + tool->GetId(), (LPARAM)&tbbi) ) { - // set the (underlying) separators width to be that of the - // control - TBBUTTONINFO tbbi; - tbbi.cbSize = sizeof(tbbi); - tbbi.dwMask = TBIF_SIZE; - tbbi.cx = size.x; - if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO, - tool->GetId(), (LPARAM)&tbbi) ) - { - // the id is probably invalid? - wxLogLastError(wxT("TB_SETBUTTONINFO")); - } + // the id is probably invalid? + wxLogLastError(wxT("TB_SETBUTTONINFO")); } - else - #endif // comctl32.dll 4.71 - // TB_SETBUTTONINFO unavailable + } + else +#endif // comctl32.dll 4.71 + // TB_SETBUTTONINFO unavailable + { + // try adding several separators to fit the controls width + int widthSep = r.right - r.left; + left = r.left; + + TBBUTTON tbb; + wxZeroMemory(tbb); + tbb.idCommand = 0; + tbb.fsState = TBSTATE_ENABLED; + tbb.fsStyle = TBSTYLE_SEP; + + size_t nSeparators = size.x / widthSep; + for ( size_t nSep = 0; nSep < nSeparators; nSep++ ) { - // try adding several separators to fit the controls width - int widthSep = r.right - r.left; - left = r.left; - - TBBUTTON tbb; - wxZeroMemory(tbb); - tbb.idCommand = 0; - tbb.fsState = TBSTATE_ENABLED; - tbb.fsStyle = TBSTYLE_SEP; - - size_t nSeparators = size.x / widthSep; - for ( size_t nSep = 0; nSep < nSeparators; nSep++ ) + if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON, + index, (LPARAM)&tbb) ) { - if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON, - index, (LPARAM)&tbb) ) - { - wxLogLastError(wxT("TB_INSERTBUTTON")); - } - - index++; + wxLogLastError(wxT("TB_INSERTBUTTON")); } - // remember the number of separators we used - we'd have to - // delete all of them later - ((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators); - - // adjust the controls width to exactly cover the separators - control->SetSize((nSeparators + 1)*widthSep, -1); + index++; } - // and position the control itself correctly vertically + // remember the number of separators we used - we'd have to + // delete all of them later + ((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators); + + // adjust the controls width to exactly cover the separators + control->SetSize((nSeparators + 1)*widthSep, -1); + } + + // position the control itself correctly vertically int height = r.bottom - r.top; int diff = height - size.y; if ( diff < 0 ) @@ -699,7 +710,23 @@ bool wxToolBar::Realize() diff = 2; } - control->Move(left == -1 ? r.left : left, r.top + (diff + 1) / 2); + int top; + if ( isVertical ) + { + left = 0; + top = y; + + y += height + 2*GetMargins().y; + } + else // horizontal toolbar + { + if ( left == -1 ) + left = r.left; + + top = r.top; + } + + control->Move(left, top + (diff + 1) / 2); } // the max index is the "real" number of buttons - i.e. counting even the @@ -803,8 +830,9 @@ bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl), // this case size_t lenAnsi = help.Len(); - #ifdef __MWERKS__ + #if defined( __MWERKS__ ) || defined( __CYGWIN__ ) // MetroWerks doesn't like calling mbstowcs with NULL argument + // neither Cygwin does size_t lenUnicode = 2*lenAnsi; #else size_t lenUnicode = mbstowcs(NULL, help, lenAnsi); @@ -1074,122 +1102,174 @@ long wxToolBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) // private functions // ---------------------------------------------------------------------------- -bool wxToolBar::sm_coloursInit = FALSE; -long wxToolBar::sm_stdColours[6]; - -void wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height) +WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height) { - if (!sm_coloursInit) + // 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]; + + if (!s_coloursInit) { - // When a bitmap is loaded, the RGB values can change. So we need to have a + // 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("wxBITMAP_STD_COLOURS", wxBITMAP_TYPE_RESOURCE); + wxBitmap stdColourBitmap(_T("wxBITMAP_STD_COLOURS")); if (stdColourBitmap.Ok()) { wxMemoryDC memDC; memDC.SelectObject(stdColourBitmap); - int i = 0; wxColour colour; - for (i = 0; i < 6; i++) + for ( size_t i = 0; i < WXSIZEOF(s_stdColours); i++ ) { - memDC.GetPixel(i, 0, & colour); - sm_stdColours[i] = RGB(colour.Red(), colour.Green(), colour.Blue()); + memDC.GetPixel(i, 0, &colour); + s_stdColours[i] = wxColourToRGB(colour); } - sm_coloursInit = TRUE; - memDC.SelectObject(wxNullBitmap); } else { - sm_stdColours[0] = RGB(000,000,000) ; - sm_stdColours[1] = RGB(128,128,128) ; - sm_stdColours[2] = RGB(192,192,192) ; - sm_stdColours[3] = RGB(255,255,255) ; - sm_stdColours[4] = RGB(000,000,255) ; - sm_stdColours[5] = RGB(255,000,255) ; - sm_coloursInit = TRUE; + 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) ; } - } - HBITMAP hBitmap = (HBITMAP) bitmap; + s_coloursInit = TRUE; + } - COLORMAP ColorMap[5]; + 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++ ) + { + ColorMap[n].to = ::GetSysColor(ColorMap[n].to); + } - ColorMap[0].from = sm_stdColours[0]; ColorMap[0].to = COLOR_BTNTEXT; // black (0, 0 0) - ColorMap[1].from = sm_stdColours[1]; ColorMap[1].to = COLOR_BTNSHADOW; // dark grey (128, 128, 128) - ColorMap[2].from = sm_stdColours[2]; ColorMap[2].to = COLOR_BTNFACE; // bright grey (192, 192, 192) - ColorMap[3].from = sm_stdColours[3]; ColorMap[3].to = COLOR_BTNHIGHLIGHT; // white (255, 255, 255) - // ColorMap[4].from = sm_stdColours[4]; ColorMap[4].to = COLOR_HIGHLIGHT; // blue (0, 0, 255) - ColorMap[4].from = sm_stdColours[5]; ColorMap[4].to = COLOR_WINDOW; // magenta (255, 0, 255) + MemoryHDC hdcMem; - for ( size_t n = 0; n < WXSIZEOF(ColorMap); n++) + if ( !hdcMem ) { - ColorMap[n].to = ::GetSysColor(ColorMap[n].to); + wxLogLastError(_T("CreateCompatibleDC")); + + return bitmap; } - HBITMAP hbmOld; - HDC hdcMem = CreateCompatibleDC(NULL); + SelectInHDC bmpInHDC(hdcMem, (HBITMAP)bitmap); - if (hdcMem) + if ( !bmpInHDC ) { - hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap); + wxLogLastError(_T("SelectObject")); - for ( int i = 0; i < width; i++ ) + 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 1 + for ( int i = 0; i < width; i++ ) + { + for ( int j = 0; j < height; j++ ) { - for ( int j = 0; j < height; j++ ) - { - COLORREF pixel = ::GetPixel(hdcMem, i, j); + COLORREF pixel = ::GetPixel(hdcMem, i, j); - for ( size_t k = 0; k < WXSIZEOF(ColorMap); k++ ) + for ( size_t k = 0; k < WXSIZEOF(ColorMap); k++ ) + { + if ( pixel == ColorMap[k].from ) { - int distance = abs( GetRValue( pixel ) - GetRValue( ColorMap[k].from )) ; - distance = max( distance , abs(GetGValue(pixel ) - GetGValue( ColorMap[k].from ))) ; - distance = max( distance , abs(GetBValue(pixel ) - GetBValue( ColorMap[k].from ))) ; - if ( distance < 0x10 ) - { - ::SetPixel(hdcMem, i, j, ColorMap[k].to); - break; - } + ::SetPixel(hdcMem, i, j, ColorMap[k].to); + break; } } } + } + return bitmap; +#else // 1 + MemoryHDC hdcMask, hdcDst; + if ( !hdcMask || !hdcDst ) + { + wxLogLastError(_T("CreateCompatibleDC")); - SelectObject(hdcMem, hbmOld); - DeleteObject(hdcMem); + return bitmap; } -} -// Some experiments... -#if 0 -// What we want to do is create another bitmap which has a depth of 4, -// and set the bits. So probably we want to convert this HBITMAP into a -// DIB, then call SetDIBits. -// AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of -// the screen), then SetDIBits fails. -HBITMAP newBitmap = ::CreateBitmap(totalBitmapWidth, totalBitmapHeight, 1, 4, NULL); -HANDLE newDIB = ::BitmapToDIB((HBITMAP) m_hBitmap, NULL); -LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) GlobalLock(newDIB); - -dc = ::GetDC(NULL); -// LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB; - -int result = ::SetDIBits(dc, newBitmap, 0, lpbmi->biHeight, FindDIBBits((LPSTR)lpbmi), (LPBITMAPINFO)lpbmi, - DIB_PAL_COLORS); -DWORD err = GetLastError(); - -::ReleaseDC(NULL, dc); - -// Delete the DIB -GlobalUnlock (newDIB); -GlobalFree (newDIB); - -// WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap); -// Substitute our new bitmap for the old one -::DeleteObject((HBITMAP) m_hBitmap); -m_hBitmap = (WXHBITMAP) newBitmap; -#endif + // 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/1 +} #endif // wxUSE_TOOLBAR && Win95