这次说一说wxDC.相信做过windows程序开发的都了解DC的概念.wxDC就是wxWidgets中对应windows中DC的.但是我们看帮助的时候,能发现wxWidgets提供的很多wxDC的子类,比如wxBufferedDC,wxMemoryDC,wxScreenDC,wxClientDC,wxPaintDC,wxWindowDC等等,它们之间到底有些什么差别呢?
在说wxDC之前,先回顾一下windows中MFC的DC一些背景知识.我们在编写MFC程序的时候都知道,对于一个窗口,有三个DC,CClientDC,CWindowDC,CPaintDC.CClientDC是窗口Client区域对应的DC.CWindowDC是对应整个窗口区域的DC,其中包括title bar,menus,scroll bars等,这样可以在窗口的任意位置显示我们需要的背景图象.CWindowDC对于一些特殊场合是非常有用的.而CPaintDC只在WM_PAINT消息中使用.
我们在来看看wxDC,我们可以看到,很多DC相关的windowsAPI都在wxDC的成员函数中有对应.能清楚知道wxDC是我们的基础类,几乎所有的功能应该都是在这里完成的.那为什么还需要这么多的子类呢?我们一个一个来说明它们的用处.
wxClientDC,其实就和windows中的CClientDC是一致的.对应窗口的client区域.一般情况下,我们都应该使用这个来修改我们的窗体显示.
wxPaintDC,wxPaintDC仅限于在wxPaintEvent事件中使用(也就是OnPanit),功能和CPaintDC是一样的.
wxWindowDC,这和CWindowDC是一致的,并且这个只在windows平台可用,象linux中的Xwindow,边框这些东西都是窗口管理器负责,自然是没有这个wxWindowDC的概念了.如果你想全面修饰窗口就需要用到这个.
wxScreenDC,这个就是整个屏幕了,如果你想捕捉屏幕,就可以用到它.还有一个小技巧,你可以通过wxScreenDC获得当前系统的分辨率:-)
上面说到的四个DC:wxClientDC,wxPaintDC,wxWindowDC,wxScreenDC.它们都必须是在栈上分配,实际就是作为局部变量使用,在函数内部临时构造.并且我们不要试图保存它们,用于其他地方.在需要使用的时候临时构造就好了.
wxMemoryDC,通过名字就能了解,是内存DC,实际上对应一个bitmap.可以通过SelectObject选择操作的bitmap.所有针对该DC的操作,实际都是画到bitmap上的.
wxBufferedDC,我们在自己用DC画东西的时候,都会碰到背景闪烁的问题,一般经典的解决方法就是双缓冲技术.就是说我们构建一个中间的DC,先把我们需要的图象都画到这个DC上,最后在整个更新到目标DC上,这样就避免了闪烁的问题.wxBufferedDC,就是完成这样的任务的:-).我们可以看到它有三个构造函数,其中一个是默认构造函数.另外两个如下:
wxBufferedDC(wxDC *dc, const wxSize& area, int style = wxBUFFER_CLIENT_AREA)
wxBufferedDC(wxDC *dc, const wxBitmap& buffer, int style = wxBUFFER_CLIENT_AREA)
可以看到它一定需要一个wxDC做参数.它实现双缓冲技术的秘密就在这里.中间对DC的操作都是和wxDC一致的,因为它需要指定一个wxBitmap做为buffer用,或者是使用一个wxSize指定大小,内部实现应该也是自己建立一个buffer.最后在对象释放的时候,把buffer中的数据一次性更新到目标DC上.当然细心的人能发现,它还有一个默认构造函数,这个是不需要参数的,那这样我们如何能实现双缓冲呢?帮助中明确说明了,如果使用默认构造函数,一定要调用wxBufferedDC::Init才能使用该DC!而其他的构造函数就不需要了.看看Init的原形:
void Init(wxDC *dc, const wxSize& area, int style = wxBUFFER_CLIENT_AREA)
void Init(wxDC *dc, const wxBitmap& buffer, int style = wxBUFFER_CLIENT_AREA)
很清楚,和非默认构造函数一一对应.
wxBufferedPaintDC,实际就是wxBufferedDC的wxPaintEvent版本.使用注意事项和wxPaintDC类似.由于wxPaintDC只针对client区域,所以能看到它的构造函数和wxBufferedDC有些差别,不需要指定wxDC,因为就是针对wxPaintDC的.构造函数如下:
wxBufferedPaintDC(wxWindow *window, const wxBitmap& buffer, int style = wxBUFFER_CLIENT_AREA)
wxBufferedPaintDC(wxWindow *window, int style = wxBUFFER_CLIENT_AREA)
替代wxDC的参数是wxWindow,这个和wxPaintDC是一致的.没有默认构造函数,自然就不需要Init函数了.
其实还有几个wxDC的子类,象wxPrinterDC,wxPostScriptDC,wxMetafileDC.因为没有用过.不清楚细节,无法给有用信息了.
不完全系列声明:
不完全系列并不是完整的说明/分析.每个主题都只是针对性说明,其中自然会遗漏很多.只是希望提供一些有用信息而已.如有笔误,敬请谅解.