这一夜我们只说CreateCompatibleDC

来源:互联网 发布:oauth独立域名 编辑:程序博客网 时间:2024/04/30 03:05

需要在Windows Mobile和Symbian OS上搭一个抽象层来对GDI有个基本的封装.定义了一个Graphics的类.原意是让他每次画图的时候在memory DC上画,最后update的时候可以整体把Memory DC bitblt到目标HDC上去.

下面就是一个简要的initGraphis的函数.粗粗的看好像平平无奇.

[cpp] view plaincopy
  1. SBool Graphics::initGraphics(HWND hwnd, const Rect& rc)  
  2. {  
  3.     if (!hwnd) return SFalse;  
  4.       
  5.     m_rc = rc;  
  6.     m_pWnd = hwnd;  
  7.     m_pDevice = GetDC(m_pWnd);  
  8.       
  9.     if (!m_pDevice) return SFalse;  
  10.     m_pMemory = CreateCompatibleDC(m_pDevice);  
  11.       
  12.     if (!m_pMemory) return SFalse;  
  13.       
  14.     // attention here, the first parameter of CreateCompatibleBitmap need to be device dc but not compatible dc   
  15.     m_pMemBmp = CreateCompatibleBitmap(m_pMemory, rc.dx, rc.dy);  
  16.     if (!m_pMemBmp) return SFalse;  
  17.     m_pOldBmp = (HBITMAP)SelectObject(m_pMemory,(void*)m_pMemBmp);   
  18.     if (!m_pOldBmp) return SFalse;  
  19.       
  20.     HBRUSH hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  21.     RECT r;  
  22.     r.left = m_rc.x;  
  23.     r.top = m_rc.y;  
  24.     r.right = m_rc.x + m_rc.dx;  
  25.     r.bottom = m_rc.y + m_rc.dy;  
  26.     FillRect(m_pMemory, &r, hBrush);  
  27.     return STrue;  
  28. }  

就是创建了memory dc, 设置了bitmap object. 有了这个东西之后,后面的一切画图的操作,我们都已m_pMemory为DC来话,在update函数的时候,我们就吧m_pMemory渲染到m_pDevice上面去.

下面是一个画矩形的函数和Update函数.

[cpp] view plaincopy
  1. void Graphics::fillRect (SInt32 x, SInt32 y, SInt32 dx, SInt32 dy, Color clr )  
  2. {  
  3.     HBRUSH hBrush, HBrushOld;     
  4.     hBrush = ::CreateSolidBrush(clr);  
  5.     HBrushOld = (HBRUSH)SelectObject(m_pMemory, hBrush);  
  6.       
  7.     RECT rc = {x, y, x+dx, y+dy};  
  8.     ::FillRect(m_pMemory, &rc, hBrush);  
  9.     SelectObject(m_pMemory, HBrushOld);  
  10.     DeleteObject(hBrush);  
  11. }  
  12. void Graphics::update()  
  13. {  
  14.     ::BitBlt(m_pDevice, m_rc.x, m_rc.y, m_rc.dx, m_rc.dy, m_pMemory, m_rc.x, m_rc.y, SRCCOPY);  
  15. }  

一起都挺和谐的,也以为肯定可以工作了.但是问题来了.在外部调用了g.drawRect(rc, RGB_GREEN);的时候.矩形是看到了.但是并没有看到绿色的矩形.只是一个黑色的矩形!!!!不像是我们的RGB_GREEN宏定义的有问题,因为实际上调用的就是系统的RGB宏来做的.那到底是什么问题呢?那个SolidBrush无效? 但是无效如何能画呢? 现在的问题只是颜色不对啊!?

终于在MSDN上找到的了原因.和自己想的果然很有差距:

A memory DC exists only in memory. When the memory DC is created, its display surface is exactly one monochrome pixel wide and one monochrome pixel high. Before an application can use a memory DC for drawing operations, it must select a bitmap of the correct width and height into the DC. To select a bitmap into a DC, use the CreateCompatibleBitmap function, specifying the height, width, and color organization required.

然后在CreateCompatibleBitmap里面说到了:

Note: When a memory device context is created, it initially has a 1-by-1 monochrome bitmap selected into it. If this memory device context is used in CreateCompatibleBitmap, the bitmap that is created is a monochromebitmap. To create a color bitmap, use the hDC that was used to create the memory device context, as shown in the following code:

[cpp] view plaincopy
  1. HDC memDC = CreateCompatibleDC ( hDC );  
  2. HBITMAP memBM = CreateCompatibleBitmap ( hDC, nWidth, nHeight );  
  3. SelectObject ( memDC, memBM );  

看到了这些才知道自己太弱了.原来CreateCompatibleDC的时候创建的memory DC只是黑白的.那怎么让他和系统的DC一致呢?只要创建一个和系统DC compatible的bitmap,然后设给这个Memory DC就行了.原来我的那段代码之所以不工作.我创建的bitmap的时候用了

m_pMemBmp = CreateCompatibleBitmap(m_pMemory, rc.dx, rc.dy);这样就变成了创建了一个黑白的bitmap.当然画上去的一些带颜色的东西都变成黑白的啦!

原创粉丝点击