本来是没有这一篇记录的,因为之前猜是肯定用了C++的析构函数做拷贝,因此很多dc看起来只要是对dc画东西,然后出了栈后,内容就自然而然的到了画面上(clientDC上)。今天无意中撞到了wxBufferedDC的代码,索性就这个猜测证实了一下。
wxBufferedDC,一般我们用的时候,会用某个clientDC作为参数传入,这样,其实在内部被m_dc记录下来,
dcbuffer.h中,可以看到如下声明,成员变量m_dc是个指针,记住了进来的dc的地址(一般就是我们传的ClientDC)。另外一个地方就是析构函数,如果m_dc不为空的话,会调用UnMask()方法。
class WXDLLIMPEXP_CORE wxBufferedDC : public wxMemoryDC { public: // Default ctor, must subsequently call Init for two stage construction. wxBufferedDC() : m_dc(NULL), m_buffer(NULL), m_style(0) { } // Construct a wxBufferedDC using a user supplied buffer. wxBufferedDC(wxDC *dc, wxBitmap& buffer = wxNullBitmap, int style = wxBUFFER_CLIENT_AREA) : m_dc(NULL), m_buffer(NULL) { Init(dc, buffer, style); } // Construct a wxBufferedDC with an internal buffer of 'area' // (where area is usually something like the size of the window // being buffered) wxBufferedDC(wxDC *dc, const wxSize& area, int style = wxBUFFER_CLIENT_AREA) : m_dc(NULL), m_buffer(NULL) { Init(dc, area, style); } // The usually desired action in the dtor is to blit the buffer. virtual ~wxBufferedDC() { if ( m_dc ) UnMask(); } // These reimplement the actions of the ctors for two stage creation void Init(wxDC *dc, wxBitmap& buffer = wxNullBitmap, int style = wxBUFFER_CLIENT_AREA) { InitCommon(dc, style); m_buffer = &buffer; UseBuffer(); } void Init(wxDC *dc, const wxSize &area, int style = wxBUFFER_CLIENT_AREA) { InitCommon(dc, style); UseBuffer(area.x, area.y); } // Blits the buffer to the dc, and detaches the dc from the buffer (so it // can be effectively used once only). // // Usually called in the dtor or by the dtor of derived classes if the // BufferedDC must blit before the derived class (which may own the dc it's // blitting to) is destroyed. void UnMask(); // Set and get the style void SetStyle(int style) { m_style = style; } int GetStyle() const { return m_style & ~wxBUFFER_USES_SHARED_BUFFER; } private: // common part of Init()s void InitCommon(wxDC *dc, int style) { wxASSERT_MSG( !m_dc, wxT("wxBufferedDC already initialised") ); m_dc = dc; m_style = style; } // check that the bitmap is valid and use it void UseBuffer(wxCoord w = -1, wxCoord h = -1); // the underlying DC to which we copy everything drawn on this one in // UnMask() // // NB: Without the existence of a wxNullDC, this must be a pointer, else it // could probably be a reference. wxDC *m_dc; // the buffer (selected in this DC), initially invalid wxBitmap *m_buffer; // the buffering style int m_style; wxSize m_area; DECLARE_DYNAMIC_CLASS(wxBufferedDC) wxDECLARE_NO_COPY_CLASS(wxBufferedDC); };
void wxBufferedDC::UnMask() { wxCHECK_RET( m_dc, wxT("no underlying wxDC?") ); wxASSERT_MSG( m_buffer && m_buffer->IsOk(), wxT("invalid backing store") ); wxCoord x = 0, y = 0; // Ensure the scale matches the device SetUserScale(1.0, 1.0); if ( m_style & wxBUFFER_CLIENT_AREA ) GetDeviceOrigin(&x, &y); // It's possible that the buffer may be bigger than the area that needs to // be drawn (the client size of the window is smaller than the bitmap, or // a shared bitmap has been reused for a smaller area, etc.) so avoid // blitting too much if possible, but only use the real DC size if the // wxBUFFER_VIRTUAL_AREA style is not set. int width = m_area.GetWidth(), height = m_area.GetHeight(); if (! m_style & wxBUFFER_VIRTUAL_AREA) { int widthDC, heightDC; m_dc->GetSize(&widthDC, &heightDC); width = wxMin(width, widthDC); height = wxMin(height, heightDC); } m_dc->Blit(0, 0, width, height, this, -x, -y); m_dc = NULL; if ( m_style & wxBUFFER_USES_SHARED_BUFFER ) wxSharedDCBufferManager::ReleaseBuffer(m_buffer); }
1、栈上创建,然后
2、在这个dc中绘图,然后
3、就没有任何跟dc相关的代码
的缘故。