Not quite understanding buffered DCs

Robin Dunn wrote:

You can also paint outside of a EVT_PAINT handler by using a
wx.ClientDC[1]. In the example in the book this is what is done in
OnMotion. The new lines are drawn to the buffer and then the buffer
will be flushed to the wx.ClientDC.

And self.buffer preserves the final state of what got written to the screen
so that it can be used again in the event of a paint event to redraw the
screen.

It is all for convenience. That one line in the example replaces about
4 lines it would take to do it without a wx.BufferedPaintDC. In fact,
all of the buffered dc classes are entirely for convenience. You can do
everything they do yourself with just a bitmap, a MemoryDC and a
ClientDC or PaintDC.

Sure, in general it takes all those elements. But in this case, isn't it
true that we don't need the MemoryDC? The image that we want to draw is
already whole in self.bitmap, so we should be able to blit it to the
PaintDC without having to worry about flicker:

dc = wx.PaintDC()
w, h = self.buffer.GetSize()
dc.Blit(0, 0, w, h, self.buffer, 0, 0)

That's still 3 lines compared with 1, so I get the convenience argument.
And I get that in a program where more than one thing is drawn to the
screen in the paint handler then we want the MemoryDC provided by the
buffered DC to minimize flicker. I just want to confirm that in this
particular program the buffered DC is doing something for us that we don't
really need. Also, is it true that the additional overhead associated with
creating the buffered device context (that is, the overhead associated with
creating the MemoryDC) is small? Otherwise, there would be an argument for
spelling out the necessary steps to avoid the unnecessary one.

···

--
Jeffrey Barish

dc = wx.PaintDC()
w, h = self.buffer.GetSize()
dc.Blit(0, 0, w, h, self.buffer, 0, 0)

This code fragment is wrong. I discovered that I could download the source
code for the examples from wxPython in Action, so I ran some
tests. The correct equivalent to the use of a buffered DC (as in the book)
is:

dc = wx.PaintDC(self)
w, h = self.buffer.GetSize()
dc2 = wx.MemoryDC()
dc2.SelectObject(self.buffer)
dc.Blit(0, 0, w, h, dc2, 0, 0)

The Blit method requires a DC as the source, not a bitmap, so it is
necessary to create a MemoryDC. Much easier to use the buffered DC.

···

--
Jeffrey Barish