工控軟體圖形介面-控制項實現(圓形儀錶控制項三)(zz)

來源:互聯網
上載者:User

介紹
在工業控制系統開發過程中,圖形顯示方面佔有著很重要的作用。比起很多專用的組態軟體,他們有著強大的在圖形系統,能夠組態出來非常漂亮的系統。現在的很多的工業圖形開發包都需要支付費用,很多漂亮的控制項比如儀錶等只能看圖興歎了。前些天一個朋友做一個泵站的監控系統,由於缺少相關的控制項,在研究了該類控制項的編程方法上,借鑒網路上的一些編程資料,完成了一些可用於工業控制系統開發使用的控制項。

本文
前面的兩篇文章中我已經用執行個體介紹了如何利用雙緩衝技術編寫圓盤儀錶的方法。具體見
    工控軟體圖形介面-控制項實現(圓形儀錶控制項) http://www.vchelp.net/itbookreview/view_paper.asp?paper_id=1671
    工控軟體圖形介面-控制項實現(圓形儀錶控制項二) http://www.vchelp.net/itbookreview/view_paper.asp?paper_id=1672
    實際儀錶的編寫原理可以大致差不多,區別就是編寫背景或者指標或者顯示即時值的時候採用的不同方法而已。而在工業控製程序中,如果採用了多種不同的模擬儀錶來實現現場的類比,將會在人機介面方面更加的友好。這裡繼續在前面的基礎上編寫一種新型的儀錶,並應用到工控現場的儀錶。
    我們還是按照編寫的步驟,建立一個整合CStatic的儀錶類。然後出發WM_PAINT等訊息。然後在OnPaint中間完成儀錶背景,儀錶指標,儀錶即時值的顯示工作。在背景編寫,指標和文字顯示的時候,我們採用疊加的方法。圖形疊加或者文字疊加方法其實很簡單,在上篇文章已經有介紹,即是我們利用在相同的地區或者位移量地區進行相同內容的繪製,繪製時候採用不同顏色,由於繪圖的先後順序,我們可以產生視覺上的立體疊加效果,具體實現見 工控軟體圖形介面-控制項實現(圓形儀錶控制項二) http://www.vchelp.net/itbookreview/view_paper.asp?paper_id=1672
