工控軟體圖形介面-控制項實現(溫度計控制項)(zz)

來源:互聯網
上載者:User

url:http://dev.firnow.com/course/3_program/c++/cppsl/2008227/101906.html

儀錶控制項,溫度計控制項,LED控制項等是工業組態軟體中最常用的人際互動控制項,能夠提供一種更友好的介面展示方法。而溫度計控制項其實綜合起來就是一個水銀柱繪製和一個刻度的繪製的過程。由於考慮到重新整理可能對介面的產生的影響,我們採用雙緩衝技術實現。
    通過VC的ClassWizard建立一個溫度計顯示控制項類,繼承CStatic。我們映射WM_PAINT訊息,在這裡完成溫度計的各種繪製工作就可以了。這個和前面的儀錶控制項繪製原理是一致的。唯一的區別就是在介面展示不同的繪製效果而已。
void CThermoMeter::OnPaint()
{
    CPaintDC dc(this);
    // 獲得控制項地區
    GetClientRect (&m_rectCtrl);
    CMemDC memDC(&dc, &m_rectCtrl);
    //繪製儀錶盤
    if (m_dcMeterPlate.GetSafeHdc() == NULL || (m_bitmapMeterPlate.m_hObject == NULL))
    {
        m_dcMeterPlate.CreateCompatibleDC(&dc);
        m_bitmapMeterPlate.CreateCompatibleBitmap(&dc, m_rectCtrl.Width(),                                                                                     m_rectCtrl.Height()) ;
        m_pbitmapOldMeterPlate = m_dcMeterPlate.SelectObject(&m_bitmapMeterPlate) ;
        DrawMeterBackground(&m_dcMeterPlate, m_rectCtrl);
    }
    memDC.BitBlt(0, 0, m_rectCtrl.Width(), m_rectCtrl.Height(),
                       &m_dcMeterPlate, 0, 0, SRCCOPY);
    DrawScale(&memDC);
    m_ctrlUnit.Draw(&memDC);
}
由於在雙緩衝繪製過程中,我們的背景可以認為是不變的,所以在程式啟動並執行資料重新整理過程中,我們可以在初始化的時候在記憶體中間完成這部分的繪製工作,然後調用的時候將他Bitbtn到介面就可以了。重新整理資料的時候每次調用以前繪製的成果BitBtn(貼)到介面上,這樣就可以省掉了重新整理的時候給人的閃爍的感覺了。然後完成水銀柱的繪製以及即時值的繪製。介面繪製為這個控制項的核心部分了。
//繪製儀錶背景
void CThermoMeter::DrawMeterBackground(CDC *pDC, CRect &rect)
{
    CString strScale;
    CFont fScaleFont, *pOldFont;
    CPen penThick, penThin, penShadow, penScale, *pOldPen;
    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->SelectObject(pOldBrush);
    m_brushBack.DeleteObject();
    //繪製邊框的立體效果   
    penThick.CreatePen(PS_SOLID, 1, RGB(172, 168, 153));
    penThin.CreatePen(PS_SOLID, 1, RGB(113, 111, 110));
    penShadow.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
    pOldPen = (CPen *)pDC->SelectObject(&penShadow);
    pDC->MoveTo(rect.left, rect.top);
    pDC->LineTo(rect.right - 1, rect.top);
    pDC->MoveTo(rect.left + 1, rect.top + 1);
    pDC->LineTo(rect.right - 2, rect.top + 1);
    pDC->MoveTo(rect.left, rect.top);
    pDC->LineTo(rect.left, rect.bottom - 1);
    pDC->MoveTo(rect.left + 1, rect.top + 1);
    pDC->LineTo(rect.left + 1, rect.bottom - 2);
    pDC->SelectObject(&penThick);
    pDC->MoveTo(rect.left + 1, rect.bottom - 1);
    pDC->LineTo(rect.right - 1, rect.bottom - 1);
    pDC->LineTo(rect.right - 1, rect.top + 1);
    pDC->SelectObject(&penThin);
    pDC->MoveTo(rect.left, rect.bottom);
    pDC->LineTo(rect.right, rect.bottom);
    pDC->LineTo(rect.right, rect.top);
    pDC->SelectObject(pOldPen);   
    //繪製指標顯示地區
    CRect rectScale;
    rectScale.SetRect(rect.left + rect.Width() / 4,
                      rect.top + rect.Height() / 12,
                      rect.left + rect.Width() / 4 + rect.Width() / 10,
                      rect.bottom - rect.Height() / 12);
    pBackBrush.CreateSolidBrush(RGB(128, 0, 0));
    pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush);
    pDC->FillRect(&rectScale, &pBackBrush);
    pDC->SelectObject(pOldBrush);
    pBackBrush.DeleteObject();
    //繪製指標地區立體效果
    pDC->SelectObject(&penThick);
    pDC->MoveTo(rectScale.left, rectScale.bottom);
    pDC->LineTo(rectScale.left, rectScale.top);
    pDC->LineTo(rectScale.right, rectScale.top);
    pDC->SelectObject(&penThin);
    pDC->MoveTo(rectScale.left + 1, rectScale.bottom);
    pDC->LineTo(rectScale.left + 1, rectScale.top + 1);
    pDC->LineTo(rectScale.right, rectScale.top + 1);
    pDC->SelectObject(&penShadow);
    pDC->MoveTo(rectScale.right - 1, rectScale.top + 1);
    pDC->LineTo(rectScale.right - 1, rectScale.bottom - 1);
    pDC->LineTo(rectScale.left + 1, rectScale.bottom - 1);
    pDC->MoveTo(rectScale.right, rectScale.top);
    pDC->LineTo(rectScale.right, rectScale.bottom);
    pDC->LineTo(rectScale.left, rectScale.bottom);
    m_rectScale = rectScale;
    m_rectScale.DeflateRect(2, 2, 2, 2);
    //繪製刻度
    fScaleFont.CreateFont(rect.Height() / 8, 0, 
        0, 
        0, 
        FW_NORMAL,
        FALSE,
        FALSE,
        FALSE,
        DEFAULT_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY,
        DEFAULT_PITCH | FF_DONTCARE,
        "System"); 
    pOldFont = (CFont *)pDC->SelectObject(&fScaleFont);
    penScale.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
    for (int i=0; i<m_nTicks+1; i++)
    {
        CPoint ptStartTick, ptEndTick;
        int nTickDisc = rect.Height() * 5 * i / (6 * m_nTicks);
        ptStartTick.x = rect.left + rect.Width() * 3 / 7;
        ptStartTick.y = rect.bottom - rect.Height() / 12 - nTickDisc;
        ptEndTick.x = rect.left + rect.Width() * 3 / 5;
        ptEndTick.y = rect.bottom - rect.Height() / 12 - nTickDisc;
        pDC->SelectObject(penScale);
        pDC->MoveTo(ptStartTick);
        pDC->LineTo(ptEndTick);
        //繪製立體感覺
        CPoint ptShadowStartTick, ptShadowEndTick;
        ptShadowStartTick = ptStartTick;
        ptShadowEndTick = ptEndTick;
        ptShadowStartTick.y--;
        ptShadowEndTick.y--;
        pDC->SelectObject(penShadow);
        pDC->MoveTo(ptShadowStartTick);
        pDC->LineTo(ptShadowEndTick);       
        //繪製子刻度
        for (int j=0; j<m_nSubTicks+1; j++)
        {
            if (i < m_nTicks)
            {
                CPoint ptSubStartTick, ptSubEndTick;
                int nSubTickDisc = (rect.Height() * 5 / (6 * m_nTicks)) * j / m_nSubTicks;
                ptSubStartTick.x = ptStartTick.x;
                ptSubStartTick.y = ptStartTick.y - nSubTickDisc;
                ptSubEndTick.x = ptSubStartTick.x + (ptEndTick.x - ptSubStartTick.x) / 2;
                ptSubEndTick.y = ptSubStartTick.y;
                pDC->SelectObject(penScale);
                pDC->MoveTo(ptSubStartTick);
                pDC->LineTo(ptSubEndTick);
                CPoint ptShadowSubStartTick, ptShadowSubEndTick;
                ptShadowSubStartTick = ptSubStartTick;
                ptShadowSubEndTick = ptSubEndTick;
                ptShadowSubStartTick.y--;
                ptShadowSubEndTick.y--;
                pDC->SelectObject(penShadow);
                pDC->MoveTo(ptShadowSubStartTick);
                pDC->LineTo(ptShadowSubEndTick);
            }
        }
        //繪製刻度
        CRect ptScale;
        pDC->SetBkMode(TRANSPARENT);
        strScale.Format("%.0f", (m_dMaxValue - m_dMinValue) * i / m_nTicks);
        CSize size = pDC->GetTextExtent(strScale);
        pDC->SetTextColor(RGB(255, 255, 255));
        ptScale.SetRect(rect.left + rect.Width() * 2 / 3,
                        ptStartTick.y - size.cy / 2,
                        rect.right,
                        ptStartTick.y + size.cy / 2);
        pDC->DrawText(strScale, ptScale, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
        pDC->SetTextColor(RGB(0, 0, 0));
        ptScale.DeflateRect(-1, -1, 1, 1);
        pDC->DrawText(strScale, ptScale, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
    }
    pDC->SelectObject(pOldPen);
    pDC->SelectObject(pOldBrush);
    pDC->SelectObject(pOldFont);
    penThick.DeleteObject();
    penThin.DeleteObject();
    penShadow.DeleteObject();
    m_brushBack.DeleteObject();
    pBackBrush.DeleteObject();
    fScaleFont.DeleteObject();
    penScale.DeleteObject();
}
下面是溫度計水銀柱的繪製。
void CThermoMeter::DrawScale(CDC *pDC)
{
    if (m_dCurrentValue > m_dMaxValue)
    {
        m_dCurrentValue = m_dMaxValue;
    }
    else if (m_dCurrentValue < m_dMinValue)
    {
        m_dCurrentValue = m_dMinValue;
    }
    CRect rectScale;
    double yScale = (m_dCurrentValue - m_dMinValue) / (m_dMaxValue - m_dMinValue);
    rectScale.SetRect(m_rectScale.left,
                      m_rectScale.bottom - int(yScale * (m_rectScale.Height())),
                      m_rectScale.right,
                      m_rectScale.bottom);
    CBrush pBackBrush, *pOldBrush;
    pBackBrush.CreateSolidBrush(RGB(255, 0, 0));
    pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush);
    pDC->FillRect(&rectScale, &pBackBrush);
    pDC->SelectObject(pOldBrush);
    pBackBrush.DeleteObject();
    m_ctrlUnit.SetRect(GetUnitRect());
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.