Device Context lifetime and typical usage. Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
HankB
In need of some credit
In need of some credit
Posts: 1
Joined: Tue Jun 30, 2020 9:03 pm

Device Context lifetime and typical usage.

Post by HankB » Tue Jun 30, 2020 10:02 pm

I looked for a "noob questions" section and not finding one, this seemed like the best place to ask this.

I've hacked the .../samples/drawing/drawing.cpp example and removed everything that seems not required to draw a circle. I have modified the onMuoseDown() code to draw a circle at the location of the mouse down (in the onMouseDown() procedure) That works as long as don't drag the mouse while down. If I drag the mouse while down, I get the popup message produced by wxLogMessage() and any circles I've added vanish. The original circle drawn during initialization remains. I'm guessing that I'm using the DC improperly in the OnMouseDown() procedure.
I tried moving the code to draw the circle in the OnPaint() callback and calling Refresh() in the OnMouseDown() procedure. The result is that the circle appears under the mouse pointer but any previously drawn circles vanish. This includes the circle drawn during startup. Dragging the mouse while down produces the popup but does not erase the most recent circle (which is all that is visible.) I think this is closer to correct usage of a device context.
I'm curious about typical usage of a DC for painting to the screen in an interactive program. Would the code normally create and save the DC, using it to paint anything initiated by the user until the program exits? Or is there something I'm doing wrong with the DC that causes the behavior I see?

Here is some of my code:

Code: Select all

void MyCanvas::DrawCircles(wxDC &dc, int x, int y, int r)
{
    dc.SetPen(*wxRED_PEN);
    dc.SetBrush(*wxGREEN_BRUSH);
    dc.DrawCircle(x, y, r);
}

Code: Select all

void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
{
    if (m_useBuffer)
    {
        wxBufferedPaintDC bpdc(this);
        DrawCircles(bpdc, m_currentpoint.x, m_currentpoint.y, 5);

    }
    else
    {
        wxPaintDC pdc(this);
        DrawCircles(pdc, m_currentpoint.x, m_currentpoint.y, 5);
    }
}

Code: Select all

void MyCanvas::OnMouseDown(wxMouseEvent &event)
{
    int x, y, xx, yy;
    event.GetPosition(&x, &y);
    CalcUnscrolledPosition(x, y, &xx, &yy);
    m_anchorpoint = wxPoint(xx, yy);
    m_currentpoint = m_anchorpoint;
    m_mouseCaptured = true;
    CaptureMouse();

    Refresh();
}
Since this is sample code that ships with wxWidgets

Code: Select all

// Copyright:   (c) Robert Roebling
// Licence:     wxWindows licence
I'm intending to go in this direction to produce a program that displays Conway's Game of Life. For that usage I would suppose that the (for each generation) code would create a DC, draw the circles to represent live cells and then delete the context. Erasing the display each time the context was recreated and displayed would be a benefit.

Thanks for any pointers on this.

User avatar
doublemax
Moderator
Moderator
Posts: 14881
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Device Context lifetime and typical usage.

Post by doublemax » Tue Jun 30, 2020 10:08 pm

Unless you use a special wxDC to render into a wxBitmap (wxMemoryDC), nothing you draw is stored anywhere. In a paint event handler you need to draw everything you want to display. In your case you'd add the mouse coordinates to a list of points, and then in the paint event handler you iterate over the list and draw a circle at each point.

As this would become slower as the list grows, another option would be to render into a wxBitmap (see above). And then in the paint event handler, you just draw the bitmap.
Use the source, Luke!

Post Reply