Search code examples
wxwidgets

Custom stippled pen


I'm trying to draw what amounts to a screen-tone effect over an existing image, but I'd like to leave an area blank. Think of how spotlights in old games are sometimes done, where most of the image is darkened, and but part of it is the "normal" color.
To do this, I need my overlay to be transparent (since the original image has to show through). I'm also drawing this with wxDC.DrawCircle(...) (with a transparent brush), since it allows me to not draw over a circular area.

Problem is, the stipple (screen tone effect) isn't transparent, it's solid. I've tried just about everything I can think of, but nothing seems to work. My current code is roughly like this:

const char* ScreenToneColor[] =
{
    /* columns rows colors chars-per-pixel */
    "3 3 2 1",
    "X c Black",
    "O c None",
    /* pixels */
    "OOO",
    "OXO",
    "OOO"
};

CustomPanel::CustomPanel(wxWindow* parent)
    : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(151, 151))
{
    SetBackgroundStyle(wxBG_STYLE_PAINT);
    // MemberVariables
    m_Stipple = wxBitmap(wxImage(ScreenToneColor));
    m_ScreenTone = wxPen(*wxBLACK, 2 * VeryLargeRadius, wxPENSTYLE_STIPPLE);
    m_ScreenTone.SetStipple(m_Stipple);
}

// Supplied with a wxAutoBufferedDC
void CustomPanel::Render(wxDC&  dc)
{
    dc.SetBrush(*wxGREEN_BRUSH);
    dc.DrawRectangle(m_PanelRectange);
    // "fade out" trimmed areas by drawing a ring.
    dc.SetBrush(*wxTRANSPARENT_BRUSH);
    dc.SetPen(m_ScreenTone);
    dc.DrawCircle(m_AnimatedCenter, VeryLargeRadius + m_VisibleRadius);
}  

I've tried supplying the mask, using the different stipple masks (avoiding wxPENSTYLE_STIPPLE_MASK_OPAQUE), etc. I'm on Windows 10 and compiling against wxWidgets 3.1, although the project is being built/run on other OSs, and possibly a lower library version.


Solution

  • wxDC doesn't support transparency with just the only exception of drawing bitmaps with alpha channel. If you want to do anything involving alpha, you need to use wxGraphicsContext and related classes. I'm not sure if GDI+ or Direct2D implementations of it currently handle this correctly, but after checking the code it seems like at least the former one should.