WxHtmlWindow
From WxWiki
No user comments, see official documentation: wxHtmlWindow
Contents |
[edit] Problems with background image
There seems to be a problem with rendering the background image while scrolling down a wxHtmlWindow object.
[edit] Without patching: creating a derived class
Here is a solution how to get it working without patching the original wxHtmlWindow class:
#ifndef WXHTMLWINDOWMY_H #define WXHTMLWINDOWMY_H #include "wx/wxhtml.h" #include "wx/dcclient.h" #include "wx/dcmemory.h" class wxHtmlWindowMy : public wxHtmlWindow { public: wxHtmlWindowMy(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxHW_DEFAULT_STYLE, const wxString& name = wxT("htmlWindow")) : wxHtmlWindow(parent, id, pos, size, style, name) { m_backBuffer = NULL; } ~wxHtmlWindowMy() {} void SetBackgroundImage(const wxBitmap& bmp) {m_bmpBg = bmp;} protected: wxBitmap m_bmpBg; bool m_eraseBgInOnPaint; wxBitmap *m_backBuffer; void OnEraseBackground(wxEraseEvent& event); void OnPaint(wxPaintEvent& event); void OnSize(wxSizeEvent& event); DECLARE_EVENT_TABLE() }; #endif
#include "htmlwinmy.h" BEGIN_EVENT_TABLE(wxHtmlWindowMy, wxHtmlWindow) EVT_ERASE_BACKGROUND(wxHtmlWindowMy::OnEraseBackground) EVT_PAINT(wxHtmlWindowMy::OnPaint) EVT_SIZE(wxHtmlWindowMy::OnSize) END_EVENT_TABLE() void wxHtmlWindowMy::OnEraseBackground(wxEraseEvent& event) { if ( !m_bmpBg.Ok() ) { // don't even skip the event, if we don't have a bg bitmap we're going // to overwrite background in OnPaint() below anyhow, so letting the // default handling take place would only result in flicker, just set a // flag to erase the background below m_eraseBgInOnPaint = true; return; } wxDC& dc = *event.GetDC(); // if the image is not fully opaque, we have to erase the background before // drawing it, however avoid doing it for opaque images as this would just // result in extra flicker without any other effect as background is // completely covered anyhow if ( m_bmpBg.GetMask() ) { dc.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID)); dc.Clear(); } dc.DrawBitmap(m_bmpBg, 0, 0, true /* use mask */); } void wxHtmlWindowMy::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(this); if (/*m_tmpCanDrawLocks > 0 || */m_Cell == NULL) return; int x, y; GetViewStart(&x, &y); wxRect rect = GetUpdateRegion().GetBox(); wxSize sz = GetSize(); wxMemoryDC dcm; if ( !m_backBuffer ) m_backBuffer = new wxBitmap(sz.x, sz.y); dcm.SelectObject(*m_backBuffer); if ( m_eraseBgInOnPaint ) { dcm.SetBackground(wxBrush(GetBackgroundColour(), wxSOLID)); dcm.Clear(); m_eraseBgInOnPaint = false; } else // someone has already erased the background, keep it { // preserve the existing background, otherwise we'd erase anything the // user code had drawn in its EVT_ERASE_BACKGROUND handler when we do // the Blit back below dcm.Blit(0, rect.GetTop(), sz.x, rect.GetBottom() - rect.GetTop() + 1, &dc, 0, rect.GetTop()); dcm.DrawBitmap(m_bmpBg, 0, -(y * wxHTML_SCROLL_STEP), true /* use mask */); } PrepareDC(dcm); dcm.SetMapMode(wxMM_TEXT); dcm.SetBackgroundMode(wxTRANSPARENT); wxHtmlRenderingInfo rinfo; wxDefaultHtmlRenderingStyle rstyle; rinfo.SetSelection(m_selection); rinfo.SetStyle(&rstyle); m_Cell->Draw(dcm, 0, 0, y * wxHTML_SCROLL_STEP + rect.GetTop(), y * wxHTML_SCROLL_STEP + rect.GetBottom(), rinfo); //#define DEBUG_HTML_SELECTION #ifdef DEBUG_HTML_SELECTION { int xc, yc, x, y; wxGetMousePosition(&xc, &yc); ScreenToClient(&xc, &yc); CalcUnscrolledPosition(xc, yc, &x, &y); wxHtmlCell *at = m_Cell->FindCellByPos(x, y); wxHtmlCell *before = m_Cell->FindCellByPos(x, y, wxHTML_FIND_NEAREST_BEFORE); wxHtmlCell *after = m_Cell->FindCellByPos(x, y, wxHTML_FIND_NEAREST_AFTER); dcm.SetBrush(*wxTRANSPARENT_BRUSH); dcm.SetPen(*wxBLACK_PEN); if (at) dcm.DrawRectangle(at->GetAbsPos(), wxSize(at->GetWidth(),at->GetHeight())); dcm.SetPen(*wxGREEN_PEN); if (before) dcm.DrawRectangle(before->GetAbsPos().x+1, before->GetAbsPos().y+1, before->GetWidth()-2,before->GetHeight()-2); dcm.SetPen(*wxRED_PEN); if (after) dcm.DrawRectangle(after->GetAbsPos().x+2, after->GetAbsPos().y+2, after->GetWidth()-4,after->GetHeight()-4); } #endif dcm.SetDeviceOrigin(0,0); dc.Blit(0, rect.GetTop(), sz.x, rect.GetBottom() - rect.GetTop() + 1, &dcm, 0, rect.GetTop()); } void wxHtmlWindowMy::OnSize(wxSizeEvent& event) { wxDELETE(m_backBuffer); wxHtmlWindow::OnSize(event); }
wxHtmlWindowMy* ctrl = new wxHtmlWindowMy(parent); ctrl->SetBackgroundImage(wxBitmap("images/grass.png"));
[edit] Patching: modifying the original wxHtmlWindow class
There is only 1 line added to the original wxHtmlWindow::OnPaint() method. If you want to patch the original source code, you just need to add the line:
dcm.DrawBitmap(m_bmpBg, 0, -(y * wxHTML_SCROLL_STEP), true /* use mask */);
to src/html/htmlwin.cpp file into the method OnPaint() after the line:
if ( m_eraseBgInOnPaint ) { ... } else { dcm.Blit(0, rect.GetTop(), sz.x, rect.GetBottom() - rect.GetTop() + 1, &dc, 0, rect.GetTop()); /* put the line here: */ dcm.DrawBitmap(m_bmpBg, 0, -(y * wxHTML_SCROLL_STEP), true /* use mask */); /* ------------------ */ }
Don't forget to recompile your wxWidgets.
If you have any questions, please send me an email: michal.fapso@gmail.com
[edit] Footnote: Bug in SetPage
The patch above works fine except if you use the SetPage method. In the current implementation (as of version 2.8.8) the SetPage method will replace any background bitmap that was previously set with a null bitmap. Bug #9833 has been raised (see http://trac.wxwidgets.org/ticket/9833) and it contains a patch.
