// 鼠标坐标变换 BOOL CDuiPanel::OnMousePointChange(CPoint& point) { if(m_pDuiPluginObject) { return m_pDuiPluginObject->OnMousePointChange(point); } if(m_bEnableScroll && ((m_nVirtualHeight > m_rc.Height()) || (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; // 当前显示的是虚拟图片中什么位置开始的图片 point.Offset(nVirtualLeft, nVirtualTop); return TRUE; } return FALSE; }
void CDuiGridCtrl::DrawControl(CDC &dc, CRect rcUpdate) { // 列表画图方法: // 1.列表的虚拟高度为每一行高度*行数 // 2.列表显示的top坐标由scroll控件记录 // 3.重画时候,根据top坐标位置计算出显示的第一行的序号,根据显示高度计算出显示的最后一行的序号 // 4.根据计算出的显示的行,画相应的内容到内存dc中 // 5.计算出显示的top坐标进行内存dc的拷贝 int nTotalColumnWidth = GetTotalColumnWidth(); // 总的列宽度 int nViewWidth = m_rc.Width() - m_nScrollWidth; // 减去滚动条的显示区域宽度 CDuiScrollHorizontal* pScrollH = (CDuiScrollHorizontal*)m_pControScrollH; int nCurPosH = pScrollH->GetScrollCurrentPos(); // 当前left位置 int nMaxRangeH = pScrollH->GetScrollMaxRange(); int nContentWidth = (nTotalColumnWidth > nViewWidth) ? nTotalColumnWidth : nViewWidth; // 内容部分的宽度(如果总的列宽小于显示区域宽度,则使用显示区域宽度) m_nVirtualLeft = (nMaxRangeH > 0) ? (int)((double)nCurPosH*(nContentWidth-nViewWidth)/nMaxRangeH) : 0; // 当前滚动条位置对应的虚拟的left位置 int nHeightAll = m_vecRowInfo.size()*m_nRowHeight; // 总的虚拟高度 //m_rc.Height(); CDuiScrollVertical* pScrollV = (CDuiScrollVertical*)m_pControScrollV; int nCurPosV = pScrollV->GetScrollCurrentPos(); // 当前top位置 int nMaxRangeV = pScrollV->GetScrollMaxRange(); m_nVirtualTop = (nMaxRangeV > 0) ? (int)((double)nCurPosV*(nHeightAll-m_rc.Height())/nMaxRangeV) : 0; // 当前滚动条位置对应的虚拟的top位置 if(m_nVirtualTop < 0) { m_nVirtualTop = 0; pScrollV->SetScrollCurrentPos(0); } m_nFirstViewRow = m_nVirtualTop / m_nRowHeight; // 显示的第一行序号 m_nLastViewRow = (m_nVirtualTop + m_rc.Height() - m_nHeaderHeight) / m_nRowHeight; // 显示的最后一行序号 if(m_nLastViewRow >= (int)m_vecRowInfo.size()) { m_nLastViewRow = m_vecRowInfo.size() - 1; } if(m_nLastViewRow < 0) { m_nLastViewRow = 0; } int nHeightView = (m_nLastViewRow - m_nFirstViewRow +1) * m_nRowHeight; // 显示涉及到的虚拟高度 int nYViewPos = m_nVirtualTop - (m_nFirstViewRow * m_nRowHeight); // 内存dc显示到屏幕时候的top位置 if(nYViewPos < 0) { nYViewPos = 0; } if(!m_bUpdate) { UpdateMemDC(dc, nTotalColumnWidth, nHeightView); Graphics graphics(m_memDC); m_memDC.BitBlt(m_nVirtualLeft, 0, nViewWidth, nHeightView, &dc, m_rc.left, m_rc.top, WHITENESS); // 画白色背景 DrawVerticalTransition(m_memDC, dc, CRect(m_nVirtualLeft, nYViewPos, nViewWidth+m_nVirtualLeft, m_rc.Height()+nYViewPos-m_nHeaderHeight), // 背景透明度 m_rc, m_nBkTransparent, m_nBkTransparent); BSTR bsFontTitle = m_strFontTitle.AllocSysString(); FontFamily fontFamilyTitle(bsFontTitle); Font fontTitle(&fontFamilyTitle, (REAL)m_nFontTitleWidth, m_fontTitleStyle, UnitPixel); ::SysFreeString(bsFontTitle); BSTR bsFont = m_strFont.AllocSysString(); FontFamily fontFamily(bsFont); Font font(&fontFamily, (REAL)m_nFontWidth, m_fontStyle, UnitPixel); ::SysFreeString(bsFont); SolidBrush solidBrush(m_clrText); // 正常文字画刷 SolidBrush solidBrushH(m_clrTextHover); // 热点文字画刷 SolidBrush solidBrushD(m_clrTextDown); // 当前行画刷 SolidBrush solidBrushT(m_clrTitle); // 标题文字画刷 SolidBrush solidBrushS(m_clrSeperator); // 分割线画刷 graphics.SetTextRenderingHint( TextRenderingHintClearTypeGridFit ); // 设置普通文字的水平和垂直对齐方式 DUI_STRING_ALIGN_DEFINE(); strFormat.SetTrimming(StringTrimmingEllipsisWord); // 以单词为单位去尾,略去部分使用省略号 //strFormat.SetFormatFlags( StringFormatFlagsNoClip | StringFormatFlagsMeasureTrailingSpaces); if(!m_bTextWrap) { strFormat.SetFormatFlags(StringFormatFlagsNoWrap | StringFormatFlagsMeasureTrailingSpaces); // 不换行 } // 标题字段采用中间对齐 StringFormat strFormatHeader; strFormatHeader.SetAlignment(StringAlignmentCenter); // 中间对齐 strFormatHeader.SetLineAlignment(StringAlignmentCenter); // 中间对齐 if(!m_bTextWrap) { strFormatHeader.SetFormatFlags(StringFormatFlagsNoWrap | StringFormatFlagsMeasureTrailingSpaces); // 不换行 } // 画标题行 if((m_nHeaderHeight > 0) && (m_vecColumnInfo.size() > 0)) { // 画单元格内容 int nPosItemX = 0; for(size_t j = 0; j < m_vecColumnInfo.size(); j++) { GridColumnInfo &columnInfo = m_vecColumnInfo.at(j); int nWidth = columnInfo.nWidth; if(j == 0) { nWidth += m_nLeftPos; } RectF rect((Gdiplus::REAL)nPosItemX, 0, (Gdiplus::REAL)nWidth, (Gdiplus::REAL)(m_nHeaderHeight-1)); // 画列标题 CString strTitle = columnInfo.strTitle; BSTR bsTitle = strTitle.AllocSysString(); graphics.DrawString(bsTitle, (INT)wcslen(bsTitle), &font, rect, &strFormatHeader, &solidBrushT); ::SysFreeString(bsTitle); nPosItemX += nWidth; } } if(m_vecRowInfo.size() > 0) { for(int i = m_nFirstViewRow; i <= m_nLastViewRow && i < (int)m_vecRowInfo.size(); i++) { GridRowInfo &rowInfo = m_vecRowInfo.at(i); SolidBrush solidBrushRow(rowInfo.clrText); // 行定义的颜色 int nXPos = 0; int nVI = i - m_nFirstViewRow; // 鼠标移动到行时候显示的背景颜色(如果设置为全0,则不显示行背景颜色) if((m_nHoverRow == i) && (m_clrRowHover.GetValue() != Color(0, 0, 0, 0).GetValue())) { SolidBrush brush(m_clrRowHover); graphics.FillRectangle(&brush, 0, m_nHeaderHeight + nVI*m_nRowHeight, nContentWidth, m_nRowHeight); } // 画检查框 int nCheckImgY = 3; if((m_sizeCheckBox.cy*2 > m_nRowHeight) || (m_uVAlignment == VAlign_Middle)) { nCheckImgY = (m_nRowHeight - m_sizeCheckBox.cy) / 2 + 1; } if((rowInfo.nCheck != -1) && (m_pImageCheckBox != NULL)) { int nCheckImageIndex = ((m_nHoverRow == i) ? ((rowInfo.nCheck==1) ? 4 : 1) : ((rowInfo.nCheck==1) ? 2 : 0)); graphics.DrawImage(m_pImageCheckBox, Rect(nXPos, m_nHeaderHeight + nVI*m_nRowHeight + nCheckImgY, m_sizeCheckBox.cx, m_sizeCheckBox.cy), nCheckImageIndex * m_sizeCheckBox.cx, 0, m_sizeCheckBox.cx, m_sizeCheckBox.cy, UnitPixel); rowInfo.rcCheck.SetRect(nXPos, i*m_nRowHeight + nCheckImgY, nXPos + m_sizeCheckBox.cx, i*m_nRowHeight + nCheckImgY + m_sizeCheckBox.cy); nXPos += (m_sizeCheckBox.cx + 3); } // 画行左边图片 int nImgY = 3; if(rowInfo.pImage != NULL) { if((rowInfo.sizeImage.cy*2 > m_nRowHeight) || (m_uVAlignment == VAlign_Middle)) { nImgY = (m_nRowHeight - rowInfo.sizeImage.cy) / 2 + 1; } // 使用行数据指定的图片 graphics.DrawImage(rowInfo.pImage, Rect(nXPos, m_nHeaderHeight + nVI*m_nRowHeight + nImgY, rowInfo.sizeImage.cx, rowInfo.sizeImage.cy), 0, 0, rowInfo.sizeImage.cx, rowInfo.sizeImage.cy, UnitPixel); nXPos += (rowInfo.sizeImage.cx + 3); }else if((rowInfo.nImageIndex != -1) && (m_pImage != NULL)) { if((m_sizeImage.cy*2 > m_nRowHeight) || (m_uVAlignment == VAlign_Middle)) { nImgY = (m_nRowHeight - m_sizeImage.cy) / 2 + 1; } // 使用索引图片 graphics.DrawImage(m_pImage, Rect(nXPos, m_nHeaderHeight + nVI*m_nRowHeight + nImgY, m_sizeImage.cx, m_sizeImage.cy), rowInfo.nImageIndex*m_sizeImage.cx, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel); nXPos += (m_sizeImage.cx + 3); } // 画行右边图片 int nRightImageWidth = 0; nImgY = 3; if(rowInfo.pRightImage != NULL) { if((rowInfo.sizeRightImage.cy*2 > m_nRowHeight) || (m_uVAlignment == VAlign_Middle)) { nImgY = (m_nRowHeight - rowInfo.sizeRightImage.cy) / 2 + 1; } // 使用行数据指定的图片 graphics.DrawImage(rowInfo.pRightImage, Rect(nContentWidth-rowInfo.sizeRightImage.cx-1, m_nHeaderHeight + nVI*m_nRowHeight + nImgY, rowInfo.sizeRightImage.cx, rowInfo.sizeRightImage.cy), 0, 0, rowInfo.sizeRightImage.cx, rowInfo.sizeRightImage.cy, UnitPixel); nRightImageWidth = rowInfo.sizeRightImage.cx + 1; }else if((rowInfo.nRightImageIndex != -1) && (m_pImage != NULL)) { if((m_sizeImage.cy*2 > m_nRowHeight) || (m_uVAlignment == VAlign_Middle)) { nImgY = (m_nRowHeight - m_sizeImage.cy) / 2 + 1; } // 使用索引图片 graphics.DrawImage(m_pImage, Rect(nContentWidth-m_sizeImage.cx-1, m_nHeaderHeight + nVI*m_nRowHeight + nImgY, m_sizeImage.cx, m_sizeImage.cy), rowInfo.nRightImageIndex*m_sizeImage.cx, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel); nRightImageWidth = m_sizeImage.cx + 1; } // 画单元格内容 int nPosItemX = (m_nLeftPos != 0) ? m_nLeftPos : nXPos; for(size_t j = 0; j < rowInfo.vecItemInfo.size(); j++) { GridColumnInfo &columnInfo = m_vecColumnInfo.at(j); GridItemInfo &itemInfo = rowInfo.vecItemInfo.at(j); BOOL bSingleLine = (itemInfo.strContent.IsEmpty() || !itemInfo.strLink.IsEmpty()); RectF rect((Gdiplus::REAL)nPosItemX, (Gdiplus::REAL)(m_nHeaderHeight + nVI*m_nRowHeight + 1), (Gdiplus::REAL)((j == 0) ? (itemInfo.rcItem.Width() - nPosItemX): itemInfo.rcItem.Width()), (Gdiplus::REAL)(bSingleLine ? (m_nRowHeight - 2) : (m_nRowHeight / 2 - 2))); if((int)(rect.GetRight()) > nContentWidth) { // 最后一列需要减去滚动条宽度 rect.Width -= m_nScrollWidth; } // 画单元格图片 int nItemImageX = 0; int nImgY = 3; if(itemInfo.pImage != NULL) { if((itemInfo.sizeImage.cy*2 > m_nRowHeight) || (m_uVAlignment == VAlign_Middle)) { nImgY = (m_nRowHeight - rowInfo.sizeImage.cy) / 2 + 1; } // 使用单元格指定的图片 graphics.DrawImage(itemInfo.pImage, Rect(nPosItemX+nItemImageX, m_nHeaderHeight + nVI*m_nRowHeight + nImgY, itemInfo.sizeImage.cx, itemInfo.sizeImage.cy), 0, 0, itemInfo.sizeImage.cx, itemInfo.sizeImage.cy, UnitPixel); nItemImageX += (itemInfo.sizeImage.cx + 3); }else if((itemInfo.nImageIndex != -1) && (m_pImage != NULL)) { if((m_sizeImage.cy*2 > m_nRowHeight) || (m_uVAlignment == VAlign_Middle)) { nImgY = (m_nRowHeight - m_sizeImage.cy) / 2 + 1; } // 使用索引图片 graphics.DrawImage(m_pImage, Rect(nPosItemX+nItemImageX, m_nHeaderHeight + nVI*m_nRowHeight + nImgY, m_sizeImage.cx, m_sizeImage.cy), itemInfo.nImageIndex*m_sizeImage.cx, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel); nItemImageX += (m_sizeImage.cx + 3); } rect.Offset((Gdiplus::REAL)nItemImageX, 0); rect.Width -= (Gdiplus::REAL)nItemImageX; // 画单元格标题或链接内容 SolidBrush solidBrushItem(m_clrText); if((m_nHoverRow == i) && (m_clrTextHover.GetValue() != Color(0, 0, 0, 0).GetValue())) // 设置了鼠标移动颜色,则使用 { solidBrushItem.SetColor(m_clrTextHover); }else if((m_nDownRow == i) && (m_clrTextDown.GetValue() != Color(0, 0, 0, 0).GetValue())) // 设置了鼠标按下颜色,则使用 { solidBrushItem.SetColor(m_clrTextDown); }else if(itemInfo.clrText.GetValue() != Color(0, 0, 0, 0).GetValue()) // 设置了单元格颜色,则使用 { solidBrushItem.SetColor(itemInfo.clrText); }else if(rowInfo.bRowColor) // 设置了行颜色,则使用 { solidBrushItem.SetColor(rowInfo.clrText); } CString strItemTitle = itemInfo.strTitle; // 计算是否需要显示tip itemInfo.bNeedTitleTip = rect.Width < GetTextBounds(font, strItemTitle).Width; itemInfo.bNeedContentTip = rect.Width < GetTextBounds(font, itemInfo.strContent).Width; if(!itemInfo.strLink.IsEmpty()) { strItemTitle = itemInfo.strLink; if((m_nHoverRow == i) && (rowInfo.nHoverItem == j)) { solidBrushItem.SetColor(m_clrTextHover); }else { solidBrushItem.SetColor((itemInfo.clrText.GetValue() != Color(0, 0, 0, 0).GetValue()) ? itemInfo.clrText : m_clrText); } } // 设置单元格文字对齐方式,使用列的对齐方式 StringFormat strFormatColumn; UINT uAlignment = m_uAlignment; if(columnInfo.uAlignment != 0xFFFFUL) { uAlignment = columnInfo.uAlignment; } if(uAlignment == Align_Left) { strFormatColumn.SetAlignment(StringAlignmentNear); }else if(uAlignment == Align_Center) { strFormatColumn.SetAlignment(StringAlignmentCenter); }else if(uAlignment == Align_Right) { strFormatColumn.SetAlignment(StringAlignmentFar); } UINT uVAlignment = m_uVAlignment; if(columnInfo.uVAlignment != 0xFFFFUL) { uVAlignment = columnInfo.uVAlignment; } if(uVAlignment == VAlign_Top) { strFormatColumn.SetLineAlignment(StringAlignmentNear); }else if(uVAlignment == VAlign_Middle) { strFormatColumn.SetLineAlignment(StringAlignmentCenter); }else if(uVAlignment == VAlign_Bottom) { strFormatColumn.SetLineAlignment(StringAlignmentFar); } if(!m_bTextWrap) { strFormatColumn.SetFormatFlags(StringFormatFlagsNoWrap | StringFormatFlagsMeasureTrailingSpaces); // 不换行 } // 根据bUseTitleFont决定用标题字体还是普通字体 BSTR bsItemTitle = strItemTitle.AllocSysString(); graphics.DrawString(bsItemTitle, (INT)wcslen(bsItemTitle), itemInfo.bUseTitleFont ? &fontTitle : &font, rect, &strFormatColumn, itemInfo.bUseTitleFont ? &solidBrushT : &solidBrushItem); ::SysFreeString(bsItemTitle); // 画单元格内容 if(!bSingleLine) { rect.Offset(0, (Gdiplus::REAL)m_nRowHeight / 2 + 2); rect.Height = (Gdiplus::REAL)m_nRowHeight / 2 - 4; BSTR bsItemContent = itemInfo.strContent.AllocSysString(); graphics.DrawString(bsItemContent, (INT)wcslen(bsItemContent), &font, rect, &strFormatColumn, &solidBrushItem); ::SysFreeString(bsItemContent); } // 设置单元格子控件的位置 for(size_t k = 0; k < itemInfo.vecControl.size(); k++) { CControlBase* pControl = itemInfo.vecControl.at(k); if(pControl) { CRect rcParent = CRect(nPosItemX, m_nHeaderHeight + nVI*m_nRowHeight + 1, (int)(rect.X+rect.Width), (nVI+1)*m_nRowHeight - 1); if((int)(rect.GetRight()) > nContentWidth) { // 最后一列需要减去滚动条宽度 rcParent.right -= m_nScrollWidth; } rcParent.OffsetRect(m_rc.left - m_nVirtualLeft, m_rc.top - (nYViewPos + m_nHeaderHeight)); pControl->SetPositionWithParent(rcParent); CRect rcControl = pControl->GetRect(); // 只有当前在显示范围内的控件设置为可见 if( (rcControl.top < m_rc.top) || (rcControl.bottom > m_rc.bottom) || (rcControl.left < m_rc.left) || (rcControl.right > m_rc.right) ) { pControl->SetVisible(FALSE); }else { pControl->SetVisible(TRUE); } } } if(j == 0) { // 为了使第二列开始是对齐的,所以第二列开始位置按照第一列的宽度计算 nPosItemX = itemInfo.rcItem.right; }else { nPosItemX += itemInfo.rcItem.Width(); } } // 画分隔线(采用拉伸模式) if(m_pImageSeperator != NULL) { // 使用拉伸模式画图 graphics.DrawImage(m_pImageSeperator, RectF(0, (Gdiplus::REAL)(m_nHeaderHeight + (nVI+1)*m_nRowHeight), (Gdiplus::REAL)(nContentWidth-2), (Gdiplus::REAL)m_sizeSeperator.cy), 0, 0, (Gdiplus::REAL)m_sizeSeperator.cx, (Gdiplus::REAL)m_sizeSeperator.cy, UnitPixel); }else if(m_clrSeperator.GetValue() != Color(0, 0, 0, 0).GetValue()) { // 未指定图片,并且分隔线显色不是全0,则画矩形 graphics.FillRectangle(&solidBrushS, 0, m_nHeaderHeight + (nVI+1)*m_nRowHeight, nContentWidth-2, 1); } } // 把不在显示范围内的单元格的控件都设置为不可见 for(int i = 0; i < (int)m_vecRowInfo.size(); i++) { if((i < m_nFirstViewRow) || (i > m_nLastViewRow)) { GridRowInfo &rowInfo = m_vecRowInfo.at(i); for(size_t j = 0; j < rowInfo.vecItemInfo.size(); j++) { GridItemInfo &itemInfo = rowInfo.vecItemInfo.at(j); for(size_t k = 0; k < itemInfo.vecControl.size(); k++) { CControlBase* pControl = itemInfo.vecControl.at(k); if(pControl) { pControl->SetVisible(FALSE); } } } } } } } // 输出到界面DC,使用与的方式合并背景 // 标题行输出 if(m_nHeaderHeight > 0) { dc.BitBlt(m_rc.left,m_rc.top, nViewWidth, m_nHeaderHeight, &m_memDC, m_nVirtualLeft, 0, SRCCOPY);//SRCAND); } // 内容部分输出 int nContentHeight = m_rc.Height() - m_nHeaderHeight; if(nTotalColumnWidth > m_rc.Width()) { nContentHeight -= m_nScrollWidth; } dc.BitBlt(m_rc.left,m_rc.top + m_nHeaderHeight, nViewWidth, nContentHeight, &m_memDC, m_nVirtualLeft, nYViewPos + m_nHeaderHeight, SRCCOPY);//SRCAND); }
void CDuiText::DrawControl(CDC &dc, CRect rcUpdate) { int nWidth = m_rc.Width(); int nHeight = m_rc.Height(); // 计算显示位置 CDuiScrollVertical* pScrollV = (CDuiScrollVertical*)m_pControScrollV; int nCurPos = pScrollV->GetScrollCurrentPos(); // 当前top位置 int nMaxRange = pScrollV->GetScrollMaxRange(); int nVirtualTop = 0; // 当前显示的是虚拟图片中什么位置开始的图片 m_nVirtualHeight = GetVirtualHeight(); if(m_nVirtualHeight > m_rc.Height()) { nVirtualTop = (nMaxRange > 0) ? nCurPos*(m_nVirtualHeight-m_rc.Height())/nMaxRange : 0; }else { nVirtualTop = 0; } if(!m_bUpdate) { UpdateMemDC(dc, nWidth, m_nVirtualHeight); Graphics graphics(m_memDC); if(m_bBack) { SolidBrush brush(m_clrBack); graphics.FillRectangle(&brush, 0, 0, nWidth, nHeight); } else { //m_memDC.BitBlt(0, 0, nWidth, nHeight, &dc, m_rc.left ,m_rc.top, SRCCOPY); m_memDC.BitBlt(0, 0, nWidth, nHeight, &dc, m_rc.left ,m_rc.top, WHITENESS); // 画白色背景 DrawVerticalTransition(m_memDC, dc, CRect(0, 0+nVirtualTop, nWidth, nHeight+nVirtualTop), // 背景透明度 m_rc, m_nBkTransparent, m_nBkTransparent); } 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( StringFormatFlagsNoWrap | StringFormatFlagsMeasureTrailingSpaces); strFormat.SetFormatFlags( StringFormatFlagsNoClip | StringFormatFlagsMeasureTrailingSpaces); //strFormat.SetTrimming(StringTrimmingEllipsisWord); // 以单词为单位去尾,略去部分使用省略号 int nXPos = 0; if(m_pImage != NULL) { graphics.DrawImage(m_pImage, Rect(0, (nHeight - m_sizeImage.cy) / 2, m_sizeImage.cx, m_sizeImage.cy), 0, 0, m_sizeImage.cx, m_sizeImage.cy, UnitPixel); nXPos += m_sizeImage.cx + 5; } Size size = GetTextBounds(font, strFormat, nWidth, m_strTitle); int nStart = m_strTitle.Find(m_strMark, m_nStart); if(m_strMark.IsEmpty() || (nStart == -1)) { int nTextWidth = nWidth - nXPos; if(m_bScrollV) { nTextWidth -= m_nScrollWidth; } // 先画阴影 if(m_bEnableShadow) { RectF rectShadow((Gdiplus::REAL)(nXPos + 1), (Gdiplus::REAL)1, (Gdiplus::REAL)nTextWidth, (Gdiplus::REAL)max(size.Height, nHeight)); SolidBrush solidBrushS(m_clrTextShadow); BSTR bsTitle = m_strTitle.AllocSysString(); graphics.DrawString(bsTitle, (INT)wcslen(bsTitle), &font, rectShadow, &strFormat, &solidBrushS); ::SysFreeString(bsTitle); } // 再画正常的文字 RectF rect((Gdiplus::REAL)(nXPos), (Gdiplus::REAL)0, (Gdiplus::REAL)nTextWidth, (Gdiplus::REAL)(max(size.Height, nHeight))); if((m_enButtonState == enBSHover) && m_bEnableHover) { SolidBrush solidBrushH(m_clrTextHover); BSTR bsTitle = m_strTitle.AllocSysString(); graphics.DrawString(bsTitle, (INT)wcslen(bsTitle), &font, rect, &strFormat, &solidBrushH); ::SysFreeString(bsTitle); }else { BSTR bsTitle = m_strTitle.AllocSysString(); graphics.DrawString(bsTitle, (INT)wcslen(bsTitle), &font, rect, &strFormat, &solidBrush); ::SysFreeString(bsTitle); } } else { SolidBrush solidBrushM(m_clrMark); SolidBrush solidBrushS(m_clrTextShadow); CString srtL = m_strTitle.Left(nStart); CString srtR = m_strTitle.Right(m_strTitle.GetLength() - m_strMark.GetLength() - nStart); Size sizeL = GetTextBounds(font, strFormat, srtL); Size sizeM = GetTextBounds(font, strFormat, m_strMark); Size sizeR = GetTextBounds(font, strFormat, srtR); if(m_bEnableShadow) { BSTR bsL = srtL.AllocSysString(); graphics.DrawString(bsL, (INT)wcslen(bsL), &font, PointF((Gdiplus::REAL)(nXPos + 1), (Gdiplus::REAL)1), &strFormat, &solidBrushS); ::SysFreeString(bsL); BSTR bsMark = m_strMark.AllocSysString(); graphics.DrawString(bsMark, (INT)wcslen(bsMark), &font, PointF((Gdiplus::REAL)(nXPos + sizeL.Width + 2 + 1), (Gdiplus::REAL)1), &strFormat, &solidBrushS); ::SysFreeString(bsMark); } BSTR bsL = srtL.AllocSysString(); graphics.DrawString(bsL, (INT)wcslen(bsL), &font, PointF((Gdiplus::REAL)(nXPos), (Gdiplus::REAL)0), &strFormat, &solidBrush); ::SysFreeString(bsL); BSTR bsMark = m_strMark.AllocSysString(); graphics.DrawString(bsMark, (INT)wcslen(bsMark), &font, PointF((Gdiplus::REAL)(nXPos + sizeL.Width + 2), (Gdiplus::REAL)0), &strFormat, &solidBrushM); ::SysFreeString(bsMark); if(m_bEnableShadow) { RectF rect((Gdiplus::REAL)(nXPos + sizeL.Width + sizeM.Width + 4 + 1), (Gdiplus::REAL)(1), (Gdiplus::REAL)(nWidth - (nXPos + sizeL.Width + sizeM.Width + 4)), (Gdiplus::REAL)nHeight); BSTR bsR = srtR.AllocSysString(); graphics.DrawString(bsR, (INT)wcslen(bsR), &font, PointF((Gdiplus::REAL)(nXPos + sizeL.Width + sizeM.Width + 4), (Gdiplus::REAL)0), &strFormat, &solidBrushS); ::SysFreeString(bsR); } //RectF rect(nXPos + point.x + sizeL.Width + sizeM.Width + 4, point.y, nWidth - (nXPos + sizeL.Width + sizeM.Width + 4 + point.x), size.Height); RectF rect((Gdiplus::REAL)(nXPos + sizeL.Width + sizeM.Width + 4), (Gdiplus::REAL)0, (Gdiplus::REAL)(nWidth - (nXPos + sizeL.Width + sizeM.Width + 4)), (Gdiplus::REAL)nHeight); BSTR bsR = srtR.AllocSysString(); graphics.DrawString(bsR, (INT)wcslen(bsR), &font, PointF((Gdiplus::REAL)(nXPos + sizeL.Width + sizeM.Width + 4), (Gdiplus::REAL)0), &strFormat, &solidBrush); ::SysFreeString(bsR); } } dc.BitBlt(m_rc.left,m_rc.top, m_rc.Width(), m_rc.Height(), &m_memDC, 0, nVirtualTop, SRCCOPY); }
// 控件界面刷新 LRESULT CDuiPanel::OnControlUpdate(CRect rcUpdate, BOOL bUpdate, CControlBase *pUpdateControlBase) { if(pUpdateControlBase == NULL) return 0; if(bUpdate) { pUpdateControlBase->SetUpdate(FALSE); } int nVirtualTop = 0; if(m_nVirtualHeight > m_rc.Height()) { // 计算显示位置 CDuiScrollVertical* pScrollV = (CDuiScrollVertical*)m_pControScrollV; int nCurPos = pScrollV->GetScrollCurrentPos(); // 当前top位置 int nMaxRange = pScrollV->GetScrollMaxRange(); nVirtualTop = (nMaxRange > 0) ? nCurPos*(m_nVirtualHeight-m_rc.Height())/nMaxRange : 0; // 当前显示的是虚拟图片中什么位置开始的图片 } int nVirtualLeft = 0; if(m_nVirtualWidth > m_rc.Width()) { // 计算显示位置 CDuiScrollHorizontal* pScrollH = (CDuiScrollHorizontal*)m_pControScrollH; int nCurPosH = pScrollH->GetScrollCurrentPos(); // 当前top位置 int nMaxRangeH = pScrollH->GetScrollMaxRange(); nVirtualLeft = (nMaxRangeH > 0) ? nCurPosH*(m_nVirtualLeft-m_rc.Width())/nMaxRangeH : 0; // 当前显示的是虚拟图片中什么位置开始的图片 } CRect rcAllUpDate = rcUpdate; if(m_bInit) { BOOL bFind = false; for (size_t i = 0; i < m_vecControl.size(); i++) { CControlBase * pControlBase = m_vecControl.at(i); if (pControlBase) { if(bFind) { if (pControlBase->GetVisible() && !(pControlBase->GetRect() & rcUpdate).IsRectEmpty()) { rcAllUpDate |= pControlBase->GetRect(); pControlBase->SetUpdate(FALSE); } } else if(pControlBase == pUpdateControlBase) { bFind = true; } } } } // 按照滚动位置修改更新区域 rcAllUpDate.OffsetRect(-nVirtualLeft, -nVirtualTop); rcAllUpDate |= m_rc; InvalidateRect(&rcAllUpDate); return 0L; };
// 画子控件(支持滚动显示) 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; }