#include "stdafx.h" #include "TGSizeDescrWnd.h" #include "math.h" //#define PI 3.1415926535 #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif CTGSizeDescrWnd::CTGSizeDescrWnd() { m_dPer = 0.00; m_eStyle = kProcess/*kPie*/; } CTGSizeDescrWnd::~CTGSizeDescrWnd() { } BEGIN_MESSAGE_MAP(CTGSizeDescrWnd, CStatic) //{{AFX_MSG_MAP(CTGSizeDescrWnd) ON_WM_PAINT() ON_WM_ERASEBKGND() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CTGSizeDescrWnd::SetPer(double dVal) { m_dPer = dVal; } double CTGSizeDescrWnd::GetPer() { return m_dPer; } void CTGSizeDescrWnd::SetStyle(Style eStyle) { m_eStyle = eStyle; } int CTGSizeDescrWnd::GetStyle() { return m_eStyle; } void CTGSizeDescrWnd::OnPaint() { CPaintDC dc(this); switch(m_eStyle) { case kPie: { DrawPie(&dc); break; } case kProcess: { DrawProcess(&dc); break; } default: break; } return; } BOOL CTGSizeDescrWnd::OnEraseBkgnd(CDC* pDC) { return TRUE; } CPoint CTGSizeDescrWnd::GetPerPoint(double dPer, int nWidthRadius, int nHeightRadius, const CPoint& ptCenter) { CPoint ptRslt(0,0); int i10XPer = (int)dPer*10; switch(i10XPer) { case 0: ptRslt.x = 2 * nWidthRadius; ptRslt.y = nHeightRadius-1; return ptRslt; case 1000: ptRslt.x = 2 * nWidthRadius; ptRslt.y = nHeightRadius; return ptRslt; case 125: ptRslt.x = 2 * nWidthRadius; ptRslt.y = 0; return ptRslt; case 250: ptRslt.x = nWidthRadius; ptRslt.y = 0; return ptRslt; case 375: ptRslt.x = 0; ptRslt.y = 0; return ptRslt; case 500: ptRslt.x = 0; ptRslt.y = nHeightRadius; return ptRslt; case 625: ptRslt.x = 0; ptRslt.y = 2 * nHeightRadius; return ptRslt; case 750: ptRslt.x = nWidthRadius; ptRslt.y = 2 * nHeightRadius; return ptRslt; case 875: ptRslt.x = 2 * nWidthRadius; ptRslt.y = 2 * nHeightRadius; return ptRslt; default: break; } int XOffSet = 0; ///x值偏移中心值 int YOffSet = 0; ///y值偏移中心值 /// 如果dPer在0 - 12.5区间, if( i10XPer < 125 && i10XPer > 0 ) { YOffSet = (int)(0.008 * nHeightRadius * i10XPer); ptRslt.x = 2 * nWidthRadius; ptRslt.y = nHeightRadius - YOffSet; } else if( i10XPer < 375 && i10XPer > 125 ) { XOffSet = (int)(0.008 * nWidthRadius * fabs((double)(i10XPer - 250))); if (i10XPer < 250) { ptRslt.x = nWidthRadius + XOffSet; } else { ptRslt.x = nWidthRadius - XOffSet; } ptRslt.y = 0; } else if( i10XPer < 625 && i10XPer > 375 ) { YOffSet = (int)(0.008 * nHeightRadius * fabs((double)(i10XPer - 500))); if (i10XPer < 500) { ptRslt.y = nHeightRadius - YOffSet; ptRslt.x = 0; } else { double dPer2Rad = PI * dPer / 50.0; ///pie终点与椭圆圆心连线在椭圆上的交点的纵坐标值与XOffSet的差值 int iPieLineXElps2Offet_Y = (int)fabs(YOffSet + (sin(dPer2Rad) * nHeightRadius)); ///pie终点与椭圆圆心连线在椭圆上的交点的横坐标值与矩形左边的差值 int iPieLineXElps2Right_X = (int)fabs((cos(dPer2Rad) * nWidthRadius) + nWidthRadius); ptRslt.x = iPieLineXElps2Right_X; ptRslt.y = nHeightRadius + YOffSet - iPieLineXElps2Offet_Y; } } else if( i10XPer < 875 && i10XPer > 625 ) { XOffSet = (int)(0.008 * nWidthRadius * fabs((double)(i10XPer - 750))); double dPer2Rad = PI * dPer / 50.0; ///pie终点与椭圆圆心连线在椭圆上的交点的横坐标值与XOffSet的差值 ///pie终点与椭圆圆心连线在椭圆上的交点的纵坐标值与矩形底边的差值 int iPieLineXElps2Bottom_Y = (int)fabs(nHeightRadius + (sin(dPer2Rad) * nHeightRadius)); if (i10XPer < 750) { int iPieLineXElps2Offet_X = (int)fabs(XOffSet + (cos(dPer2Rad) * nWidthRadius)); ptRslt.x = nWidthRadius - XOffSet + iPieLineXElps2Offet_X; } else { int iPieLineXElps2Offet_X = (int)fabs(XOffSet - (cos(dPer2Rad) * nWidthRadius)); ptRslt.x = nWidthRadius + XOffSet - iPieLineXElps2Offet_X; } ptRslt.y = 2 * nHeightRadius - iPieLineXElps2Bottom_Y; } else if( i10XPer < 1000 && i10XPer > 875 ) { YOffSet = (int)(0.008 * nHeightRadius * (1000 -i10XPer)); double dPer2Rad = PI * dPer / 50.0; ///pie终点与椭圆圆心连线在椭圆上的交点的纵坐标值与XOffSet的差值 int iPieLineXElps2Offet_Y = (int)fabs(YOffSet + (sin(dPer2Rad) * nHeightRadius)); ///pie终点与椭圆圆心连线在椭圆上的交点的横坐标值与矩形右边的差值 int iPieLineXElps2Right_X = (int)fabs(nWidthRadius - (cos(dPer2Rad) * nWidthRadius)); ptRslt.x = 2 * nWidthRadius - iPieLineXElps2Right_X; ptRslt.y = nHeightRadius + YOffSet - iPieLineXElps2Offet_Y; } return ptRslt; } void CTGSizeDescrWnd::DrawPie(CDC *pDC) { ASSERT(pDC != NULL); if ( GetPer() < -1.e-10 || GetPer() - 100 > 1.e-10) { ::MessageBox(AfxGetMainWnd()->m_hWnd, _T("使用的空间范围有误!"),_T("TPM"), MB_OK); return; } CRect rc; //上面的粉色pie CRect rc2;//下面的紫色pie GetClientRect(&rc);//控件的矩形区大小 rc2 = rc; rc2.OffsetRect(0,15); //将紫色pie矩形区向下偏移15像素 CBrush brBkgnd,brFrgnd,brDrawClr; CBrush* pBrushOld = NULL; brBkgnd.CreateSolidBrush( RGB(128,0,128) );//RGB(128,0,128) 紫色 brFrgnd.CreateSolidBrush( RGB(255,0,255) );//RGB(255,0,255) 粉色 brDrawClr.CreateSolidBrush( RGB(0,0,255) );//RGB(0,0,255) 蓝色 //画紫色pie pBrushOld = pDC->SelectObject(&brBkgnd); pDC->Ellipse(rc2); pDC->SelectObject(pBrushOld); brBkgnd.DeleteObject(); //ptStart 画饼的起始点 //ptEnd 粉色饼的结束点 //ptBkgndPieEnd 紫色饼的结束点 CPoint ptStart,ptEnd,ptBkgndPieEnd; //起始位置 ptStart.x = rc2.right; ptStart.y = rc2.CenterPoint().y; //取得粉色pie终点的位置 ptEnd = GetPerPoint( m_dPer, rc.Width() / 2, rc.Height() / 2, rc.CenterPoint() ); //对于紫色pie,终点位置相对于粉色pie向下偏移15个像素 ptBkgndPieEnd.x = ptEnd.x; ptBkgndPieEnd.y = ptEnd.y + 15; //画紫色pie中使用的蓝色部分,当m_dPer为0时,不画,只使用紫色的背景 if( (m_dPer > 1.e-10) && (m_dPer - 100.0 < 1.e-10)) { pBrushOld =pDC->SelectObject(&brDrawClr); pDC->Pie( rc2, ptStart, ptBkgndPieEnd); } if (100.0 - m_dPer < 1.e-10) { pBrushOld =pDC->SelectObject(&brDrawClr); pDC->Ellipse(rc2); } //修正立体效果,用rc2矩形中点和紫色pie的终点建立修正矩形 if ( (m_dPer - 50.0 > 1.e-10) && (m_dPer - 75.0 < 1.e-10) ) { CRect rc2Fix; rc2Fix.top = rc2.CenterPoint().y; rc2Fix.left = ptBkgndPieEnd.x; rc2Fix.right = rc2.CenterPoint().x; rc2Fix.bottom = ptBkgndPieEnd.y; CPen penNew; CPen* pPenOld = NULL; penNew.CreatePen(PS_SOLID,0,RGB(128,0,128)); pPenOld = pDC->SelectObject(&penNew); brBkgnd.CreateSolidBrush( RGB(128,0,128) );//RGB(128,0,128)紫色 pBrushOld = pDC->SelectObject(&brBkgnd); pDC->Rectangle(rc2Fix); pDC->SelectObject(pBrushOld); pDC->SelectObject(pPenOld); brBkgnd.DeleteObject(); penNew.DeleteObject(); //画连接上下两个终点的饼的边线 pDC->MoveTo(ptBkgndPieEnd); pDC->LineTo(ptBkgndPieEnd.x,ptBkgndPieEnd.y - 15); } else if ( (m_dPer - 75.0 > 1.e-10) && (m_dPer - 100.0 < 1.e-10) ) { CRect rc2Fix; rc2Fix.top = rc2.CenterPoint().y; rc2Fix.left = rc2.CenterPoint().x; rc2Fix.bottom = ptBkgndPieEnd.y; rc2Fix.right = ptBkgndPieEnd.x; CPen penNew; CPen* pPenOld = NULL; penNew.CreatePen(PS_SOLID, 0, RGB(0,0,255)); pPenOld = pDC->SelectObject(&penNew); brBkgnd.CreateSolidBrush( RGB(0,0,255) );//RGB(0,0,255)蓝色 pBrushOld = pDC->SelectObject(&brBkgnd); pDC->Rectangle(rc2Fix); pDC->SelectObject(pBrushOld); pDC->SelectObject(pPenOld); brBkgnd.DeleteObject(); penNew.DeleteObject(); //画连接上下两个终点的饼的边线 pDC->MoveTo(ptBkgndPieEnd); pDC->LineTo(ptBkgndPieEnd.x,ptBkgndPieEnd.y - 15); } pDC->SelectObject(pBrushOld); //连接上下椭圆两边的侧线,看起来比较立体一些 pDC->MoveTo(rc2.left, rc2.CenterPoint().y); pDC->LineTo(rc.left, rc.CenterPoint().y); pDC->MoveTo(rc2.right, rc2.CenterPoint().y); pDC->LineTo(rc.right, rc.CenterPoint().y); //画粉色的pie pBrushOld = pDC->SelectObject( &brFrgnd ); pDC->Ellipse(rc); pDC->SelectObject(pBrushOld); brFrgnd.DeleteObject(); //画粉色pie中使用的蓝色部分 ptStart.x = rc.right; ptStart.y = rc.CenterPoint().y; pBrushOld =pDC->SelectObject(&brDrawClr); if ( m_dPer > 1.e-10 && m_dPer - 100.0 < 1.e-10) { pDC->Pie(rc, ptStart, ptEnd); } //如果是100%,直接画椭圆,m_dPer == 100 if (fabs(100.0 - m_dPer) < 1.e-10) { pDC->Ellipse(rc); } pDC->SelectObject(pBrushOld); //加使用率文字 CFont ftPerTxt; ftPerTxt.CreateFont( 15, 0, 0, 0, FW_BLACK, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY , DEFAULT_PITCH, NULL ); CFont* pOldFont=(CFont*)pDC->SelectObject(&ftPerTxt); pDC->SetTextColor(RGB(255,255,0)); pDC->SetBkMode(TRANSPARENT); CString str; str.Format(_T("%d"), int(m_dPer)); str += _T("%"); const double fXScale = rc.CenterPoint().x/112.5; //112.5为制作控件时的长轴 const double fYScale = rc.CenterPoint().y/69.0; //69.0为制作控件时的短轴 //1 3 && int(m_dPer) <= 25) { if (int(m_dPer) < 7) { pDC->TextOut( ((rc.CenterPoint().x * 3) / 2 + (int)(2.0 * fXScale)), ((rc.CenterPoint().y + ptEnd.y) / 2 ), str); } else { pDC->TextOut( ((rc.CenterPoint().x * 3) / 2 ), ((rc.CenterPoint().y + ptEnd.y) / 2 + (int)(5.0 * fXScale)), str); } } else if (int(m_dPer) > 25 && int(m_dPer) <= 50) { if (int(m_dPer) < 37) { pDC->TextOut( ((rc.right + ptEnd.x) / 2 - (int)(12.0 * fXScale)), ((rc.CenterPoint().y + ptEnd.y) / 2 - (int)(1.0 * fYScale) - 1), str); } else { pDC->TextOut( ((rc.right + ptEnd.x) / 2 - (int)(8.0 * fXScale)), ((rc.CenterPoint().y) / 2 - (int)(3.0 * fYScale)), str); } } else if (int(m_dPer) > 50 && int(m_dPer) <= 75) { if (int(m_dPer) < 67) { pDC->TextOut( (rc.CenterPoint().x - (int)((m_dPer - 48) * 2 * fXScale)), ((rc.CenterPoint().y) / 2 - (int)(5.0 * fYScale)) , str); } else { pDC->TextOut( (rc.CenterPoint().x / 2 - (int)((69 - m_dPer) * 2 * fXScale)), ((rc.CenterPoint().y) - 20), str); } } else if (int(m_dPer) > 75 && int(m_dPer) <= 100) { if (int(m_dPer) < 87) { pDC->TextOut( rc.CenterPoint().x / 2 , ((rc.CenterPoint().y) - 20), str); } else { pDC->TextOut( (rc.CenterPoint().x / 2 - (int)((79 - m_dPer) * 2 * fXScale)), ((rc.CenterPoint().y) - 20), str); } } ftPerTxt.DeleteObject(); // str.Format("h:%d w:%d",rc.Height(),rc.Width()); // MessageBox(str); return; } void CTGSizeDescrWnd::DrawProcess(CDC *pDC) { ASSERT(pDC != NULL); //m_dPer >= 0 && m_dPer <= 100 if ((m_dPer > -1.e-10) && (m_dPer - 100.0 < 1.e-10)) { //画背景条 CRect rc; GetClientRect(&rc); CBrush brBkgnd; CBrush* pBrushOld = NULL; brBkgnd.CreateSolidBrush( RGB(128,0,128) );//RGB(128,0,128)紫色 pBrushOld = pDC->SelectObject(&brBkgnd); pDC->Rectangle(rc); pDC->SelectObject(pBrushOld); brBkgnd.DeleteObject(); //画使用百分率条 CBrush brDrawClr; brDrawClr.CreateSolidBrush( RGB(0,0,255) );//RGB(0,0,255)蓝色 pBrushOld = pDC->SelectObject(&brDrawClr); pDC->Rectangle(rc.left, rc.top, (int)(rc.right * m_dPer / 100), rc.bottom); pDC->SelectObject(pBrushOld); brDrawClr.DeleteObject(); return; } else { MessageBox(_T("使用的空间范围有误!"),_T("错误")); return; } }