X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d624fd67f82a90d74c7f796b241508663367134f..2c8e47380ebbcb5764307d4a8b15e84d8ce74ccf:/src/msw/dc.cpp diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 72de5d6db8..354c617418 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -48,9 +48,6 @@ #include "wx/msw/private.h" // needs to be before #include #if wxUSE_COMMON_DIALOGS -#if wxUSE_NORLANDER_HEADERS - #include -#endif #include #endif @@ -74,6 +71,10 @@ static const int MM_METRIC = 10; static const double M_PI = 3.14159265358979323846; #endif // M_PI +// ROPs which don't have standard names (see "Ternary Raster Operations" in the +// MSDN docs for how this and other numbers in wxDC::Blit() are obtained) +#define DSTCOPY 0x00AA0029 // a.k.a. NOP operation + // --------------------------------------------------------------------------- // private functions // --------------------------------------------------------------------------- @@ -317,12 +318,15 @@ bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const // get the color of the pixel COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y)); + // JACS: what was this for? +#if 0 // get the color of the pen COLORREF pencolor = 0x00ffffff; if (m_pen.Ok()) { pencolor = m_pen.GetColour().GetPixel(); } +#endif // return the color of the pixel if( col ) @@ -334,7 +338,10 @@ bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const // check, if color of the pixels is the same as the color of the current // pen and return TRUE if it is, FALSE otherwise - return pixelcolor == pencolor; + // JACS, 24/02/2000: can't understand the reason for this, so returning TRUE instead. + // return pixelcolor == pencolor; + + return TRUE; } void wxDC::DoCrossHair(wxCoord x, wxCoord y) @@ -359,10 +366,9 @@ void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), NULL); (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y2)); - /* MATTHEW: [6] New normalization */ -#if WX_STANDARD_GRAPHICS - (void)LineTo(GetHdc(), XLOG2DEV(x2) + 1, YLOG2DEV(y2)); -#endif + // Normalization: Windows doesn't draw the last point of the line. + // But apparently neither does GTK+, so we take it out again. +// (void)LineTo(GetHdc(), XLOG2DEV(x2) + 1, YLOG2DEV(y2)); CalcBoundingBox(x1, y1); CalcBoundingBox(x2, y2); @@ -410,6 +416,41 @@ void wxDC::DoDrawArc(wxCoord x1,wxCoord y1,wxCoord x2,wxCoord y2, wxCoord xc, wx CalcBoundingBox((wxCoord)(xc+radius), (wxCoord)(yc+radius)); } +void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, + wxCoord width, wxCoord height) +{ + wxCoord x2 = x1 + width, + y2 = y1 + height; + +#if defined(__WIN32__) && !defined(__SC__) + RECT rect; + rect.left = x1; + rect.top = y1; + rect.right = x2; + rect.bottom = y2; + + DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK); +#else // Win16 + // In WIN16, draw a cross + HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); + HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH); + HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen); + HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush); + ::SetROP2(GetHdc(), R2_COPYPEN); + Rectangle(GetHdc(), x1, y1, x2, y2); + MoveTo(GetHdc(), x1, y1); + LineTo(GetHdc(), x2, y2); + MoveTo(GetHdc(), x2, y1); + LineTo(GetHdc(), x1, y2); + ::SelectObject(GetHdc(), hPenOld); + ::SelectObject(GetHdc(), hBrushOld); + ::DeleteObject(blackPen); +#endif // Win32/16 + + CalcBoundingBox(x1, y1); + CalcBoundingBox(x2, y2); +} + void wxDC::DoDrawPoint(wxCoord x, wxCoord y) { COLORREF color = 0x00ffffff; @@ -541,16 +582,31 @@ void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) wxCoord x2 = x + width; wxCoord y2 = y + height; - // Windows draws the filled rectangles without outline (i.e. drawn with a - // transparent pen) one pixel smaller in both directions and we want them - // to have the same size regardless of which pen is used - adjust - if ( m_pen.GetStyle() == wxTRANSPARENT ) + if ((m_logicalFunction == wxCOPY) && (m_pen.GetStyle() == wxTRANSPARENT)) { - x2++; - y2++; + RECT rect; + rect.left = XLOG2DEV(x); + rect.top = YLOG2DEV(y); + rect.right = XLOG2DEV(x2); + rect.bottom = YLOG2DEV(y2); + (void)FillRect(GetHdc(), &rect, (HBRUSH)m_brush.GetResourceHandle() ); + } + else + { + // Windows draws the filled rectangles without outline (i.e. drawn with a + // transparent pen) one pixel smaller in both directions and we want them + // to have the same size regardless of which pen is used - adjust + + // I wonder if this shouldn´t be done after the LOG2DEV() conversions. RR. + if ( m_pen.GetStyle() == wxTRANSPARENT ) + { + x2++; + y2++; + } + + (void)Rectangle(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2)); } - (void)Rectangle(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2)); CalcBoundingBox(x, y); CalcBoundingBox(x2, y2); @@ -582,6 +638,15 @@ void wxDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord h wxCoord x2 = (x+width); wxCoord y2 = (y+height); + // Windows draws the filled rectangles without outline (i.e. drawn with a + // transparent pen) one pixel smaller in both directions and we want them + // to have the same size regardless of which pen is used - adjust + if ( m_pen.GetStyle() == wxTRANSPARENT ) + { + x2++; + y2++; + } + (void)RoundRect(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2), (int) (2*XLOG2DEV(radius)), (int)( 2*YLOG2DEV(radius))); @@ -679,30 +744,19 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask HDC hdcMem = ::CreateCompatibleDC(GetHdc()); ::SelectObject(hdcMem, GetHbitmapOf(bmp)); - // this will only work if the transparent part of our bitmap is black - // because it is combined with the destination rectangle using OR, so - // it won't be really transparent otherwise - I don't know what to do - // about it, may be use MAKEROP4(SRCCOPY, DSTINVERT) twice? Or create a - // copy of the bitmap with the transparent part replaced with black - // pixels? - - // GRG: now this works regardless of what the source bitmap - // contains in the area which is to be transparent. - // + // use MaskBlt() with ROP which doesn't do anything to dst in the mask + // points bool ok = ::MaskBlt(GetHdc(), x, y, width, height, hdcMem, 0, 0, hbmpMask, 0, 0, - MAKEROP4(SRCCOPY, 0x00AA0029)) != 0; + MAKEROP4(SRCCOPY, DSTCOPY)) != 0; ::DeleteDC(hdcMem); if ( !ok ) #endif // Win32 { - // VZ: this is incorrect, Blit() doesn't (and can't) draw - // transparently, but it's still better than nothing at all - // GRG: Blit() *should* draw transparently when there is a mask - - // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level + // Rather than reproduce wxDC::Blit, let's do it at the wxWin API + // level wxMemoryDC memDC; memDC.SelectObject(bmp); @@ -1048,22 +1102,23 @@ void wxDC::SetRop(WXHDC dc) switch (m_logicalFunction) { + case wxCLEAR: rop = R2_BLACK; break; case wxXOR: rop = R2_XORPEN; break; case wxINVERT: rop = R2_NOT; break; case wxOR_REVERSE: rop = R2_MERGEPENNOT; break; case wxAND_REVERSE: rop = R2_MASKPENNOT; break; - case wxCLEAR: rop = R2_WHITE; break; - case wxSET: rop = R2_BLACK; break; - case wxOR_INVERT: rop = R2_MERGENOTPEN; break; + case wxCOPY: rop = R2_COPYPEN; break; case wxAND: rop = R2_MASKPEN; break; - case wxOR: rop = R2_MERGEPEN; break; - case wxEQUIV: rop = R2_NOTXORPEN; break; - case wxNAND: rop = R2_NOTMASKPEN; break; case wxAND_INVERT: rop = R2_MASKNOTPEN; break; - case wxCOPY: rop = R2_COPYPEN; break; case wxNO_OP: rop = R2_NOP; break; - case wxSRC_INVERT: rop = R2_NOTCOPYPEN; break; case wxNOR: rop = R2_NOTMERGEPEN; break; + case wxEQUIV: rop = R2_NOTXORPEN; break; + case wxSRC_INVERT: rop = R2_NOTCOPYPEN; break; + case wxOR_INVERT: rop = R2_MERGENOTPEN; break; + case wxNAND: rop = R2_NOTMASKPEN; break; + case wxOR: rop = R2_MERGEPEN; break; + case wxSET: rop = R2_WHITE; break; + default: wxFAIL_MSG( wxT("unsupported logical function") ); return; @@ -1334,7 +1389,7 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, case wxNAND: dwRop = 0x007700E6; break; case wxAND_INVERT: dwRop = 0x00220326; break; case wxCOPY: dwRop = SRCCOPY; break; - case wxNO_OP: dwRop = 0x00AA0029; break; + case wxNO_OP: dwRop = DSTCOPY; break; case wxSRC_INVERT: dwRop = NOTSRCCOPY; break; case wxNOR: dwRop = NOTSRCCOPY; break; default: @@ -1347,46 +1402,14 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, if (useMask) { #ifdef __WIN32__ - // prepare the mask bitmap - HBITMAP hbmpMask = wxInvertMask((HBITMAP)mask->GetMaskBitmap()); - - // select the correct brush: the current one by default, background one - // if none - HBRUSH hbrNew; - if ( m_brush.Ok() ) - { - hbrNew = (HBRUSH)m_brush.GetResourceHandle(); - } - else if ( m_backgroundBrush.Ok() ) - { - hbrNew = (HBRUSH)m_backgroundBrush.GetResourceHandle(); - } - else - { - hbrNew = 0; - } - - HGDIOBJ hbrOld = hbrNew ? ::SelectObject(GetHdc(), hbrNew) : 0; - // we want the part of the image corresponding to the mask to be - // transparent, i.e. do PATCOPY there and apply dwRop elsewhere - - // GRG: PATCOPY is not transparent, as can be seen when blitting - // over a pattern: the 'transparent' area would be filled - // with the selected colour. We should use NOP instead, or - // do MaskBlt + BitBlt. - // + // transparent, so use "DSTCOPY" ROP for the mask points (the usual + // meaning of fg and bg is inverted which corresponds to wxWin notion + // of the mask which is also contrary to the Windows one) success = ::MaskBlt(GetHdc(), xdest, ydest, width, height, GetHdcOf(*source), xsrc, ysrc, - hbmpMask, 0, 0, - MAKEROP4(0x00AA0029, dwRop)) != 0; - - if ( hbrNew ) - { - (void)::SelectObject(GetHdc(), hbrOld); - } - - ::DeleteObject(hbmpMask); + (HBITMAP)mask->GetMaskBitmap(), 0, 0, + MAKEROP4(dwRop, DSTCOPY)) != 0; if ( !success ) #endif // Win32