diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index 61197650e7..f850b7b554 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -1109,6 +1109,8 @@ extern WXDLLIMPEXP_CORE wxSize wxGetHiconSize(HICON hicon); WXDLLIMPEXP_CORE void wxDrawLine(HDC hdc, int x1, int y1, int x2, int y2); +WXDLLIMPEXP_CORE void wxDrawHVLine(HDC hdc, int x1, int y1, int x2, int y2, COLORREF color, int width); + // fill the client rect of the given window on the provided dc using this brush inline void wxFillRect(HWND hwnd, HDC hdc, HBRUSH hbr) { diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index fec2650f2e..6f91e9f55f 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -819,7 +819,31 @@ void wxMSWDCImpl::DoCrossHair(wxCoord x, wxCoord y) void wxMSWDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) { - wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2)); + // We have optimized function to draw physical vertical or horizontal lines + // with solid color and square ends. + // Because checking wheteher the line would be horizontal/vertical + // in the device coordinate system is complex so we only check whether + // the line is horizontal/vertical in the logical coordinates and use + // optimized function only for DC which coordinate system is for sure + // not rotated (graphics mode of the DC != GM_ADVANCED). + // Moreover, optimized function can be used only for regular lines with pen + // width > 0 because it doesn't support drawing non-scaled 1-pixel wide + // lines when pen width is 0. + if ( (x1 == x2 || y1 == y2) && + ::GetGraphicsMode(GetHdc()) != GM_ADVANCED && // ensure DC is not rotated + m_pen.IsNonTransparent() && // this calls IsOk() too + m_pen.GetStyle() == wxPENSTYLE_SOLID && + m_pen.GetWidth() > 0 && + (m_pen.GetWidth() == 1 || m_pen.GetCap() == wxCAP_BUTT) + ) + { + wxDrawHVLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2), + wxColourToRGB(m_pen.GetColour()), m_pen.GetWidth()); + } + else + { + wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2)); + } CalcBoundingBox(x1, y1); CalcBoundingBox(x2, y2); diff --git a/src/msw/utilsgui.cpp b/src/msw/utilsgui.cpp index 7c7bfcf07c..ec67bb7a8a 100644 --- a/src/msw/utilsgui.cpp +++ b/src/msw/utilsgui.cpp @@ -209,6 +209,35 @@ void wxDrawLine(HDC hdc, int x1, int y1, int x2, int y2) MoveToEx(hdc, x1, y1, NULL); LineTo((HDC) hdc, x2, y2); } +// Function dedicated to drawing horizontal/vertical lines with solid color +// It fills rectangle representing the line with ::ExtTextOut() API which +// apparently is faster than ::MoveTo()/::LineTo() on DC with a non-rotated +// coordinate system. +void wxDrawHVLine(HDC hdc, int x1, int y1, int x2, int y2, COLORREF color, int width) +{ + wxASSERT(x1 == x2 || y1 == y2); + + int w1 = width / 2; + int w2 = width - w1; + RECT r; + if ( y1 == y2 ) + { + if ( x1 == x2 ) + return; + ::SetRect(&r, x1, y1 - w1, x2, y1 + w2); + } + else + { + ::SetRect(&r, x1 - w1, y1, x2 + w2, y2); + } + + COLORREF bgColorOrig = ::GetBkColor(hdc); + ::SetBkColor(hdc, color); + + ::ExtTextOutW(hdc, 0, 0, ETO_OPAQUE, &r, L"", 0, NULL); + + ::SetBkColor(hdc, bgColorOrig); +} // ---------------------------------------------------------------------------- // Shell API wrappers