void CDuiSlider::DrawControl(CDC &dc, CRect rcUpdate) { int nWidth = m_rc.Width(); int nHeight = m_rc.Height(); if(!m_bUpdate) { UpdateMemDC(dc, nWidth, nHeight * 4); Graphics graphics(m_memDC); // 画4个状态的内存图片 for(int i = 0; i < 4; i++) { // 复制背景 m_memDC.BitBlt(0, i * nHeight, nWidth, nHeight, &dc, m_rc.left ,m_rc.top, SRCCOPY); int nPosY = i * nHeight; if(m_pImageForeGround != NULL) // 使用背景和前景图片画进度条 { if(m_pImageBackGround != NULL) // 画背景 { DrawImageFrameMID(graphics, m_pImageBackGround, CRect(0, nPosY + m_nThumbTop, nWidth, nPosY + m_nThumbTop + m_nSliderHeight), 0, 0, m_sizeBackGround.cx, m_sizeBackGround.cy, m_nHeadLength, 0, m_nHeadLength, 0); } if(m_nProgress != 0) // 画前景 { DrawImageFrameMID(graphics, m_pImageForeGround, CRect(0, nPosY + m_nThumbTop, nWidth * m_nProgress / m_nMaxProgress, nPosY + m_nThumbTop + m_nSliderHeight), 0, 0, m_sizeForeGround.cx, m_sizeForeGround.cy, m_nHeadLength, 0, m_nHeadLength, 0); } }else if(m_pImage != NULL) // 使用单张图片画进度条 { DrawImageFrame(graphics, m_pImage, CRect(0, nPosY + m_nThumbTop, nWidth, nPosY + m_nThumbTop + m_nSliderHeight), 0, 0, m_sizeImage.cx, m_sizeImage.cy, 2); if(m_nProgress != 0) { DrawImageFrame(graphics, m_pImage, CRect(0, nPosY + m_nThumbTop, nWidth * m_nProgress / m_nMaxProgress, nPosY + m_nThumbTop + m_nSliderHeight), m_sizeImage.cx, 0, m_sizeImage.cx, m_sizeImage.cy, 2); } } // 画滑块 if(m_pImageThumb != NULL) { // 计算滑块的位置 int nPos = (int)__max(m_rc.Width() * m_nProgress / m_nMaxProgress - m_nThumbWidth / 2, 0); nPos = (int)__min(nPos, m_rc.Width() - m_nThumbWidth); Rect rect(nPos, nPosY, m_nThumbWidth, m_nThumbHeight); graphics.DrawImage(m_pImageThumb, rect, i * m_sizeThumb.cx, 0, m_sizeThumb.cx, m_sizeThumb.cy, UnitPixel); } // 画进度文字 if(m_bShowText) { BSTR bsFont = m_strFont.AllocSysString(); FontFamily fontFamily(bsFont); Font font(&fontFamily, (REAL)m_nFontWidth, m_fontStyle, UnitPixel); ::SysFreeString(bsFont); SolidBrush solidBrush(m_clrText); graphics.SetTextRenderingHint( TextRenderingHintClearTypeGridFit ); // 设置水平和垂直对齐方式 DUI_STRING_ALIGN_DEFINE(); strFormat.SetFormatFlags( StringFormatFlagsNoClip | StringFormatFlagsMeasureTrailingSpaces); CString strText; // 只有最大值设置为100情况下才会显示百分号 strText.Format(_T("%s%d%s"), m_strTitle, m_nProgress, (m_nMaxProgress == 100) ? _T("%") : _T("")); BSTR bsTitle = strText.AllocSysString(); RectF rect((Gdiplus::REAL)(0), (Gdiplus::REAL)nPosY, (Gdiplus::REAL)nWidth, (Gdiplus::REAL)nHeight); graphics.DrawString(bsTitle, (INT)wcslen(bsTitle), &font, rect, &strFormat, &solidBrush); ::SysFreeString(bsTitle); } } } dc.BitBlt(m_rc.left,m_rc.top, m_rc.Width(), m_rc.Height(), &m_memDC, 0, m_enButtonState * nHeight, SRCCOPY); }
void CWndShadow::Update(HWND hParent) { //int ShadSize = 5; //int Multi = 100 / ShadSize; RECT WndRect; GetWindowRect(hParent, &WndRect); int nShadWndWid = 0; int nShadWndHei = 0; if(m_pShadowImage != NULL) { // 九宫格方式,计算阴影窗口总的宽度和高度 nShadWndWid = WndRect.right - WndRect.left + m_nShadowWLT + m_nShadowWRB; nShadWndHei = WndRect.bottom - WndRect.top + m_nShadowHLT + m_nShadowHRB; }else { // 算法阴影方式,计算阴影窗口总的宽度和高度 nShadWndWid = WndRect.right - WndRect.left + m_nSize * 2; nShadWndHei = WndRect.bottom - WndRect.top + m_nSize * 2; } // Create the alpha blending bitmap BITMAPINFO bmi; // bitmap header ZeroMemory(&bmi, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = nShadWndWid; bmi.bmiHeader.biHeight = nShadWndHei; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; // four 8-bit components bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biSizeImage = nShadWndWid * nShadWndHei * 4; BYTE *pvBits; // pointer to DIB section HBITMAP hbitmap = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&pvBits, NULL, 0); HDC hMemDC = CreateCompatibleDC(NULL); HBITMAP hOriBmp = (HBITMAP)SelectObject(hMemDC, hbitmap); if(m_pShadowImage != NULL) { // 九宫格方式画阴影图片 Graphics graphics(hMemDC); CRect rcTemp(0, 0, nShadWndWid, nShadWndHei); DrawImageFrameMID(graphics, m_pShadowImage, rcTemp, 0, 0, m_pShadowImage->GetWidth(), m_pShadowImage->GetHeight(), m_nShadowWLT, m_nShadowHLT, m_nShadowWRB+1, m_nShadowHRB+1); }else { // 画算法阴影 ZeroMemory(pvBits, bmi.bmiHeader.biSizeImage); MakeShadow((UINT32 *)pvBits, hParent, &WndRect); } // 计算阴影窗口偏移位置 POINT ptDst; if(m_pShadowImage != NULL) { ptDst.x = WndRect.left - m_nShadowWLT; ptDst.y = WndRect.top - m_nShadowHLT; } else { ptDst.x = WndRect.left + m_nxOffset - m_nSize; ptDst.y = WndRect.top + m_nyOffset - m_nSize; } POINT ptSrc = {0, 0}; SIZE WndSize = {nShadWndWid, nShadWndHei}; BLENDFUNCTION blendPixelFunction= { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; MoveWindow(m_hWnd, ptDst.x, ptDst.y, nShadWndWid, nShadWndHei, FALSE); BOOL bRet= s_UpdateLayeredWindow(m_hWnd, NULL, &ptDst, &WndSize, hMemDC, &ptSrc, 0, &blendPixelFunction, ULW_ALPHA); _ASSERT(bRet); // something was wrong.... // Delete used resources SelectObject(hMemDC, hOriBmp); DeleteObject(hbitmap); DeleteDC(hMemDC); }
// 画控件 void CDuiTabCtrl::DrawControl(CDC &dc, CRect rcUpdate) { int nWidth = m_rc.Width(); //int nHeight = m_rc.Height(); // 纵向内存DC的高度是整个tabctrl的高度,不只是页签部分高度 int nTabHeight = m_nTabCtrlHeight; // 纵向内存DC高度改为tabctrl部分高度 if(!m_bUpdate) { // 创建内存DC,纵向分为6层: // 1.tab页签图片-原图 // 2.tab页签图片-鼠标热点 // 3.tab页签图片-鼠标按下 // 4,5,6层是上面3层的备份 UpdateMemDC(dc, nWidth, nTabHeight * 3 * 2); Graphics graphics(m_memDC); BSTR bsFont = m_strFont.AllocSysString(); FontFamily fontFamily(bsFont); Font font(&fontFamily, (REAL)m_nFontWidth, m_fontStyle, UnitPixel); ::SysFreeString(bsFont); //SolidBrush solidBrush(m_clrText); // 正常文字画刷 graphics.SetTextRenderingHint( TextRenderingHintClearTypeGridFit ); // 设置tab页签文字的水平和垂直对齐方式 DUI_STRING_ALIGN_DEFINE(); strFormat.SetFormatFlags( StringFormatFlagsNoWrap | StringFormatFlagsMeasureTrailingSpaces); // 画内存DC的3个层的内容 for(int i = 0; i < 3; i++) { // 将背景内容拷贝到内存DC m_memDC.BitBlt(0, i * nTabHeight, nWidth, nTabHeight, &dc, m_rc.left, m_rc.top, SRCCOPY); // 画tab页签 int nXPos = m_nTabLeftPading; int nYPos = i * nTabHeight; for(size_t j = 0; j < m_vecItemInfo.size(); j++) { TabItemInfo &itemInfo = m_vecItemInfo.at(j); if(!itemInfo.bVisible) { continue; } // 图片位置(根据对齐方式进行计算) CPoint point = GetOriginPoint(m_nTabItemWidth, m_nTabCtrlHeight, itemInfo.sizeImage.cx, itemInfo.sizeImage.cy, GetGDIAlignment(m_uAlignment), GetGDIVAlignment(m_uVAlignment)); // 如果有图片和文字,则图片的垂直对齐按照上对齐方式 if(!itemInfo.strText.IsEmpty()) { point.y = 0; } // 画tab页签底图 if(itemInfo.pImage != NULL) // 如果页签设置了图片,则使用tab页签指定的图片 { int nImageIndex = i; if(itemInfo.nImageCount == 1) { nImageIndex = 0; } graphics.DrawImage(itemInfo.pImage, Rect(nXPos + point.x, nYPos + point.y, itemInfo.sizeImage.cx, itemInfo.sizeImage.cy), itemInfo.sizeImage.cx * nImageIndex, 0, itemInfo.sizeImage.cx, itemInfo.sizeImage.cy, UnitPixel); }else if((m_pImage != NULL) && (itemInfo.nImageIndex != -1)) // 如果设置了页签图片索引,使用tabctrl图片的索引图片 { if(m_enTabImageMode == enTIMNormal) // 普通模式 { graphics.DrawImage(m_pImage, Rect(nXPos + point.x, nYPos + point.y, itemInfo.sizeImage.cx, itemInfo.sizeImage.cy), itemInfo.sizeImage.cx * itemInfo.nImageIndex, 0, itemInfo.sizeImage.cx, itemInfo.sizeImage.cy, UnitPixel); }else if(m_enTabImageMode == enTIMMID) // 九宫格模式 { CRect rcTemp(nXPos, nYPos, nXPos+m_nTabItemWidth, nYPos+m_nTabCtrlHeight); DrawImageFrameMID(graphics, m_pImage, rcTemp, m_sizeImage.cx * i, 0, m_sizeImage.cx, m_sizeImage.cy, m_nWLT, m_nHLT, m_nWRB, m_nHRB); } } // 画tab页签热点图(如果存在tabctrl设置的热点图的话) if((m_pImageHover != NULL) && (i > 0)) { int nX = (itemInfo.rc.Width() - m_sizeHover.cx) / 2; if(nX < 0) { nX = 0; } graphics.DrawImage(m_pImageHover, Rect(nXPos + nX, nYPos, m_sizeHover.cx, m_sizeHover.cy), m_sizeHover.cx * (i-1), 0, m_sizeHover.cx, m_sizeHover.cy, UnitPixel); } // 画tab页签文字 if(!itemInfo.strText.IsEmpty()) { // 设置页签文字颜色 SolidBrush solidBrushItem(m_clrText); if((m_nHoverItem == j) && (m_clrTextHover.GetValue() != Color(0, 0, 0, 0).GetValue())) // 设置了鼠标移动颜色,则使用 { solidBrushItem.SetColor(m_clrTextHover); }else if((m_nDownItem == j) && (m_clrTextDown.GetValue() != Color(0, 0, 0, 0).GetValue())) // 设置了鼠标按下颜色,则使用 { solidBrushItem.SetColor(m_clrTextDown); } RectF rectText((Gdiplus::REAL)nXPos, (Gdiplus::REAL)(nYPos + itemInfo.sizeImage.cy + 1), (Gdiplus::REAL)((m_pImageTabBtn != NULL) ? (itemInfo.rc.Width()-m_sizeTabBtn.cx) : itemInfo.rc.Width()), (Gdiplus::REAL)(m_nTabCtrlHeight - itemInfo.sizeImage.cy - 1)); if(m_nTabCtrlHeight <= itemInfo.sizeImage.cy) { // 如果tabctrl高度小于图片高度,则文字直接居中显示 rectText.Y = (Gdiplus::REAL)nYPos; rectText.Height = (Gdiplus::REAL)m_nTabCtrlHeight; } // 计算是否需要显示tip itemInfo.bNeedTextTip = rectText.Width < GetTextBounds(font, itemInfo.strText).Width; BSTR bsText = itemInfo.strText.AllocSysString(); graphics.DrawString(bsText, (INT)wcslen(bsText), &font, rectText, &strFormat, &solidBrushItem); ::SysFreeString(bsText); } nXPos += itemInfo.rc.Width(); // 画tab页签之间的分隔图片(采用拉伸方式) if(j < m_vecItemInfo.size() - 1 && m_pImageSeperator != NULL) { CRect &rc = m_vecRcSeperator.at(j); int nSepHeight = itemInfo.rc.Height(); // m_sizeSeperator.cy graphics.DrawImage(m_pImageSeperator, Rect(nXPos, nYPos, m_sizeSeperator.cx, nSepHeight), 0, 0, m_sizeSeperator.cx, m_sizeSeperator.cy, UnitPixel); nXPos += m_sizeSeperator.cx; } } } // 内存dc复制一份进行备份 m_memDC.BitBlt(0, nTabHeight * 3, nWidth, nTabHeight * 3, &m_memDC, 0, 0, SRCCOPY); } // 画Tab页签按钮到内存dc if(m_pImageTabBtn != NULL) { // 现将备份的内存dc整体进行恢复,避免页签按钮叠加之后的影响 m_memDC.BitBlt(0, 0, nWidth, nTabHeight * 3, &m_memDC, 0, nTabHeight * 3, SRCCOPY); Graphics graphics(m_memDC); for(int i = 0; i < 3; i++) { for(size_t j = 0; j < m_vecItemInfo.size(); j++) { TabItemInfo &itemInfo = m_vecItemInfo.at(j); graphics.DrawImage(m_pImageTabBtn, RectF((Gdiplus::REAL)itemInfo.rcButton.left, (Gdiplus::REAL)(nTabHeight * i + itemInfo.rcButton.top), (Gdiplus::REAL)itemInfo.rcButton.Width(), (Gdiplus::REAL)itemInfo.rcButton.Height()), (Gdiplus::REAL)(itemInfo.buttonState * m_sizeTabBtn.cx), 0, (Gdiplus::REAL)m_sizeTabBtn.cx, (Gdiplus::REAL)m_sizeTabBtn.cy, UnitPixel); } } } // 内存dc输出到dc // 1.画原图 dc.BitBlt(m_rc.left,m_rc.top, nWidth, nTabHeight, &m_memDC, 0, 0, SRCCOPY); // 2.画鼠标热点的Tab页签 if((m_nHoverItem != -1) && (m_nHoverItem < (int)m_vecItemInfo.size())) { TabItemInfo &itemInfo = m_vecItemInfo.at(m_nHoverItem); dc.BitBlt(itemInfo.rc.left, itemInfo.rc.top, itemInfo.rc.Width(), itemInfo.rc.Height(), &m_memDC, itemInfo.rc.left - m_rc.left, itemInfo.rc.top - m_rc.top + nTabHeight, SRCCOPY); } // 3.画鼠标按下的Tab页签 if((m_nDownItem != -1) && (m_nDownItem < (int)m_vecItemInfo.size())) { TabItemInfo &itemInfo = m_vecItemInfo.at(m_nDownItem); dc.BitBlt(itemInfo.rc.left, itemInfo.rc.top, itemInfo.rc.Width(), itemInfo.rc.Height(), &m_memDC, itemInfo.rc.left - m_rc.left, itemInfo.rc.top - m_rc.top + nTabHeight * 2, SRCCOPY); } }
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(); }