// 画子控件 BOOL CControlBase::DrawSubControls(CDC &dc, CRect rcUpdate) { for (size_t i = 0; i < m_vecControl.size(); i++) { CControlBase * pControlBase = m_vecControl.at(i); if (pControlBase && pControlBase->GetVisible()) { pControlBase->Draw(dc, rcUpdate); } } return TRUE; }
void CControlBase::Draw(CDC &dc, CRect rcUpdate) { if(m_bIsVisible && !(m_rc & rcUpdate).IsRectEmpty()) { DrawControl(dc, rcUpdate); // 画子区域 for (size_t i = 0; i < m_vecArea.size(); i++) { CControlBase * pControlBase = m_vecArea.at(i); if (pControlBase) { pControlBase->Draw(dc, rcUpdate); } } // 画子控件 DrawSubControls(dc, rcUpdate); } }
void CDlgPopup::DrawWindow(CDC *pDC) { if(!m_bInitFinish) return; CRect rcClient; GetClientRect(&rcClient); CDC MemDC; MemDC.CreateCompatibleDC(pDC); CBitmap memBit; //memBit.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); // 因为直接使用CreateCompatibleBitmap在16位颜色下会有问题,因此改为调用DuiCreateCompatibleBitmap函数 HBITMAP hMemBitmap = DuiCreateCompatibleBitmap(rcClient); memBit.Attach(hMemBitmap); CBitmap *pOldBit = MemDC.SelectObject(&memBit); MemDC.SetBkMode(TRANSPARENT); if(m_pImage) { Graphics graphics(MemDC); if(m_enBackMode == enBMFrame) // 边框模式 { DrawImageFrame(graphics, m_pImage, rcClient, 0, 0, m_sizeBKImage.cx, m_sizeBKImage.cy, m_nFrameSize); }else if(m_enBackMode == enBMMID) // 九宫格边框模式 { DrawImageFrameMID(graphics, m_pImage, rcClient, 0, 0, m_sizeBKImage.cx, m_sizeBKImage.cy, m_nFrameWLT, m_nFrameHLT, m_nFrameWRB, m_nFrameHRB); }else // 图片模式 { graphics.DrawImage(m_pImage, Rect(0, 0, m_sizeBKImage.cx, m_sizeBKImage.cy), 0, 0, m_sizeBKImage.cx, m_sizeBKImage.cy, UnitPixel); } } else { MemDC.FillSolidRect(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), RGB(0, 147, 209)); MemDC.FillSolidRect(rcClient.left + 1, rcClient.top + 1, rcClient.Width() - 2, rcClient.Height() - 2, RGB(255, 255, 255)); } DrawWindow(MemDC, rcClient); DrawWindowEx(MemDC, rcClient); for (size_t i = 0; i < m_vecArea.size(); i++) { CControlBase * pControlBase = m_vecArea.at(i); if (pControlBase) { pControlBase->Draw(MemDC, rcClient); } } for (size_t i = 0; i < m_vecControl.size(); i++) { CControlBase * pControlBase = m_vecControl.at(i); if (pControlBase) { pControlBase->Draw(MemDC, rcClient); } } ClientToScreen(&rcClient); POINT pointDes; pointDes.x = rcClient.left; pointDes.y = rcClient.top; POINT pointSrc; pointSrc.x = 0; pointSrc.y = 0; SIZE sizeDes; sizeDes.cx = rcClient.Width(); sizeDes.cy = rcClient.Height(); BLENDFUNCTION blend; memset( &blend, 0, sizeof( blend) ); blend.AlphaFormat = AC_SRC_ALPHA ; blend.SourceConstantAlpha = m_nBackTranslucent; HWND hWnd = GetSafeHwnd(); SetWindowLong(hWnd,GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); // 如果允许背景Alpha通道,则根据是否有背景图片决定是否使用Aplha通道 DWORD dwFlags = 0; if(m_bBackAlpha) { dwFlags = (m_pImage ? ULW_ALPHA : ULW_COLORKEY); } UpdateLayeredWindow(pDC, &pointDes, &sizeDes, &MemDC, &pointSrc, 0, &blend, dwFlags); MemDC.SelectObject(pOldBit); memBit.DeleteObject(); MemDC.DeleteDC(); }
// 画子控件(支持滚动显示) BOOL CDuiPanel::DrawSubControls(CDC &dc, CRect rcUpdate) { // 如果不需要滚动条,则直接使用父控件的画图方法 if(!m_bEnableScroll || ((m_nVirtualHeight <= m_rc.Height()) && (m_nVirtualWidth <= m_rc.Width()))) { return __super::DrawSubControls(dc, rcUpdate); } BOOL bShowScrollV = m_nVirtualHeight > m_rc.Height(); BOOL bShowScrollH = m_nVirtualWidth > m_rc.Width(); // 计算显示位置 CDuiScrollVertical* pScrollV = (CDuiScrollVertical*)m_pControScrollV; int nCurPosV = pScrollV->GetScrollCurrentPos(); // 当前top位置 int nMaxRangeV = pScrollV->GetScrollMaxRange(); int nVirtualTop = (nMaxRangeV > 0) ? nCurPosV*(m_nVirtualHeight-m_rc.Height())/nMaxRangeV : 0; // 当前显示的是虚拟图片中什么位置开始的图片 CDuiScrollHorizontal* pScrollH = (CDuiScrollHorizontal*)m_pControScrollH; int nCurPosH = pScrollH->GetScrollCurrentPos(); // 当前top位置 int nMaxRangeH = pScrollH->GetScrollMaxRange(); int nVirtualLeft = (nMaxRangeH > 0) ? nCurPosH*(m_nVirtualWidth-m_rc.Width())/nMaxRangeH : 0; // 当前显示的是虚拟图片中什么位置开始的图片 // 根据滚动条位置画子控件 // 初始化虚拟显示dc,并复制背景到虚拟显示dc CBitmap virtualBitmap; CDC virtualDC; virtualDC.CreateCompatibleDC(&dc); virtualBitmap.CreateCompatibleBitmap(&dc, bShowScrollH ? (m_rc.left + m_nVirtualWidth) : (m_rc.right - (bShowScrollV ? m_nScrollWidth : 0)), bShowScrollV ? (m_rc.top + m_nVirtualHeight) : (m_rc.bottom - (bShowScrollH ? m_nScrollWidth : 0)) ); CBitmap* pOldVirtualBitmap = virtualDC.SelectObject(&virtualBitmap); virtualDC.BitBlt(m_rc.left+nVirtualLeft, m_rc.top+nVirtualTop, m_rc.Width()-(bShowScrollV ? m_nScrollWidth : 0), m_rc.Height()-(bShowScrollH ? m_nScrollWidth : 0), &dc, m_rc.left, m_rc.top, SRCCOPY); // 背景复制到虚拟显示dc // 更新区域按照显示区域调整 rcUpdate.OffsetRect(nVirtualLeft, nVirtualTop); // 画子控件到虚拟dc for (size_t i = 0; i < m_vecControl.size(); i++) { CControlBase * pControlBase = m_vecControl.at(i); if (pControlBase && pControlBase->GetVisible() && (pControlBase != m_pControScrollV) && (pControlBase != m_pControScrollH)) { // 如果顶部位置发生了变化,需要重画所有子控件,但会造成速度很慢 if(m_nVirtualTop != nVirtualTop) { pControlBase->UpdateControl(true); } pControlBase->Draw(virtualDC, rcUpdate); } } // 画滚动条,滚动条整个区域都需要更新 m_pControScrollV->Draw(dc, m_pControScrollV->GetRect()); m_pControScrollH->Draw(dc, m_pControScrollH->GetRect()); m_nVirtualTop = nVirtualTop; m_nVirtualLeft = nVirtualLeft; // 虚拟显示dc复制到dc(滚动条部分不用复制) dc.BitBlt(m_rc.left, m_rc.top, m_rc.Width()-(bShowScrollV ? m_nScrollWidth : 0), m_rc.Height()-(bShowScrollH ? m_nScrollWidth : 0), &virtualDC, m_rc.left + nVirtualLeft, m_rc.top + nVirtualTop, SRCCOPY); // 释放虚拟显示dc virtualDC.SelectObject(pOldVirtualBitmap); virtualDC.DeleteDC(); virtualBitmap.DeleteObject(); return TRUE; }