// 绘制的顺序,先坐标,再曲线、擦除多余的曲线、坐标值、标记、参数值 void CFFTDisp::DrawCurve() { int i,j; CSize szText; int x; int y; CFont* pOldFont; CString strMsg; CPen *pOldPen; double dErr = 0; // 与背景对齐 int nSigPicWidth = m_nClientWidth - FFT_LEFT_MARGIN * 2; int nSigPicHeight = m_nClientHeight - FFT_TOP_MARGIN * 2; int nSigPicSmallWidth = nSigPicWidth / FFT_NUM_HORZ; int nSigPicSmallHeight = nSigPicHeight / FFT_NUM_VERT; // 对齐后的宽度和高度 int nPicWidth = nSigPicSmallWidth * FFT_NUM_HORZ; int nPicHeight = nSigPicSmallHeight * FFT_NUM_VERT; if ( m_dcPlot.GetSafeHdc() != NULL ) { // 清除原来的图像 m_dcPlot.SetBkColor (m_crBackColor) ; m_dcPlot.FillRect(m_rectPlot, &m_brushBack) ; // 标题 /////////////////////////////////////////////////////////////////////////// pOldFont = m_dcPlot.SelectObject( &m_fntTitle ); m_dcPlot.SetTextColor( m_crImageColor ); m_dcPlot.TextOut( 2, 2, m_strTitle ); if ( pOldFont != NULL ) { m_dcPlot.SelectObject( pOldFont ); } /////////////////////////////////////////////////////////////////////////// /* // 计算Ain dErr = 0; CAdcTestPlatView* pView = (CAdcTestPlatView*)GetParent(); if ( pView != NULL && pView->m_dVpp > 0 ) { // Ain(峰峰值最大为2V) dErr = 20*log10( pView->m_dVpp / 2); } */ // 计算Ain dErr = 0; // if ( m_dVpp > 0 ) // { // dErr = 20*log10( m_dVpp / 2); // } // 显示曲线、坐标 ///////////////////////////////////////////////////////////////////////// // 画笔 CPen penCh1Signal( PS_SOLID, 1, m_crImageColor ); pOldPen = m_dcPlot.SelectObject( &penCh1Signal ); // 先进行修正(原来更新点数为m_dwDot,所以出现只更新前面数据,后面数据不更新的情况) // m_dwDot -> MAX_DEPTH for ( i = 0; i < MAX_DEPTH; i++ ) { //m_FFTData[i] += dErr; m_daDispData[i] = m_FFTData[i] + dErr; } // 计算最大值/最小值(这段没有意义,实际的最大最小在下面指定) m_dMaxData = -10000; m_dMinData = 0; for ( i = 0; i < m_dwDot; i++ ) { if ( m_nBeginPos+i >= 0 && m_nBeginPos+i < MAX_DEPTH/2 ) { if ( m_daDispData[m_nBeginPos+i] > m_dMaxData ) { m_dMaxData = m_daDispData[m_nBeginPos+i]; } if ( m_daDispData[m_nBeginPos+i] < m_dMinData ) { m_dMinData = m_daDispData[m_nBeginPos+i]; } } } // 最大值为0dB m_dMaxData = 0; // 最小值为-120dB -> -160 m_dMinData = -160; // 每像素的点数 double dPointXpixel = (nPicWidth - 0.0) / m_dwDot; double dPointYpixel = (nPicHeight - 0.0 ) / (m_dMaxData-m_dMinData); // 画笔 CPen penAxi( PS_DOT, 1, RGB(128, 128, 128)); pOldPen = m_dcPlot.SelectObject( &penAxi ); // 画坐标 double dData; int nCount; for ( i = 0; i < m_dwDot; i++ ) { dData = (m_nBeginPos+i)*m_dOrgSampFreq/MAX_DEPTH; // 先找到开始的大小 if ( i == 0 ) { nCount = dData / m_dGap;// + 1 } if ( dData >= nCount * m_dGap ) { // 画坐标线 x = FFT_LEFT_MARGIN + (int)(i*dPointXpixel); y = FFT_TOP_MARGIN; m_dcPlot.MoveTo( x, y ); x = FFT_LEFT_MARGIN + (int)(i*dPointXpixel); y = FFT_TOP_MARGIN + nPicHeight; m_dcPlot.LineTo( x, y ); // 找到第一个后更新计数的大小 nCount++; } } if ( pOldPen != NULL ) { m_dcPlot.SelectObject( pOldPen ); } CPen penSideAxi( PS_SOLID, 1, RGB(128, 128, 128)); pOldPen = m_dcPlot.SelectObject( &penSideAxi ); // 开始和最后的两根线 x = FFT_LEFT_MARGIN; y = FFT_TOP_MARGIN; m_dcPlot.MoveTo( x, y ); x = FFT_LEFT_MARGIN; y = FFT_TOP_MARGIN + nPicHeight; m_dcPlot.LineTo( x, y ); x = FFT_LEFT_MARGIN + nPicWidth; y = FFT_TOP_MARGIN; m_dcPlot.MoveTo( x, y ); x = FFT_LEFT_MARGIN + nPicWidth; y = FFT_TOP_MARGIN + nPicHeight; m_dcPlot.LineTo( x, y ); // 恢复现场 if ( pOldPen != NULL ) { m_dcPlot.SelectObject( pOldPen ); } penAxi.DeleteObject(); penSideAxi.DeleteObject(); // 显示曲线 m_bFirstVaule = TRUE; for ( i = 0; i < m_dwDot; i++ ) { // 先移动到第一个有效的点 if ( m_bFirstVaule && m_nBeginPos+i >= 0 && m_nBeginPos+i < MAX_DEPTH ) { m_bFirstVaule = FALSE; m_dcPlot.MoveTo( FFT_LEFT_MARGIN + (int)(i*dPointXpixel), FFT_TOP_MARGIN + nPicHeight - (int)((m_daDispData[m_nBeginPos+i] - m_dMinData)*dPointYpixel) ); } // 画线 if ( m_nBeginPos+i >= 0 && m_nBeginPos+i < MAX_DEPTH ) { x = FFT_LEFT_MARGIN + (int)(i*dPointXpixel); y = FFT_TOP_MARGIN + nPicHeight - (int)((m_daDispData[m_nBeginPos+i] - m_dMinData)*dPointYpixel); m_dcPlot.LineTo( x, y ); } } m_dcPlot.SelectObject( pOldPen ); penCh1Signal.DeleteObject(); // 擦除多余部分 CRect rcFill( 0, FFT_TOP_MARGIN + FFT_NUM_VERT * nSigPicSmallHeight, m_nClientWidth, m_nClientHeight ); m_dcPlot.FillRect( rcFill, &m_brushBack ); ///////////////////////////////////////////////////////////////////////////// // 显示坐标值 /////////////////////////////////////////////////////////////////////////// // 字体 m_dcPlot.SetTextColor( RGB(128, 128, 128) ); pOldFont = m_dcPlot.SelectObject( &m_fntScale ); // 坐标值 for ( i = 0; i < m_dwDot; i++ ) { dData = (m_nBeginPos+i)*m_dOrgSampFreq/MAX_DEPTH; // 先找到开始的大小 if ( i == 0 ) { if ( dData > 0 ) { nCount = dData / m_dGap + 1; } else { nCount = dData / m_dGap; } } if ( dData >= nCount * m_dGap ) { // 刻度值 //strMsg.Format( "%d", m_nBeginPos+i ); //strMsg.Format( "%.2f", (m_nBeginPos+i)*m_dOrgSampFreq/MAX_DEPTH ); strMsg.Format( "%.2f", nCount * m_dGap - m_dOrgSampFreq / 2 ); szText = m_dcPlot.GetTextExtent( strMsg ); x = FFT_LEFT_MARGIN + (int)(i*dPointXpixel) - szText.cx / 2; y = FFT_TOP_MARGIN + nPicHeight + 2; m_dcPlot.TextOut( x, y, strMsg ); nCount++; } } // 显示单位 strMsg = "(MHz)"; szText = m_dcPlot.GetTextExtent( strMsg ); x = FFT_LEFT_MARGIN + nPicWidth/2 - szText.cx / 2; y = FFT_TOP_MARGIN + nPicHeight + szText.cy; m_dcPlot.TextOut( x, y, strMsg ); if ( pOldFont != NULL ) { m_dcPlot.SelectObject( pOldFont ); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // 画标记 #define MARK_NUM 6 #define MINGAP 200 double dMaxData; int nPos; int naPos[MARK_NUM]; int t; bool bMax = FALSE; for ( i = 0; i < MARK_NUM; i++ ) { naPos[i] = -1; } // 查找5个最大值 for ( i = 0; i < MARK_NUM; i++ ) { dMaxData = -10000; //j>0, ignore DC for ( j = 1; j < MAX_DEPTH; j++ ) { // if ( j != naPos[0] && j != naPos[1] && j != naPos[2] // && j != naPos[3] && j != naPos[4] && m_daDispData[j] > dMaxData // && abs(j-naPos[0])>MINGAP && abs(j-naPos[1])>MINGAP && abs(j-naPos[2])>MINGAP // && abs(j-naPos[3])>MINGAP && abs(j-naPos[4])>MINGAP) // { // dMaxData = m_daDispData[j]; // nPos = j; // } if ( m_daDispData[j] > dMaxData) { bMax = TRUE; for (t=0; t<i; ++t) { if (j==naPos[t] || abs(j-naPos[t])<MINGAP) { bMax = FALSE; } } if (bMax) { dMaxData = m_daDispData[j]; nPos = j; } } } for (t=i; t<MARK_NUM; ++t) { naPos[t] = nPos; } //TRACE( "pos = %d, data = %f\n", naPos[i], m_daDispData[ naPos[i] ] ); } pOldFont = m_dcPlot.SelectObject( &m_fntTitle ); m_dcPlot.SetTextColor( RGB(0,255,255) ); // 画标记 CString strMax; for ( i = 0; i < MARK_NUM; i++ ) { // 在当前显示的点数范围内才显示 if ( naPos[i] - m_nBeginPos < m_dwDot ) { x = FFT_LEFT_MARGIN + (int)( (naPos[i]-m_nBeginPos) * dPointXpixel ); y = FFT_TOP_MARGIN + nPicHeight - (int)((m_daDispData[ naPos[i] ] - m_dMinData)*dPointYpixel); DrawMark( x, y, 'x', RGB(0,255,255) ); strMax.Format( "(%.2f,%.2f)", naPos[i]*m_dOrgSampFreq/MAX_DEPTH, m_daDispData[ naPos[i] ] ); m_dcPlot.TextOut(x+3, y-3, strMax ); } } //////////////////////////////////////////////////////////////////////// // 显示参数 //////////////////////////////////////////////////////////////////////// if ( m_dVpp > 0 && m_bShowParam ) { // 查找最长的,左边对齐 strMsg.Format( "SFDR = %2.2fdB", m_dSFDR ); szText = m_dcPlot.GetTextExtent( strMsg ); int nLen = szText.cx; // Ain(峰峰值最大为2V) dErr = 20*log10( m_dVpp / 2); strMsg.Format( "AIN = %.2fdB", dErr ); szText = m_dcPlot.GetTextExtent( strMsg ); x = m_nClientWidth - FFT_LEFT_MARGIN - nLen; y = FFT_TOP_MARGIN + 2; m_dcPlot.TextOut( x, y, strMsg ); // SNR strMsg.Format( "SNR = %.2fdB", m_dSNR ); szText = m_dcPlot.GetTextExtent( strMsg ); x = m_nClientWidth - FFT_LEFT_MARGIN - nLen; y = FFT_TOP_MARGIN + 2 + szText.cy; m_dcPlot.TextOut( x, y, strMsg ); // SFDR strMsg.Format( "SFDR = %.2fdB", m_dSFDR ); szText = m_dcPlot.GetTextExtent( strMsg ); x = m_nClientWidth - FFT_LEFT_MARGIN - nLen; y = FFT_TOP_MARGIN + 2 + szText.cy*2; m_dcPlot.TextOut( x, y, strMsg ); // SINAD strMsg.Format( "SINAD = %.2fdB", m_dSINAD ); szText = m_dcPlot.GetTextExtent( strMsg ); x = m_nClientWidth - FFT_LEFT_MARGIN - nLen; y = FFT_TOP_MARGIN + 2 + szText.cy*3; m_dcPlot.TextOut( x, y, strMsg ); // ENOB strMsg.Format( "ENOB = %.2f", m_dENOB ); szText = m_dcPlot.GetTextExtent( strMsg ); x = m_nClientWidth - FFT_LEFT_MARGIN - nLen; y = FFT_TOP_MARGIN + 2 + szText.cy*4; m_dcPlot.TextOut( x, y, strMsg ); } if ( pOldFont != NULL ) { m_dcPlot.SelectObject( pOldFont ); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // 在顶部显示五个最大值 CString straValue[MARK_NUM]; DWORD dwMarkWidth; dwMarkWidth = 0; for ( i = 0; i < MARK_NUM; i++ ) { // 安全检查 if ( naPos[i] > 0 ) { straValue[i].Format( "(%.2f,%.2f)", naPos[i]*m_dOrgSampFreq/MAX_DEPTH, m_daDispData[ naPos[i] ] ); } szText = m_dcPlot.GetTextExtent( straValue[i] ); dwMarkWidth += szText.cx; } pOldFont = m_dcPlot.SelectObject( &m_fntTitle ); m_dcPlot.SetTextColor( RGB(0,255,255) ); // 视图足够宽时显示5个值 if ( dwMarkWidth < nPicWidth ) { x = (nPicWidth-dwMarkWidth)/2; y = 0; szText.cx = 0; for ( i = 0; i < MARK_NUM; i++ ) { if ( i > 0 ) { szText = m_dcPlot.GetTextExtent( straValue[i-1] ); } x += szText.cx; m_dcPlot.TextOut( x, y, straValue[i] ); } } if ( pOldFont != NULL ) { m_dcPlot.SelectObject( pOldFont ); } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // 鼠标移动显示坐标值 if ( m_ptMove.x >= FFT_LEFT_MARGIN && m_ptMove.x <= FFT_LEFT_MARGIN + nPicWidth && m_ptMove.y >= FFT_TOP_MARGIN && m_ptMove.y <= FFT_TOP_MARGIN + nPicHeight ) { CString strValue; int nPos; nPos = (m_ptMove.x - FFT_LEFT_MARGIN)*m_dwDot/nPicWidth + m_nBeginPos; if ( nPos >= 0 && nPos < MAX_DEPTH / 2 ) { // 显示鼠标点的坐标 //strValue.Format( "(%.2f , %.2f)", nPos * m_dOrgSampFreq / MAX_DEPTH, // -(m_ptMove.y - FFT_TOP_MARGIN) / dPointYpixel ); // 显示曲线上的点频率和幅度 strValue.Format( "(%.2f , %.2f)", nPos * m_dOrgSampFreq / MAX_DEPTH, m_daDispData[nPos] ); // 字体 pOldFont = m_dcPlot.SelectObject( &m_fntTitle ); m_dcPlot.SetTextColor( RGB(0,255,255) ); // 显示的区域 szText = m_dcPlot.GetTextExtent( strValue ); if ( m_ptMove.x + szText.cx <= FFT_LEFT_MARGIN + nPicWidth && m_ptMove.y >= FFT_TOP_MARGIN ) { m_dcPlot.TextOut( m_ptMove.x, m_ptMove.y - szText.cy, strValue ); } } } ////////////////////////////////////////////////////////////////////////////// Invalidate(); } }
void CProgressCtrlX::DrawText(const CDrawInfo& info, const CRect &rcMax, const CRect &rcBar) { if(!(info.dwStyle&PBS_TEXTMASK)) return; BOOL fVert = info.dwStyle&PBS_VERTICAL; CDC *pDC = info.pDC; int nValue = 0; CString sFormat; GetWindowText(sFormat); switch(info.dwStyle&PBS_TEXTMASK) { case PBS_SHOW_PERCENT: if(sFormat.IsEmpty()) sFormat = _T("%d%%"); // retrieve current position and range nValue = (int)((float)(info.nCurPos-info.nLower) * 100 / ((info.nUpper-info.nLower == 0) ? 1 : info.nUpper-info.nLower)); break; case PBS_SHOW_POSITION: if(sFormat.IsEmpty()) sFormat = _T("%d"); // retrieve current position nValue = info.nCurPos; break; } if (sFormat.IsEmpty()) return; CFont* pFont = GetFont(); CSelFont sf(pDC, pFont); CSelTextColor tc(pDC, m_clrTextOnBar); CSelBkMode bm(pDC, TRANSPARENT); CSelTextAlign ta(pDC, TA_BOTTOM|TA_CENTER); CPoint ptOrg = pDC->GetWindowOrg(); CString sText; sText.Format(sFormat, nValue); LONG grad = 0; if(pFont) { LOGFONT lf; pFont->GetLogFont(&lf); grad = lf.lfEscapement/10; } int x = 0, y = 0, dx = 0, dy = 0; CSize sizText = pDC->GetTextExtent(sText); if(grad == 0) { x = sizText.cx; y = sizText.cy; dx = 0; dy = sizText.cy;} else if(grad == 90) { x = sizText.cy; y = sizText.cx; dx = sizText.cy; dy = 0;} else if(grad == 180) { x = sizText.cx; y = sizText.cy; dx = 0; dy = -sizText.cy;} else if(grad == 270) { x = sizText.cy; y = sizText.cx; dx = -sizText.cy; dy = 0;} else ASSERT(0); // angle not supported CPoint pt = pDC->GetViewportOrg(); if(info.dwStyle&PBS_TIED_TEXT) { CRect rcFill(ConvertToReal(info, rcBar)); if((fVert ? y : x) <= rcBar.Width()) { pDC->SetViewportOrg(rcFill.left + (rcFill.Width() + dx)/2, rcFill.top + (rcFill.Height() + dy)/2); DrawClippedText(info, rcBar, sText, ptOrg); } } else { pDC->SetViewportOrg(info.rcClient.left + (info.rcClient.Width() + dx)/2, info.rcClient.top + (info.rcClient.Height() + dy)/2); if(m_clrTextOnBar == m_clrTextOnBk) // if the same color for bar and background draw text once DrawClippedText(info, rcMax, sText, ptOrg); else { // else, draw clipped parts of text // draw text on gradient if(rcBar.left != rcBar.right) DrawClippedText(info, rcBar, sText, ptOrg); // draw text out of gradient if(rcMax.right > rcBar.right) { tc.Select(m_clrTextOnBk); CRect rc(rcMax); rc.left = rcBar.right; DrawClippedText(info, rc, sText, ptOrg); } if(rcMax.left < rcBar.left) { tc.Select(m_clrTextOnBk); CRect rc(rcMax); rc.right = rcBar.left; DrawClippedText(info, rc, sText, ptOrg); } } } pDC->SetViewportOrg(pt); }
void CChevronOwnerDrawMenu::DrawItem(LPDRAWITEMSTRUCT pdis) { ASSERT(pdis->CtlType == ODT_MENU); CString strText(_T("")); CSize Size; CDC *pDC; pDC = CDC::FromHandle(pdis->hDC); int nSave = pDC->SaveDC(); // getting the text (on the right of the bitmap) MENUITEMINFO info; ZeroMemory(&info, sizeof(MENUITEMINFO)); info.cbSize = sizeof(MENUITEMINFO); info.fMask = MIIM_STRING; BOOL bGotText = FALSE; if(GetMenuItemInfo(pdis->itemID, &info)) { LPTSTR pszText; pszText = strText.GetBuffer(info.cch); info.dwTypeData = pszText; info.cch++; // space for zero terminator bGotText = GetMenuItemInfo(pdis->itemID, &info); strText.ReleaseBuffer(); } CBitmap *pBmp; pBmp = (CBitmap *) pdis->itemData; // Find the rect that will center the bitmap in the menu item CRect rc, rcItem(pdis->rcItem); BOOL bGotBitmap = FALSE; int nBitmapHeight = 0; int nBitmapWidth = 0; if(pBmp && pBmp->IsKindOf(RUNTIME_CLASS(CBitmap))) { BITMAP bitmap; bGotBitmap = TRUE; pBmp->GetObject(sizeof(BITMAP), &bitmap); nBitmapHeight = bitmap.bmHeight; nBitmapWidth = bitmap.bmWidth; } else { // using default icon size bGotBitmap = FALSE; nBitmapHeight = ::GetSystemMetrics(SM_CYSMICON); nBitmapWidth = ::GetSystemMetrics(SM_CXSMICON); } rc.top = rcItem.Height() / 2 - nBitmapHeight / 2 + rcItem.top - 1; rc.left = 0; rc.right = nBitmapWidth + 1; rc.bottom = nBitmapHeight + 1; rc.bottom += rc.top; rc.right += rc.left; //the actual drawing begins COLORREF crMenu = ::GetSysColor(COLOR_MENU); CDC dcMem; dcMem.CreateCompatibleDC(NULL); pDC->SelectObject(&m_MenuFont); Size = pDC->GetTextExtent(strText); // Selected (possibly grayed) if(pdis->itemState & ODS_SELECTED) { // MenuColor CRect rcFill(pdis->rcItem); rcFill.left = rc.right + 2; pDC->FillSolidRect(rcFill, ::GetSysColor(COLOR_HIGHLIGHT)); // if not grayed and not checked, raise the button if (bGotBitmap) { if(!(pdis->itemState & (ODS_GRAYED | ODS_CHECKED))) { pDC->Draw3dRect(rc.left, rc.top, rc.Width() + 1, rc.Height() + 1, ::GetSysColor(COLOR_BTNHIGHLIGHT), ::GetSysColor(COLOR_BTNSHADOW)); } } // Text if (bGotText) { pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT)); pDC->SetTextColor( (pdis->itemState & ODS_GRAYED) ? crMenu : ::GetSysColor(COLOR_HIGHLIGHTTEXT)); pDC->ExtTextOut(rc.right + 3, rc.top + rc.Height() / 2 - Size.cy / 2, ETO_OPAQUE, NULL, strText, NULL); } } else { pDC->FillSolidRect(&pdis->rcItem, crMenu); pDC->SetBkColor(crMenu); // Grayed (disabled) if(pdis->itemState & ODS_GRAYED) { pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT)); pDC->SetBkMode(TRANSPARENT); // Text if (bGotText) { pDC->ExtTextOut(rc.right + 4, rc.top + rc.Height() / 2 - Size.cy / 2 + 1, ETO_OPAQUE, NULL, strText, NULL); pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT)); pDC->ExtTextOut(rc.right + 3, rc.top + rc.Height() / 2 - Size.cy / 2, 0, NULL, strText, NULL); } } // Everything else else { // if checked draw as pushed if (bGotBitmap) { if(pdis->itemState & ODS_CHECKED) { pDC->Draw3dRect(rc.left, rc.top, rc.Width() + 1, rc.Height() + 1, ::GetSysColor(COLOR_BTNSHADOW), ::GetSysColor(COLOR_BTNHIGHLIGHT)); } } // text if (bGotText) { pDC->SetBkColor(crMenu); pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT)); pDC->ExtTextOut(rc.right + 3, rc.top + rc.Height() / 2 - Size.cy / 2, ETO_OPAQUE, NULL, strText, NULL); } } } // The bitmap... if (bGotBitmap) { CBitmap bmp; int x = 0, y = 0; if(pdis->itemState & ODS_GRAYED) { ::AfxGetGrayBitmap(*pBmp, &bmp, crMenu); pBmp = &bmp; } else { if(pdis->itemState & ODS_CHECKED) { ::AfxGetDitheredBitmap(*pBmp, &bmp, crMenu, RGB(255, 255, 255)); pBmp = &bmp; } } CDC dcMem; dcMem.CreateCompatibleDC(NULL); dcMem.SelectObject(pBmp); rc.InflateRect(-1, -1); pDC->BitBlt(rc.left, rc.top, rc.right, rc.bottom, &dcMem, x, y, SRCCOPY); } pDC->RestoreDC(nSave); }
void CProgressCtrlX::DrawGradient(const CDrawInfo& info, const CRect &rcGrad, const CRect &rcClip, COLORREF clrStart, COLORREF clrEnd) { // Split colors to RGB chanels, find chanel with maximum difference // between the start and end colors. This distance will determine // number of steps of gradient int r = (GetRValue(clrEnd) - GetRValue(clrStart)); int g = (GetGValue(clrEnd) - GetGValue(clrStart)); int b = (GetBValue(clrEnd) - GetBValue(clrStart)); int nSteps = max(abs(r), max(abs(g), abs(b))); // if number of pixels in gradient less than number of steps - // use it as numberof steps int nPixels = rcGrad.Width(); nSteps = min(nPixels, nSteps); if(nSteps == 0) nSteps = 1; float rStep = (float)r/nSteps; float gStep = (float)g/nSteps; float bStep = (float)b/nSteps; r = GetRValue(clrStart); g = GetGValue(clrStart); b = GetBValue(clrStart); BOOL fLowColor = info.pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE; if(!fLowColor && nSteps > 1) if(info.pDC->GetDeviceCaps(BITSPIXEL)*info.pDC->GetDeviceCaps(PLANES) < 8) nSteps = 1; // for 16 colors no gradient float nWidthPerStep = (float)rcGrad.Width() / nSteps; CRect rcFill(rcGrad); CBrush br; // Start filling for (int i = 0; i < nSteps; i++) { rcFill.left = rcGrad.left + (int)(nWidthPerStep * i); rcFill.right = rcGrad.left + (int)(nWidthPerStep * (i+1)); if(i == nSteps-1) //last step (because of problems with float) rcFill.right = rcGrad.right; if(rcFill.right < rcClip.left) continue; // skip - band before cliping rect // clip it if(rcFill.left < rcClip.left) rcFill.left = rcClip.left; if(rcFill.right > rcClip.right) rcFill.right = rcClip.right; COLORREF clrFill = RGB(r + (int)(i * rStep), g + (int)(i * gStep), b + (int)(i * bStep)); if(fLowColor) { br.CreateSolidBrush(clrFill); // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth info.pDC->FillRect(&ConvertToReal(info, rcFill), &br); br.DeleteObject(); } else info.pDC->FillSolidRect(&ConvertToReal(info, rcFill), clrFill); if(rcFill.right >= rcClip.right) break; // stop filling if we reach current position } }
/***************************************************************************** * NAME: * DrawGradient * * DESCRIPTION: * Found this as part of an overly complicated gradient progress bar on codeguru * So, I simplified it for my own uses :) -Lumberjack * *******************************************************************************/ void CSideBarCtrl::DrawGradient(CDC* pDC, const CRect &rcGrad, COLORREF clrStart, COLORREF clrEnd, BOOL bVertical, COLORREF clrDither /*=0xFFFFFFFF*/ ) { // Split colors to RGB chanels, find chanel with maximum difference // between the start and end colors. This distance will determine // number of steps of gradient int r = (GetRValue(clrEnd) - GetRValue(clrStart)); int g = (GetGValue(clrEnd) - GetGValue(clrStart)); int b = (GetBValue(clrEnd) - GetBValue(clrStart)); int nSteps = max(abs(r), max(abs(g), abs(b))); // if number of pixels in gradient less than number of steps - // use it as numberof steps int nPixels = rcGrad.Width(); nSteps = min(nPixels, nSteps); if(nSteps == 0) nSteps = 1; float rStep = (float)r/nSteps; float gStep = (float)g/nSteps; float bStep = (float)b/nSteps; r = GetRValue(clrStart); g = GetGValue(clrStart); b = GetBValue(clrStart); BOOL fLowColor = pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE; if(!fLowColor && nSteps > 1) if(pDC->GetDeviceCaps(BITSPIXEL)*pDC->GetDeviceCaps(PLANES) < 8) nSteps = 1; // for 16 colors no gradient float nSpacePerStep = bVertical?(float)rcGrad.Height()/nSteps:(float)rcGrad.Width()/nSteps; CRect rcFill(rcGrad); CBrush br; // Start filling for (int i = 0; i < nSteps; i++) { if( bVertical ) { rcFill.top = rcGrad.top + (int)(nSpacePerStep * i); rcFill.bottom = rcGrad.top + (int)(nSpacePerStep * (i+1)); if(i == nSteps-1) //last step (because of problems with float) rcFill.bottom = rcGrad.bottom; } else { rcFill.left = rcGrad.left + (int)(nSpacePerStep * i); rcFill.right = rcGrad.left + (int)(nSpacePerStep * (i+1)); if(i == nSteps-1) //last step (because of problems with float) rcFill.right = rcGrad.right; } COLORREF clrFill = RGB(r + (int)(i * rStep), g + (int)(i * gStep), b + (int)(i * bStep)); if( fLowColor ) { br.CreateSolidBrush(clrFill); // CDC::FillSolidRect is faster, but it does not handle 8-bit color depth pDC->FillRect(&rcFill, &br); br.DeleteObject(); } else { if( 0xFFFFFFFF != clrDither ) { COLORREF crExisting = 0; for( int nHoriz = rcFill.left; nHoriz < rcFill.right; nHoriz++ ) { for( int nVert = rcFill.top; nVert < rcFill.bottom; nVert++ ) { crExisting = pDC->GetPixel(nHoriz,nVert); if( crExisting == clrDither ) { pDC->SetPixel(nHoriz,nVert,findMidColor(clrFill,clrDither) ); } else { pDC->SetPixel(nHoriz,nVert,clrFill); } } } } else { pDC->FillSolidRect(&rcFill, clrFill); } } } }