相關核心代碼如下:
繪製儀錶背景
//繪製儀錶背景
void CPanelMeter::DrawMeterBackground(CDC *pDC, CRect &rect)
{
    CBrush m_brushBack, pBackBrush, *pOldBrush;
    pDC->SetBkColor(m_BackColor);
    m_brushBack.CreateSolidBrush(m_BackColor);
    pOldBrush = (CBrush *)pDC->SelectObject(&m_brushBack);   
    pDC->FillRect(rect, &m_brushBack);   //繪製背景
    pDC->Rectangle(rect);                //繪製一個邊框
    pDC->SelectObject(pOldBrush);
    m_brushBack.DeleteObject();
    int yHalf = rect.bottom - 8;
    float fa = (float)rect.Width() / 2;
    float fb = (float)rect.Height() - 8;
    CFont fScaleFont;
    fScaleFont.CreateFont(10, 12, 
        0, 
        0, 
        FW_NORMAL,
        FALSE,
        FALSE,
        FALSE,
        DEFAULT_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY,
        DEFAULT_PITCH | FF_DONTCARE,
        "Arial"); 
    if (m_dValidValueMin >= 0) 
    {
        CBrush brshGreen;
        CBrush brshRed;
        brshGreen.CreateSolidBrush(RGB(0, 192, 0));
        brshRed.CreateSolidBrush(RGB(230, 100, 100));
        float fStartAngle = (float)(m_dValidValueMin - m_dMinValue) / (float)(m_dMaxValue - m_dMinValue) * 3.14f;
        float fEndAngle   = (float)(m_dValidValueMax - m_dMinValue) / (float)(m_dMaxValue - m_dMinValue) * 3.14f;
        pDC->MoveTo(rect.left, yHalf);
        pDC->LineTo(rect.left + 20, yHalf);
        pDC->MoveTo(rect.right - 1, yHalf);
        pDC->LineTo(rect.right - 22, yHalf);
        pDC->MoveTo(rect.left, yHalf);
        for (float f = 0; f <= 3.14; f += 0.01f)
        {
            pDC->LineTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top);
        }
        pDC->MoveTo(rect.left + 20, yHalf);
        for (f = 0; f <= 3.14; f += 0.01f)
        {
            pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(f)) + rect.left, yHalf - (int)((fb - 20) * sin(f)) + rect.top);
        }
        CBrush *pOldBrush = pDC->SelectObject(&brshRed);
        pDC->FloodFill(rect.left + 10, yHalf - 10, RGB(0, 0, 0));
        fStartAngle *= 100;
        fStartAngle = (float)((int)fStartAngle) / 100;
        fEndAngle *= 100;
        fEndAngle = (float)((int)fEndAngle) / 100;
        pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(fStartAngle)) + rect.left, yHalf - (int)(fb * sin(fStartAngle)) + rect.top);
        pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(fStartAngle)) + rect.left, yHalf - (int)((fb - 20) * sin(fStartAngle)) + rect.top);
        pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(fEndAngle)) + rect.left, yHalf - (int)(fb * sin(fEndAngle)) + rect.top);
        pDC->LineTo(rect.Width() / 2 - (int)((fa - 20) * cos(fEndAngle)) + rect.left, yHalf - (int)((fb - 20) * sin(fEndAngle)) + rect.top);
        pDC->SelectObject(brshGreen);
        if (fStartAngle > 0 && fEndAngle < 3.14)
        {
            pDC->FloodFill(rect.Width() / 2 - (int)((fa - 5) * cos((fStartAngle + fEndAngle) / 2)) + rect.left, yHalf - (int)((fb - 5) * sin((fStartAngle + fEndAngle) / 2)) + rect.top, RGB(0,0,0));
        }
        pDC->SelectObject(pOldBrush);
    }
    CPen pen;
    pen.CreatePen(PS_SOLID, 3, RGB(255,255,255));
    CPen *pOldPen = pDC->SelectObject(&pen);
    CFont *pOldFont = pDC->SelectObject(&fScaleFont);
    pDC->SetBkMode(TRANSPARENT);
    fa -= 10;
    fb -= 10;
    pDC->MoveTo(rect.left + 10, yHalf);
    for (float f = 0; f <= 3.14; f += 0.01f)
    {
        pDC->LineTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top);
    }
    float fBigStep = 3.14f / ((float)(m_dMaxValue - m_dMinValue) / (float)m_dInterval) / 4;
    int nDiv = 0;
    int nScale = (int)m_dMinValue;
    for (f = 0; f <= 3.15; f += fBigStep)
    {
        pDC->MoveTo(rect.Width() / 2 - (int)(fa * cos(f)) + rect.left, yHalf - (int)(fb * sin(f)) + rect.top);
        if (nDiv == 0)
        {
            pDC->LineTo(rect.Width() / 2 - (int)((fa - 15) * cos(f)) + rect.left, yHalf - (int)((fb - 15) * sin(f)) + rect.top);
            CString str;
            str.Format("%d", nScale);
            nScale += (int)m_dInterval;
            CSize size = pDC->GetOutputTextExtent(str);
            pDC->SetTextColor(RGB(0,0,0));
            pDC->TextOut(rect.Width() / 2 - (int)((fa - 33) * cos(f)) + rect.left - size.cx / 2 + 1, yHalf - (int)((fb - 33) * sin(f)) + rect.top - size.cy / 2 + 1, str);
            pDC->SetTextColor(RGB(255, 255, 255));
            pDC->TextOut(rect.Width() / 2 - (int)((fa - 33) * cos(f)) + rect.left - size.cx / 2, yHalf - (int)((fb - 33) * sin(f)) + rect.top - size.cy / 2, str);
            nDiv++;
        }
        else
        {
            pDC->LineTo(rect.Width() / 2 - (int)((fa - 10) * cos(f)) + rect.left, yHalf - (int)((fb - 10) * sin(f)) + rect.top);
            nDiv++;
            if (nDiv == 4)
            {
                nDiv = 0;
            }
        }       
    }   
    pDC->SelectObject(pOldFont);
    fScaleFont.DeleteObject();
    CPoint m_ptMeterCenter;
    m_ptMeterCenter.x = rect.left + rect.Width() / 2;
    m_ptMeterCenter.y = rect.bottom;
    int nRadiusFrame = rect.Height();
    CFont pUnitFont;
    LOGFONT lf;
    lf.lfEscapement = 0;
    lf.lfItalic = NULL;
    lf.lfUnderline = NULL;
    lf.lfStrikeOut = NULL;
    lf.lfCharSet = DEFAULT_CHARSET;
    lf.lfHeight = nRadiusFrame / 4;
    strcpy(lf.lfFaceName, "隸書");
    pUnitFont.CreateFontIndirect(&lf);
    pOldFont = (CFont *)pDC->SelectObject(&pUnitFont);   
    pDC->SetBkMode(TRANSPARENT);
    pDC->SetTextColor(RGB(0, 0, 0));
    CRect rectUnits(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f + 2),
                    int(m_ptMeterCenter.y - nRadiusFrame * 0.70f + 2),
                    int(m_ptMeterCenter.x + nRadiusFrame * 0.30f + 2),
                    int(m_ptMeterCenter.y - nRadiusFrame * 0.20f + 2));
    pDC->DrawText(m_strUnits, &rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
    pDC->SetTextColor(RGB( 255, 255, 255));
    rectUnits.SetRect(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f),
                      int(m_ptMeterCenter.y - nRadiusFrame * 0.70f),
                      int(m_ptMeterCenter.x + nRadiusFrame * 0.30f),
                      int(m_ptMeterCenter.y - nRadiusFrame * 0.20f));
    pDC->DrawText(m_strUnits, rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
    pDC->SelectObject(pOldPen);
    pDC->SelectObject(pOldFont);
    pUnitFont.DeleteObject();
}
繪製儀錶指標,採用疊加立體效果的處理技術
void CPanelMeter::DrawNeedle(CDC *pDC, CRect &rect)
{
    if (m_dCurrentValue > m_dMaxValue)
    {
        m_dCurrentValue = m_dMaxValue;
    }
    else if (m_dCurrentValue < m_dMinValue)
    {
        m_dCurrentValue = m_dMinValue;
    } 
    double dAngle = (m_dCurrentValue - m_dMinValue) / (m_dMaxValue - m_dMinValue) * 3.14f;
    float fa = (float)rect.Width() / 2;
    float fb = (float)rect.Height() - 8;
    CBrush brshWhite;
    CBrush brshShadow;
    brshWhite.CreateSolidBrush(RGB(255, 255, 255));
    brshShadow.CreateSolidBrush(RGB(0, 0, 0));
    CBrush *pOldBrush = pDC->SelectObject(&brshShadow);
    pDC->Ellipse(rect.Width() / 2 - 9 + rect.left, rect.Height() - 20 + rect.top, rect.Width() / 2 + 11 + rect.left, rect.Height() + rect.top);
    pDC->SelectObject(&brshWhite);
    pDC->Ellipse(rect.Width() / 2 - 10 + rect.left, rect.Height() - 21 + rect.top, rect.Width() / 2 + 10 + rect.left, rect.Height() - 1 + rect.top);
    pDC->SelectObject(pOldBrush);
    CPen penThick;
    CPen penThin;
    CPen penShadow;
    penThick.CreatePen(PS_SOLID, 5, RGB(255, 100, 50));
    penThin.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
    penShadow.CreatePen(PS_SOLID, 5, RGB(0, 0, 0));
    CPen *pOldPen = pDC->SelectObject(&penShadow);
    pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left + 1, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top + 1);
    pDC->LineTo(rect.Width() / 2 + rect.left + 1, rect.Height() - 11 + rect.top + 1);
    pDC->SelectObject(&penThick);
    pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top);
    pDC->LineTo(rect.Width() / 2 + rect.left, rect.Height() - 11 + rect.top);
    pDC->SelectObject(&penThin);
    pDC->MoveTo(rect.Width() / 2 - (int)((fa - 8) * cos(dAngle)) + rect.left, rect.Height() - 11 - (int)((fb - 8) * sin(dAngle)) + rect.top);
    pDC->LineTo(rect.Width() / 2 + rect.left, rect.Height() - 11 + rect.top);
    pDC->SelectObject(pOldPen);
}
繪製即時值,同樣採用疊加技術
void CPanelMeter::DrawValue(CDC *pDC, CRect &rect)
{
    char strCurrentValue[10];
    memset(strCurrentValue, 0, sizeof(strCurrentValue));
    sprintf(strCurrentValue, "%.2f", m_dCurrentValue);
    CPoint m_ptMeterCenter;
    m_ptMeterCenter.x = rect.left + rect.Width() / 2;
    m_ptMeterCenter.y = rect.bottom;
    int nRadiusFrame = rect.Height();
    CFont pUnitFont, *pOldFont;
    LOGFONT lf;
    lf.lfEscapement = 0;
    lf.lfItalic = NULL;
    lf.lfUnderline = NULL;
    lf.lfStrikeOut = NULL;
    lf.lfCharSet = DEFAULT_CHARSET;
    lf.lfHeight = nRadiusFrame / 6;
    strcpy(lf.lfFaceName, "Arial");
    pUnitFont.CreateFontIndirect(&lf);
    pOldFont = (CFont *)pDC->SelectObject(&pUnitFont);   
    pDC->SetBkMode(TRANSPARENT);
    pDC->SetTextColor(RGB(0, 0, 0));
    CRect rectUnits(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f + 2),
                    int(m_ptMeterCenter.y - nRadiusFrame * 0.40f + 2),
                    int(m_ptMeterCenter.x + nRadiusFrame * 0.30f + 2),
                    int(m_ptMeterCenter.y - nRadiusFrame * 0.10f + 2));
    pDC->DrawText(strCurrentValue, &rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
    pDC->SetTextColor(RGB( 255, 255, 255));
    rectUnits.SetRect(int(m_ptMeterCenter.x - nRadiusFrame * 0.30f),
                      int(m_ptMeterCenter.y - nRadiusFrame * 0.40f),
                      int(m_ptMeterCenter.x + nRadiusFrame * 0.30f),
                      int(m_ptMeterCenter.y - nRadiusFrame * 0.10f));
    pDC->DrawText(strCurrentValue, rectUnits, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
    pDC->SelectObject(pOldFont);
    pUnitFont.DeleteObject();
}
至此,基本繪製工作完成,我們添加一些介面以便能在程式中進行程式參數的改變。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.