#include "Hello.h" #define SEGMENTS 500 #define PI 3.1415926535897932384626433832795 CMyApp myApp; #define CLKSCALE ((INT)8000) // 表盘 typedef struct { SHORT sin; SHORT cos; } TRIG; TRIG CirTab[] = { // circle sin, cos, table { -7999, -0 }, { -7956, -836 }, { -7825, -1663 }, { -7608, -2472 }, { -7308, -3253 }, { -6928, -4000 }, { -6472, -4702 }, { -5945, -5353 }, { -5353, -5945 }, { -4702, -6472 }, { -3999, -6928 }, { -3253, -7308 }, { -2472, -7608 }, { -1663, -7825 }, { -836 , -7956 }, { 0, -7999 }, { 836, -7956 }, { 1663, -7825 }, { 2472, -7608 }, { 3253, -7308 }, { 3999, -6928 }, { 4702, -6472 }, { 5353, -5945 }, { 5945, -5353 }, { 6472, -4702 }, { 6928, -4000 }, { 7308, -3253 }, { 7608, -2472 }, { 7825, -1663 }, { 7956, -836 }, { 8000, 0 }, { 7956, 836 }, { 7825, 1663 }, { 7608, 2472 }, { 7308, 3253 }, { 6928, 4000 }, { 6472, 4702 }, { 5945, 5353 }, { 5353, 5945 }, { 4702, 6472 }, { 3999, 6928 }, { 3253, 7308 }, { 2472, 7608 }, { 1663, 7825 }, { 836, 7956 }, { 0, 7999 }, { -836, 7956 }, { -1663, 7825 }, { -2472, 7608 }, { -3253, 7308 }, { -4000, 6928 }, { -4702, 6472 }, { -5353, 5945 }, { -5945, 5353 }, { -6472, 4702 }, { -6928, 3999 }, { -7308, 3253 }, { -7608, 2472 }, { -7825, 1663 }, { -7956, 836 } }; // End BOOL CMyApp::InitInstance() { // Initialize GDI+. Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); m_pMainWnd = new CMainWindow(); m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); return CWinApp::InitInstance(); } BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP() CMainWindow::CMainWindow() { Create(NULL,_T("The Hello Application")); InitCLR(); } void CMainWindow::InitCLR() { m_nLowwer = 0; m_nUpper = 1000; m_clrLine = RGB(250,0,0); m_nLineWidth = 1; m_fCurrentValue = 83.0; m_clrCurrentLine = RGB(105,220,200); //m_clrCurrentBack = RGB(250,250,225); m_clrCurrentBack = RGB(99,99,99); m_clrCurrentFore = RGB(80,250,230); } void CMainWindow::Draw(CDC* pDC) { CRect rectRgn = m_rctCurrent; COLORREF clrPen = m_clrCurrentLine; COLORREF clrBrush = m_clrCurrentBack; COLORREF clrText = m_clrCurrentFore; /*if (!bRuning) { rectRgn = m_rect; clrPen = m_clrLine; clrBrush = m_clrBack; clrText = m_clrFore; } if (!m_bVariant) m_strCurrentCaption = m_strCaption;*/ rectRgn.NormalizeRect(); CBrush brush(clrText); CBrush *prebrush = pDC->SelectObject(&brush); pDC->FillSolidRect(rectRgn, clrBrush); int top = rectRgn.top+10; int middle = rectRgn.bottom - 40; if ( middle < top ) middle = top; CRect rectPie = CRect(rectRgn.left + 10, top, rectRgn.right - 10, top + 2*(middle-top)); //pDC->Rectangle(rectPie.left,rectPie.top,rectPie.right,rectRgn.bottom-38);; CPoint s = CPoint(rectRgn.right - 10, middle); CPoint e = CPoint(rectRgn.left + 10, middle); INT HorzRes = pDC->GetDeviceCaps(HORZRES); INT VertRes = pDC->GetDeviceCaps(VERTRES); INT VertSize = pDC->GetDeviceCaps(VERTSIZE); INT HorzSize = pDC->GetDeviceCaps(HORZSIZE); m_lAspectN = ((LONG)VertRes * 100) / (LONG)VertSize; m_lAspectD = ((LONG)HorzRes * 100) / (LONG)HorzSize; // 画指针; //CPen pen( PS_SOLID, m_nLineWidth, m_clrLine ); //CPen* pOldPen = pDC->SelectObject(&pen); //pDC->MoveTo(rectPie.CenterPoint()); // 根据外部值,画直线(显示指针位置); //rectPie.DeflateRect(5,5,5,5); //CRgn rgn; //rgn.CreateEllipticRgnIndirect( rectPie ); //float angle = 180-180*(m_fCurrentValue-m_nLowwer)/(m_nUpper-m_nLowwer); //int bLeft = 1; //if ( angle < 90 ) bLeft = -1; //CPoint lastPoint; //int clockRadius = min(m_rect.Width()/2 - 10 , m_rect.Height() - 50) - 10; //lastPoint.x = rectPie.CenterPoint().x + clockRadius*cos(angle/180*PI); //lastPoint.y = rectPie.CenterPoint().y - clockRadius*sin(angle/180*PI) ; // 差了个精度; //lastPoint.y = rectPie.CenterPoint().y - clockRadius*sin(angle/180*PI) + 1; // 根据传参,画直线的终点; //pDC->LineTo(lastPoint); //pDC->SelectObject(pOldPen); // 画边框; pDC->DrawEdge(&rectRgn,BDR_RAISEDOUTER,BF_RECT); rectRgn.DeflateRect(1,1); pDC->DrawEdge(rectRgn, BDR_RAISEDOUTER, BF_RECT); rectRgn.left = rectRgn.left+5; rectRgn.right = rectRgn.right-5; rectRgn.top = rectRgn.top+5; rectRgn.bottom = rectRgn.bottom-35; pDC->DrawEdge(&rectRgn,BDR_SUNKENOUTER,BF_RECT); pDC->SelectObject(prebrush); //pDC->Rectangle(rectRgn); // pDC->SelectObject(pOldPen); // 画表盘弧形刻度值; //DrawFace(pDC); int nRadius[3]; nRadius[0] = rectRgn.Height()/2 - 10; nRadius[1] = nRadius[0] - 60; nRadius[2] = nRadius[1] - 80; pDC->SetWindowExt(rectRgn.Width(),rectRgn.Height()); DrawWatch( pDC, rectRgn, 0, // 最小范围值; 1000, // 最大范围值; m_rect.Width()/10 + m_rect.Height()/10, // 当前范围值; "单位:M", // 量程单位; 180, // 范围弧度; nRadius, // 内弧半径; 10, // 大刻度数; 10); // 小刻度数; //DeleteObject( pen ); DeleteObject( brush ); //DeleteObject( rgn ); } void CMainWindow::DrawFace(CDC* pDC) { INT i; RECT tRect; tagPOINT clockCenter; // 表盘针形起点; m_rect = m_rctCurrent; char c[5] = {0}; int clockRadius = min(m_rect.Width()/2 - 10 , m_rect.Height() - 50); clockCenter.y = m_rect.bottom - 20; clockCenter.x = m_rect.left + m_rect.Width()/2; #if 0 int nSmall = (m_nUpper - m_nLowwer) / 100; int nBig = nSmall / 5; POINT ptStart; POINT ptEnd; pDC->Arc(&m_rect,ptStart,ptEnd); #endif for (i=0; i < 31; i++) { tRect.top = (INT)(((LONG)(CirTab[i].cos) * clockRadius) / CLKSCALE + clockCenter.y - 20); tRect.left = (INT)(((LONG)(CirTab[i].sin) * clockRadius) / CLKSCALE + clockCenter.x); if (i % 5) { tRect.right = tRect.left + 2; tRect.bottom = tRect.top + 2; pDC->FillSolidRect(&tRect, RGB(255,0,0)); } else { tRect.right = tRect.left + 2; tRect.bottom = tRect.top + 2; if((i / 5) == 0) _itoa(m_nLowwer, c , 10); else _itoa((m_nUpper - m_nLowwer) * i / 30, c , 10); pDC->SetTextColor(m_clrFore); // 以下TextOut,文本的输出应该放在弧形刻度内侧;而不是放在中间; // pDC->TextOut(tRect.left-1,tRect.top-2,c,(int)strlen(c)); pDC->TextOut(tRect.left-1,tRect.top-2,c,(int)strlen(c)); } } } void CMainWindow::OnPaint() { CRect rect; GetClientRect(&rect); CPaintDC dc(this); dc.SetBkMode(TRANSPARENT); int nWidth = rect.Width(); int nHeight = rect.Height(); #if 1 m_rect = rect; m_rctCurrent = m_rect; Draw((CDC*)&dc); #endif #if 1 TCHAR szTextOut[256] = {0}; sprintf_s(szTextOut,"当前窗口大小:%d * %d,倍率 = %lf",nWidth,nHeight,(double)nWidth/nHeight); CPen pen(PS_SOLID,1,RGB(105,220,210)); dc.SelectObject(pen); dc.SetTextColor(RGB(105,220,250)); CRect rtShow(rect.left + 20, rect.top + 40,rect.right ,rect.bottom); dc.DrawText(szTextOut, -1, &rtShow, 0); #endif #if 0 dc.SetViewportOrg(nWidth/2,nHeight/2); int nRadius[]= { 220, 160, 90 }; DrawWatch( (CDC *)&dc, rect, -500, // 最小范围值; 500, // 最大范围值; nHeight/10 + nWidth/10, // 当前范围值; "单位:M", // 量程单位; 320, // 范围弧度; nRadius, // 内弧半径; 10, // 大刻度数; 10); // 小刻度数; #endif } // GDI弧度的起始位置跟数学上的不一样,在GDI中,弧度是从X轴负方向(左边),顺时针开始计算的; void CMainWindow::DrawWatch( CDC *pDC, CRect &Wrect, float fMin, // 最小范围值; float fMax, // 最大范围值; const float &fValue, // 当前值; CString strUnit, // 量程单位; const float &fRadian, // 范围弧度大小; int nRadius[3], // 内弧半径; const int &nTable, // 大刻度数; const int &nScale // 小刻度数; ) { if(fMin>fValue) { fMin=fValue; } if(fValue>fMax) { fMax=fValue; } int nWidth,nHeight; //nWidth = nHeight = 200; //nWidth = m_rctCurrent.Width(); //nHeight = m_rctCurrent.Height(); CRect rect = Wrect; //(-nWidth,nHeight,nWidth,-nHeight); nWidth = Wrect.Width(); nHeight = Wrect.Height(); //int nTable = 10; // 大格; //int nScale = 5; // 每小段里面的小格; COLORREF Green(RGB(0,255,0)); COLORREF Blue(RGB(0,0,255)); COLORREF Cyan(RGB(92,92,92)); COLORREF Yellow(RGB(255,255,0)); COLORREF Red(RGB(255,0,0)); COLORREF SkyBlue(RGB(0,128,255)); COLORREF LineColor(RGB(128,0,0)); // 巧克力色; // 张开的弧度; //float fRadian = 60; //// 同心圆半径; //int nRadius[]= //{ // 220, // 160, // 90 //}; // 圆心; //CPoint ptCenter; /*if ( fRadian >180 ) { ptCenter.x = Wrect.left + nWidth/2 ; ptCenter.y = Wrect.top + nHeight/2 ; nRadius[0] = nHeight/2 - 10; nRadius[1] = nRadius[0]*5/6 - 10; nRadius[2] = nRadius[1]*2/7 - 10; } else if( fRadian >= 0 && fRadian <= 180) { ptCenter.x = Wrect.left + nWidth/2 ; ptCenter.y = Wrect.bottom; nRadius[0] = nHeight - 10; nRadius[1] = nRadius[0]*5/6 - 10; nRadius[2] = nRadius[1]*2/7 - 10; }*/ // 圆心; CPoint ptCenter; if ( fRadian > 180 ) { ptCenter.x = rect.left + nWidth/2 ; ptCenter.y = rect.top + nHeight/2 -6 ; if ( nHeight < nWidth) { nRadius[0] = nHeight/2 - 10; }else nRadius[0] = nWidth/2 - 10; nRadius[1] = nRadius[0]*5/6 - 10; nRadius[2] = nRadius[1]*2/7 - 10; } else if( fRadian > 0 && fRadian <= 180) { ptCenter.x = rect.left + nWidth/2 ; ptCenter.y = rect.bottom - 6; if ( fRadian == 180 ) { if ( nHeight < nWidth/2) nRadius[0] = nHeight - 10; else nRadius[0] = nWidth/2 - 10; }else { if ( nHeight < nWidth/2) nRadius[0] = nHeight - 10; else nRadius[0] = nWidth/2 - 10; } nRadius[1] = nRadius[0]*5/6 - 10; nRadius[2] = nRadius[1]*2/7 - 10; } //CPoint ptCenter( 0 , 0 ); // 刻度长度; int nLongScal = 16; int nShortScal = 6; CPen LinePen(PS_SOLID,2,LineColor); // 画笔颜色; pDC->SelectObject(LinePen); // 画3段弧; CRect rtArc1(ptCenter.x - nRadius[0], ptCenter.y - nRadius[0], ptCenter.x - nRadius[0] + 2*nRadius[0] + 1, ptCenter.y - nRadius[0] + 2*nRadius[0] + 1); CRect rtArc2(ptCenter.x - nRadius[1], ptCenter.y - nRadius[1], ptCenter.x - nRadius[1] + 2*nRadius[1] + 1, ptCenter.y - nRadius[1] + 2*nRadius[1] + 1); CRect rtArc3(ptCenter.x - nRadius[2], ptCenter.y - nRadius[2], ptCenter.x - nRadius[2] + 2*nRadius[2] + 1, ptCenter.y - nRadius[2] + 2*nRadius[2] + 1); CPoint ptArcStart,ptArcEnd; double rad = ((180-fRadian)/2)/180*PI ; ptArcEnd.x = ptCenter.x - nRadius[0]*cos(rad); ptArcEnd.y = ptCenter.y - nRadius[0]*sin(rad); rad = ( (180-fRadian)/2 + fRadian )/180*PI ; ptArcStart.x = ptCenter.x - nRadius[0]*cos(rad); ptArcStart.y = ptCenter.y - nRadius[0]*sin(rad); // 画弧,是从起点逆时针到终点,所以要交换点位置; pDC->Arc(rtArc1,ptArcStart,ptArcEnd); pDC->Arc(rtArc2,ptArcStart,ptArcEnd); CPen LinePen1(PS_SOLID,1,LineColor); // 画笔颜色; pDC->SelectObject(LinePen1); pDC->Arc(rtArc3,ptArcStart,ptArcEnd); // 画 刻度(分段); for( int i = 0; i <= nTable*nScale; i++ ) // 总刻度; { CPoint pt0,pt1; double f0 = ( (180-fRadian)/2 + fRadian/(nTable*nScale)*i )/180*PI; // 刻度数对应的弧度; pt1.x = ptCenter.x + nRadius[1]*cos(f0); pt1.y = ptCenter.y - nRadius[1]*sin(f0); if( i%nTable == 0 ) { pt0.x = ptCenter.x + (nRadius[1]+nLongScal)*cos(f0); pt0.y = ptCenter.y - (nRadius[1]+nLongScal)*sin(f0); CString str; str.Format(_T("%.0f"),fMax-(fMax-fMin)/(nTable*nScale)*i); // 获取文本所占的大小; // 还是不标准位置,应该还有个系数跟弧度有关; CRect textrc; // 要使得矩形中心点 在直线 pt0~pt1上; CSize ftszie = pDC->GetTextExtent(str); // 矩形对角线长度/2; double dRtLength = sqrt((pow((float)ftszie.cx,2) + pow((float)ftszie.cy,2)))/2; CPoint ptText; ptText.x = ptCenter.x + (nRadius[1] + nLongScal + dRtLength)*cos(f0); ptText.y = ptCenter.y - (nRadius[1] + nLongScal + dRtLength)*sin(f0); textrc.left = ptText.x - ftszie.cx/2; textrc.top = ptText.y - ftszie.cy/2; textrc.right = ptText.x + ftszie.cx/2; textrc.bottom = ptText.y + ftszie.cy/2 ; pDC->SetBkColor(Green); pDC->SetTextColor(Blue); pDC->DrawText(str, &textrc,0); CPoint pt2,pt3; int nGap = 5; pt3.x = ptCenter.x +(nRadius[0]+0)*cos(f0); pt3.y = ptCenter.y -(nRadius[0]+0)*sin(f0); pt2.x = ptCenter.x +(nRadius[0]-nGap)*cos(f0); pt2.y = ptCenter.y -(nRadius[0]-nGap)*sin(f0); CPen BigPen(PS_SOLID,2,Yellow); // 画笔颜色; pDC->SelectObject(BigPen); pDC->MoveTo(pt2); pDC->LineTo(pt3); pDC->MoveTo(pt0); pDC->LineTo(pt1); DeleteObject(BigPen); } else { pt0.x = ptCenter.x + (nRadius[1]+nShortScal)*cos(f0); pt0.y = ptCenter.y - (nRadius[1]+nShortScal)*sin(f0); CPen SmallPen(PS_SOLID,1,Blue); // 画笔颜色; pDC->SelectObject(SmallPen); pDC->MoveTo(pt0); pDC->LineTo(pt1); DeleteObject(SmallPen); } } CFont font; font.CreatePointFont(150,_T("Times New Roman")); pDC->SelectObject(font); // 输出文本:单位; CRect UnitRc; CSize ftsize = pDC->GetTextExtent(strUnit); UnitRc.left = ptCenter.x - ftsize.cx/2; //UnitRc.top = ptCenter.y - (nRadius[0]-nRadius[1]+nRadius[2] + ftsize.cy/2); UnitRc.top = ptCenter.y - (nRadius[1]-nRadius[2])/2 - nRadius[2] - ftsize.cy/2; // 使居中; UnitRc.right = UnitRc.left + ftsize.cx; UnitRc.bottom = UnitRc.top + ftsize.cy; pDC->SetTextColor(Red); pDC->DrawText(strUnit,&UnitRc,0); // 输出文本:当前数据; // 要保持在圆心上方; CRect DataRc; CString strData; strData.Format(_T("当前值:%.0f"),fValue); ftsize = pDC->GetTextExtent(strData); DataRc.left = ptCenter.x - ftsize.cx/2; //DataRc.top = ptCenter.y - (nRadius[2]-nLongScal); DataRc.top = ptCenter.y - (nRadius[2]/2 - nLongScal); // 使居中; DataRc.right = DataRc.left + ftsize.cx; DataRc.bottom = DataRc.top + ftsize.cy; pDC->DrawText(strData,&DataRc,0); // 画指针; CPen PointPen(PS_SOLID,2,Green); pDC->SelectObject(PointPen); CPoint pt0,pt1; double f0 = ((180-fRadian)/2+fRadian/(fMax-fMin)*(-fValue+fMax))/180*PI; pt0.x = ptCenter.x + (nRadius[2]*cos(f0)); pt0.y = ptCenter.y - (nRadius[2]*sin(f0)); pt1.x = ptCenter.x + ((nRadius[1]+nShortScal/2)*cos(f0)); pt1.y = ptCenter.y - ((nRadius[1]+nShortScal/2)*sin(f0)); pDC->MoveTo(pt0); pDC->LineTo(pt1); } int CMyApp::ExitInstance() { // TODO: 在此添加专用代码和/或调用基类 Gdiplus::GdiplusShutdown(gdiplusToken); return CWinApp::ExitInstance(); }