diff --git a/include/wx/msw/dc.h b/include/wx/msw/dc.h index 4cd330f22e..744fd3dcca 100644 --- a/include/wx/msw/dc.h +++ b/include/wx/msw/dc.h @@ -140,6 +140,9 @@ public: const wxBitmap& GetSelectedBitmap() const { return m_selectedBitmap; } wxBitmap& GetSelectedBitmap() { return m_selectedBitmap; } + // update the internal clip box variables + void UpdateClipBox(); + protected: virtual void DoFloodFill(wxCoord x, wxCoord y, const wxColour& col, int style = wxFLOOD_SURFACE); diff --git a/include/wx/msw/private.h b/include/wx/msw/private.h index 8af2cfce9a..67e82da840 100644 --- a/include/wx/msw/private.h +++ b/include/wx/msw/private.h @@ -293,6 +293,9 @@ private: #define GetHfont() ((HFONT)GetHFONT()) #define GetHfontOf(font) ((HFONT)(font).GetHFONT()) +#define GetHrgn() ((HRGN)GetHRGN()) +#define GetHrgnOf(rgn) ((HRGN)(rgn).GetHRGN()) + #endif // wxUSE_GUI // --------------------------------------------------------------------------- diff --git a/include/wx/univ/setup.h b/include/wx/univ/setup.h index 55d9dd069e..aed56d9911 100644 --- a/include/wx/univ/setup.h +++ b/include/wx/univ/setup.h @@ -126,7 +126,8 @@ #define wxUSE_MS_HTML_HELP 0 #define wxUSE_RESOURCES 0 #define wxUSE_CONSTRAINTS 0 -#define wxUSE_CLIPBOARD 0 +#define wxUSE_CLIPBOARD 1 +#define wxUSE_DATAOBJ 1 #define wxUSE_SPLINES 0 #define wxUSE_DRAG_AND_DROP 0 #define wxUSE_XPM_IN_MSW 1 diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h index 519e520f8e..5beea7d0b8 100644 --- a/include/wx/univ/textctrl.h +++ b/include/wx/univ/textctrl.h @@ -231,6 +231,8 @@ protected: const wxString& text, long selStart, long selEnd); + void DoDrawTextInRect(wxDC& dc, const wxRect& rectUpdate); + virtual void DoDraw(wxControlRenderer *renderer); // calc the size from the text extent diff --git a/samples/univ/univ.cpp b/samples/univ/univ.cpp index 49192562f8..78afc03195 100644 --- a/samples/univ/univ.cpp +++ b/samples/univ/univ.cpp @@ -53,6 +53,8 @@ #include "wx/univ/theme.h" +#define TEST_TEXT_ONLY + //#define DEBUG_SCROLL //#define DEBUG_LISTBOX @@ -214,7 +216,9 @@ bool MyUnivApp::OnInit() #ifdef DEBUG_LISTBOX wxLog::AddTraceMask(_T("listbox")); #endif +#ifdef TEST_TEXT_ONLY wxLog::AddTraceMask(_T("text")); +#endif return TRUE; } @@ -226,7 +230,7 @@ bool MyUnivApp::OnInit() MyUnivFrame::MyUnivFrame(const wxString& title) : wxFrame(NULL, -1, title, wxDefaultPosition, -#if 0 +#ifndef TEST_TEXT_ONLY wxSize(700, 700) #else wxSize(240, 150) @@ -236,7 +240,7 @@ MyUnivFrame::MyUnivFrame(const wxString& title) SetBackgroundColour(wxGetApp().GetBgColour()); new wxStaticText(this, _T("Test static text"), wxPoint(10, 10)); -#if 0 +#ifndef TEST_TEXT_ONLY new wxStaticText(this, _T("&Multi line\n(and very very very very long)\nstatic text"), wxPoint(210, 10)); @@ -378,10 +382,10 @@ MyUnivFrame::MyUnivFrame(const wxString& title) new wxTextCtrl(this, -1, _T("Hello, Universe!"), wxPoint(550, 150), wxDefaultSize); -#else // 1 +#else // TEST_TEXT_ONLY new wxTextCtrl(this, -1, _T("Hello, Universe!"), - wxPoint(10, 50), wxSize(200, -1)); -#endif // 0/1 + wxPoint(10, 40), wxSize(200, -1)); +#endif // !TEST_TEXT_ONLY/TEST_TEXT_ONLY } void MyUnivFrame::OnButton(wxCommandEvent& event) @@ -438,13 +442,15 @@ void MyUnivCanvas::OnPaint(wxPaintEvent& event) static bool s_oddRepaint = TRUE; s_oddRepaint = !s_oddRepaint; + +#ifdef DEBUG_SCROLL wxCoord x, y; GetViewStart(&x, &y); -#ifdef DEBUG_SCROLL wxLogDebug("Repainting with %s pen (at %dx%d)", s_oddRepaint ? "red" : "green", x, y); #endif // DEBUG_SCROLL + dc.SetPen(s_oddRepaint ? *wxRED_PEN: *wxGREEN_PEN); dc.SetTextForeground(s_oddRepaint ? *wxRED : *wxGREEN); @@ -452,7 +458,5 @@ void MyUnivCanvas::OnPaint(wxPaintEvent& event) dc.DrawText(_T("This is the top of the canvas"), 10, 10); dc.DrawLabel(_T("This is the bottom of the canvas"), wxRect(0, 950, 950, 50), wxALIGN_RIGHT | wxBOTTOM); - - //event.Skip(); } diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 59d1e67109..f92b3f9ff1 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -239,7 +239,7 @@ bool wxApp::Initialize() #endif // __WIN95__ -#if wxUSE_OLE +#if wxUSE_OLE || wxUSE_DRAG_AND_DROP || wxUSE_DATAOBJ #ifdef __WIN16__ // for OLE, enlarge message queue to be as large as possible @@ -250,6 +250,7 @@ bool wxApp::Initialize() // we need to initialize OLE library if ( FAILED(::OleInitialize(NULL)) ) wxLogError(_("Cannot initialize OLE")); + #endif // wxUSE_OLE #if wxUSE_CTL3D @@ -257,7 +258,7 @@ bool wxApp::Initialize() wxLogError(wxT("Cannot register CTL3D")); Ctl3dAutoSubclass(wxhInstance); -#endif +#endif // wxUSE_CTL3D // VZ: these icons are not in wx.rc anyhow (but should they?)! #if 0 diff --git a/src/msw/clipbrd.cpp b/src/msw/clipbrd.cpp index 9a2d7b327c..ecff1b8bd5 100644 --- a/src/msw/clipbrd.cpp +++ b/src/msw/clipbrd.cpp @@ -59,7 +59,7 @@ // wxDataObject is tied to OLE/drag and drop implementation, therefore so are // the functions using wxDataObject in wxClipboard -#define wxUSE_DATAOBJ wxUSE_DRAG_AND_DROP +//#define wxUSE_DATAOBJ wxUSE_DRAG_AND_DROP #if wxUSE_DATAOBJ #include "wx/dataobj.h" diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 4db677187b..aadda6ea9e 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -252,39 +252,45 @@ void wxDC::SelectOldObjects(WXHDC dc) // clipping // --------------------------------------------------------------------------- -#define DO_SET_CLIPPING_BOX() \ -{ \ - RECT rect; \ - \ - GetClipBox(GetHdc(), &rect); \ - \ - m_clipX1 = (wxCoord) XDEV2LOG(rect.left); \ - m_clipY1 = (wxCoord) YDEV2LOG(rect.top); \ - m_clipX2 = (wxCoord) XDEV2LOG(rect.right); \ - m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom); \ +void wxDC::UpdateClipBox() +{ + RECT rect; + GetClipBox(GetHdc(), &rect); + + m_clipX1 = (wxCoord) XDEV2LOG(rect.left); + m_clipY1 = (wxCoord) YDEV2LOG(rect.top); + m_clipX2 = (wxCoord) XDEV2LOG(rect.right); + m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom); } void wxDC::DoSetClippingRegion(wxCoord cx, wxCoord cy, wxCoord cw, wxCoord ch) { m_clipping = TRUE; - IntersectClipRect(GetHdc(), XLOG2DEV(cx), YLOG2DEV(cy), - XLOG2DEV(cx + cw), YLOG2DEV(cy + ch)); - DO_SET_CLIPPING_BOX() + + // NB: IntersectClipRect() accepts clogical coords and, as usual, excludes + // the right and bottom edges, so account for it + if ( IntersectClipRect(GetHdc(), + cx, cy, cx + cw + 1, cy + ch + 1) == ERROR ) + { + wxLogLastError(wxT("IntersectClipRect")); + } + + UpdateClipBox(); } void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region) { - wxCHECK_RET( region.GetHRGN(), wxT("invalid clipping region") ); + wxCHECK_RET( GetHrgnOf(region), wxT("invalid clipping region") ); m_clipping = TRUE; #ifdef __WIN16__ - SelectClipRgn(GetHdc(), (HRGN) region.GetHRGN()); -#else - ExtSelectClipRgn(GetHdc(), (HRGN) region.GetHRGN(), RGN_AND); -#endif + SelectClipRgn(GetHdc(), GetHrgnOf(region)); +#else // Win32 + ExtSelectClipRgn(GetHdc(), GetHrgnOf(region), RGN_AND); +#endif // Win16/32 - DO_SET_CLIPPING_BOX() + UpdateClipBox(); } void wxDC::DestroyClippingRegion() @@ -298,6 +304,7 @@ void wxDC::DestroyClippingRegion() SelectClipRgn(GetHdc(), rgn); DeleteObject(rgn); } + m_clipping = FALSE; } diff --git a/src/msw/dcclient.cpp b/src/msw/dcclient.cpp index b2edbb6003..7df1dbfc58 100644 --- a/src/msw/dcclient.cpp +++ b/src/msw/dcclient.cpp @@ -146,12 +146,18 @@ void wxClientDC::InitDC() SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID)); - // clip the DC to avoid overwriting the non client area + // in wxUniv build we must manually do some DC adjustments usually + // performed by Windows for us #ifdef __WXUNIVERSAL__ wxPoint ptOrigin = m_canvas->GetClientAreaOrigin(); - SetDeviceOrigin(ptOrigin.x, ptOrigin.y); - wxSize size = m_canvas->GetClientSize(); - SetClippingRegion(wxPoint(0, 0), size); + if ( ptOrigin.x || ptOrigin.y ) + { + // no need to shift DC origin if shift is null + SetDeviceOrigin(ptOrigin.x, ptOrigin.y); + } + + // clip the DC to avoid overwriting the non client area + SetClippingRegion(wxPoint(0, 0), m_canvas->GetClientSize()); #endif // __WXUNIVERSAL__ } diff --git a/src/msw/ole/oleutils.cpp b/src/msw/ole/oleutils.cpp index 55e74c6c45..1666fb1c78 100644 --- a/src/msw/ole/oleutils.cpp +++ b/src/msw/ole/oleutils.cpp @@ -56,7 +56,7 @@ bool IsIidFromList(REFIID riid, const IID *aIids[], size_t nCount) return FALSE; } -#if wxUSE_DRAG_AND_DROP +#if wxUSE_DRAG_AND_DROP || wxUSE_DATAOBJ // ---------------------------------------------------------------------------- // Debug support diff --git a/src/msw/ole/uuid.cpp b/src/msw/ole/uuid.cpp index 9436536733..4f637bdda5 100644 --- a/src/msw/ole/uuid.cpp +++ b/src/msw/ole/uuid.cpp @@ -26,15 +26,13 @@ #include "wx/setup.h" -#if wxUSE_DRAG_AND_DROP +#if wxUSE_DRAG_AND_DROP || wxUSE_DATAOBJ // standard headers #include // UUID related functions #include "wx/msw/ole/uuid.h" - - // ============================================================================ // Implementation // ============================================================================ diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index db923b2b5c..334349f557 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -32,13 +32,13 @@ #ifndef WX_PRECOMP #include "wx/log.h" - #include "wx/clipbrd.h" - #include "wx/dcclient.h" #include "wx/validate.h" #include "wx/textctrl.h" #endif +#include "wx/clipbrd.h" + #include "wx/caret.h" #include "wx/univ/inphand.h" @@ -878,6 +878,9 @@ wxTextCtrlHitTestResult wxTextCtrl::HitTest(const wxPoint& pos, void wxTextCtrl::ShowHorzPosition(wxCoord pos) { + // pos is the logical position to show + + // m_ofsHorz is the fisrt logical position shown if ( pos < m_ofsHorz ) { // scroll backwards @@ -896,7 +899,8 @@ void wxTextCtrl::ShowHorzPosition(wxCoord pos) width = m_rectText.width; } - if ( pos > width ) + // m_ofsHorz + width is the last logical position shown + if ( pos > m_ofsHorz + width) { // scroll forward long col; @@ -1051,37 +1055,18 @@ void wxTextCtrl::DrawTextLine(wxDC& dc, const wxRect& rect, } } -void wxTextCtrl::DoDraw(wxControlRenderer *renderer) +void wxTextCtrl::DoDrawTextInRect(wxDC& dc, const wxRect& rectUpdate) { - // hide the caret while we're redrawing the window and show it after we are - // done with it - wxCaretSuspend cs(this); - - // prepare the DC - wxDC& dc = renderer->GetDC(); - dc.SetFont(GetFont()); - dc.SetTextForeground(GetForegroundColour()); - - // get the intersection of the update region with the text area: note that - // the update region is in window coord and text area is in the client - // ones, so it must be shifted before computing intesection - wxRegion rgnUpdate = GetUpdateRegion(); - wxRect rectTextArea = m_rectText; - wxPoint pt = GetClientAreaOrigin(); - rectTextArea.x += pt.x; - rectTextArea.y += pt.y; - rgnUpdate.Intersect(rectTextArea); - wxRect rectUpdate = rgnUpdate.GetBox(); - - // FIXME: why is this needed (at least under MSW)? - rectUpdate.Inflate(2, 1); - // debugging trick to see the update rect visually -#if 0 - static int s_count = 0; - dc.SetBrush(*(++s_count % 2 ? wxRED_BRUSH : wxGREEN_BRUSH)); - dc.SetPen(*wxTRANSPARENT_PEN); - dc.DrawRectangle(rectUpdate); +#if 1 + if ( 0 ) + { + wxWindowDC dc(this); + static int s_count = 0; + dc.SetBrush(*(++s_count % 2 ? wxRED_BRUSH : wxGREEN_BRUSH)); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(rectUpdate); + } #endif // calculate the range of lines to refresh @@ -1105,8 +1090,6 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer) rectText.y = m_rectText.y + lineStart*rectText.height; // do draw the invalidated parts of each line - // shouldn't be needed: dc.SetClippingRegion(rectUpdate); - DoPrepareDC(dc); // adjust for scrolling for ( long line = lineStart; line <= lineEnd; line++ ) { // calculate the update rect in text positions for this line @@ -1140,6 +1123,14 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer) rectText.x = m_rectText.x + GetTextWidth(textLine.Left(colStart)); rectText.width = GetTextWidth(text); + // check that the string that we draw fits entirely into the text area, + // we don't want to draw just a part of characters + while ( rectText.GetRight() > m_ofsHorz + m_rectText.width ) + { + rectText.width -= GetTextWidth(text.Last()); + text.RemoveLast(); + } + // do draw the text DrawTextLine(dc, rectText, text, selStart, selEnd); wxLogTrace(_T("text"), _T("Line %ld: positions %ld-%ld redrawn."), @@ -1152,6 +1143,47 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer) } } +void wxTextCtrl::DoDraw(wxControlRenderer *renderer) +{ + // hide the caret while we're redrawing the window and show it after we are + // done with it + wxCaretSuspend cs(this); + + // prepare the DC + wxDC& dc = renderer->GetDC(); + dc.SetFont(GetFont()); + dc.SetTextForeground(GetForegroundColour()); + + // get the intersection of the update region with the text area: note that + // the update region is in window coord and text area is in the client + // ones, so it must be shifted before computing intesection + wxRegion rgnUpdate = GetUpdateRegion(); + wxRect rectTextArea = m_rectText; + wxPoint pt = GetClientAreaOrigin(); + rectTextArea.x += pt.x; + rectTextArea.y += pt.y; + rgnUpdate.Intersect(rectTextArea); + +#if 0 + // even though the drawing is already clipped to the update region, we must + // explicitly clip it to the rect we will use as otherwise parts of letters + // might be drawn outside of it (if even a small part of a charater is + // inside, HitTest() will return its column and DrawText() can't draw only + // the part of the character, of course) + dc.SetClippingRegion(m_rectText); +#endif // 0 + + // adjust for scrolling + DoPrepareDC(dc); + + // and now refresh thei nvalidated parts of the window + wxRegionIterator iter(rgnUpdate); + for ( ; iter.HaveRects(); iter++ ) + { + DoDrawTextInRect(dc, iter.GetRect()); + } +} + wxCoord wxTextCtrl::GetCaretPosition() const { wxString textBeforeCaret(GetLineText(m_curLine), (size_t)m_curRow); diff --git a/src/univ/themes/win32.cpp b/src/univ/themes/win32.cpp index 7df80fc049..2cdf5bbcb4 100644 --- a/src/univ/themes/win32.cpp +++ b/src/univ/themes/win32.cpp @@ -41,6 +41,12 @@ #include "wx/univ/colschem.h" #include "wx/univ/theme.h" +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +static const int BORDER_THICKNESS = 20; + // ---------------------------------------------------------------------------- // wxWin32Renderer: draw the GUI elements in Win32 style // ---------------------------------------------------------------------------- @@ -1068,13 +1074,18 @@ void wxWin32Renderer::DrawBorder(wxDC& dc, int WXUNUSED(flags), wxRect *rectIn) { + int i; + wxRect rect = rectTotal; switch ( border ) { case wxBORDER_SUNKEN: - DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); - DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey); + for ( i = 0; i < BORDER_THICKNESS / 2; i++ ) + { + DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight); + DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey); + } break; case wxBORDER_STATIC: @@ -1082,7 +1093,8 @@ void wxWin32Renderer::DrawBorder(wxDC& dc, break; case wxBORDER_RAISED: - DrawRaisedBorder(dc, &rect); + for ( i = 0; i < BORDER_THICKNESS / 2; i++ ) + DrawRaisedBorder(dc, &rect); break; case wxBORDER_DOUBLE: @@ -1114,7 +1126,7 @@ wxRect wxWin32Renderer::GetBorderDimensions(wxBorder border) const { case wxBORDER_RAISED: case wxBORDER_SUNKEN: - width = 2; + width = BORDER_THICKNESS; break; case wxBORDER_SIMPLE: diff --git a/src/univ/winuniv.cpp b/src/univ/winuniv.cpp index 0a3694037b..ad6bbe73a7 100644 --- a/src/univ/winuniv.cpp +++ b/src/univ/winuniv.cpp @@ -377,7 +377,8 @@ wxPoint wxWindow::GetClientAreaOrigin() const void wxWindow::DoGetClientSize(int *width, int *height) const { - wxWindowNative::DoGetClientSize(width, height); + int w, h; + wxWindowNative::DoGetClientSize(&w, &h); // we assume that the scrollbars are positioned correctly (by a previous // call to PositionScrollbars()) here @@ -386,33 +387,32 @@ void wxWindow::DoGetClientSize(int *width, int *height) const if ( m_renderer ) rectBorder = m_renderer->GetBorderDimensions(GetBorder()); - wxSize size = GetSize(); - bool inside = m_renderer->AreScrollbarsInsideBorder(); if ( width ) { // in any case, take account of the scrollbar if ( m_scrollbarVert ) - *width -= size.x - m_scrollbarVert->GetPosition().x; + w -= m_scrollbarVert->GetSize().x; // if we don't have scrollbar or if it is outside the border (and not // blended into it), take account of the right border as well - if ( !m_scrollbarVert || !inside ) - *width -= rectBorder.width; + if ( !m_scrollbarVert || inside ) + w -= rectBorder.width; - *width -= rectBorder.x; + // and always account for the left border + *width = w - rectBorder.x; } if ( height ) { if ( m_scrollbarHorz ) - *height -= size.y - m_scrollbarHorz->GetPosition().y; + h -= m_scrollbarHorz->GetSize().y; - if ( !m_scrollbarHorz || !inside ) - *height -= rectBorder.height; + if ( !m_scrollbarHorz || inside ) + h -= rectBorder.height; - *height -= rectBorder.y; + *height = h - rectBorder.y; } }