www.gusucode.com > 一个支持各种交叉等形状工业控制管道控件 > 一个支持各种交叉等形状工业控制管道控件/testPipe2/PipeCtrl.cpp
/*********************************************************************** * Copyright (c) 2007 * All rights reserved.* * ATTRIBUTE: 一种管道的控件,用于面板管道信息显示,模拟现场环境等 * FILE NAME: PipeCtrl.cpp * FILE ID: PIPECTRL-CPP * ABSTRACT: 工业组态控制系统控制处理专用 * CURRENT VERSION: V1.0 * AUTHOR: 戚高 * CONTECT: successq_g@163.com * BUILD DATA: 09/12/2007 * COMPLETION DATE: 09/12/2007 * PRE-VERSION: NONE * PRE-AUTHOR: NONE * PRE-COMPLETION DATE: * NOTE: 未经授权请不要作为商业用途,或者如果您要作为商业 用途,请联系作者 ***********************************************************************/ #include "stdafx.h" #include "PipeCtrl.h" //----------------------------------------------------- CPipeCtrl::CPipeCtrl() { m_nShadowBeginColor = RGB( 150, 150, 150); m_nShadowEndColor = RGB( 20, 20, 20); m_nWidth = 30; m_enumFace = PF_HORIZONTAL; m_nBackColor[0] = RGB( 0, 0, 0); m_nBackColor[1] = RGB( 75, 75, 75); m_nBackColor[2] = RGB( 128, 128, 128); m_nBackColor[3] = RGB( 192, 192, 192); m_nBackColor[4] = RGB( 220, 220, 220); m_nBackColor[5] = RGB( 255, 255, 255); } CPipeCtrl::~CPipeCtrl() { } BEGIN_MESSAGE_MAP(CPipeCtrl, CStatic) //{{AFX_MSG_MAP(CPipeCtrl) ON_WM_PAINT() ON_WM_ERASEBKGND() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CPipeCtrl::PreSubclassWindow() { CStatic::PreSubclassWindow(); SetBackTransparent(this); } void CPipeCtrl::SetPipeWidth(const int nWidth) { CRect rect; GetClientRect(&rect); if (rect.Width() < nWidth) { m_nWidth = rect.Width(); } else { m_nWidth = nWidth; } Invalidate(); } void CPipeCtrl::SetItemFace(const PIPEFACE enumFace) { m_enumFace = enumFace; Invalidate(); } void CPipeCtrl::OnPaint() { CPaintDC dc(this); RECT rcClient; GetClientRect(&rcClient); switch (m_enumFace) { case PF_HORIZONTAL: DrawHorizontal(&dc, rcClient); break; case PF_VERTICAL: DrawVertical(&dc, rcClient); break; case PF_CORNER_LEFT_TOP: DrawCornerLeftTop(&dc, rcClient); break; case PF_CORNER_RIGHT_TOP: DrawCornerRightTop(&dc, rcClient); break; case PF_CORNER_RIGHT_BOTTOM: DrawCornerRightBottom(&dc, rcClient); break; case PF_CORNER_LEFT_BOTTOM: DrawCornerLeftBottom(&dc, rcClient); break; case PF_CROSS_CENTER: DrawCrossCenter(&dc, rcClient); break; case PF_CROSS_TOP: DrawCrossTop(&dc, rcClient); break; case PF_CROSS_RIGHT: DrawCrossRight(&dc, rcClient); break; case PF_CROSS_BOTTOM: DrawCrossBottom(&dc, rcClient); break; case PF_CROSS_LEFT: DrawCrossLeft(&dc, rcClient); break; } } //用渐变的方法进行填充,不过这里效果不明显,慎重采用这个方法 void CPipeCtrl::DrawGradient(HDC pDC, const RECT &rectClient, COLORREF nShadowBeginColor, COLORREF nShadowEndColor) { RECT rectFill; //显示区域 float fStep; //每一步的幅宽 HBRUSH hBrush; //显示的颜色画刷 int nRed = 0, nGreen = 0, nBlue = 0; float fRefStep = 0.0f, fGreenStep =0.0f, fBlueStep = 0.0f; //得到不同颜色并相减,返回颜色之间的最大差值 nRed = (GetRValue(nShadowEndColor) - GetRValue(nShadowBeginColor)); nGreen = (GetGValue(nShadowEndColor) - GetGValue(nShadowBeginColor)); nBlue = (GetBValue(nShadowEndColor) - GetBValue(nShadowBeginColor)); //使进程条显示的总数 等于最大的颜色差值 int nSteps = max(abs(nRed), max(abs(nGreen), abs(nBlue))); //确定每一颜色填充多大的矩形区域 //以下两种计算步长方式均成立,视个人喜好而定 fStep = (float)m_nWidth / (float)(nSteps * 2); //设置每一颜色填充的步数 fRefStep = nRed / (float)nSteps; fGreenStep = nGreen / (float)nSteps; fBlueStep = nBlue / (float)nSteps; nRed = GetRValue(nShadowBeginColor); nGreen = GetGValue(nShadowBeginColor); nBlue = GetBValue(nShadowBeginColor); //绘制颜色渐变的进程条 for (int nOnBand=0; nOnBand<nSteps; nOnBand++) { //本质为使用一个一个的小RECT填充客户区,而每次填充使用不同的颜色(BRUSH),从而达到渐变的效果 SetRect(&rectFill, 0, (int)(nOnBand * fStep) + rectClient.top, rectClient.right + 1, (int)((nOnBand + 1) * fStep) + rectClient.top); hBrush = CreateSolidBrush(RGB(nRed + fRefStep * nOnBand, nGreen + fGreenStep * nOnBand, nBlue + fBlueStep * nOnBand)); HBRUSH oldBrush = (HBRUSH)::SelectObject(pDC, hBrush); FillRect(pDC, &rectFill , hBrush); ::SelectObject(pDC, oldBrush); DeleteObject(hBrush); } } void CPipeCtrl::DrawHorizontal(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); SetRect(&rcSect, rectClient.left, rectClient.top + i * nSectWidth, rectClient.right, rectClient.top + (i + 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawVertical(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); SetRect(&rcSect, rectClient.left + i * nSectWidth, rectClient.top, rectClient.left + (i + 1) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCornerLeftTop(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //绘制横向 SetRect(&rcSect, rectClient.left + i * nSectWidth, rectClient.top + i * nSectWidth, rectClient.right, rectClient.top + (i + 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); //绘制竖向 SetRect(&rcSect, rectClient.left + i * nSectWidth, rectClient.top + i * nSectWidth, rectClient.left + (i + 1) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCornerRightBottom(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //绘制横向 SetRect(&rcSect, rectClient.left, rectClient.bottom - (SECTCOUNT - i) * nSectWidth, rectClient.right - (SECTCOUNT - i) * nSectWidth, rectClient.bottom - (SECTCOUNT - i - 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); //绘制竖向 SetRect(&rcSect, rectClient.right - (SECTCOUNT - i) * nSectWidth, rectClient.top, rectClient.right - (SECTCOUNT - i - 1) * nSectWidth, rectClient.bottom - (SECTCOUNT - i - 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCornerRightTop(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //绘制横向 SetRect(&rcSect, rectClient.left, rectClient.top + i * nSectWidth, rectClient.right - i * nSectWidth, rectClient.top + (i + 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); //绘制竖向 SetRect(&rcSect, rectClient.right - (SECTCOUNT -i) * nSectWidth, rectClient.top + (SECTCOUNT - i) * nSectWidth, rectClient.right - (SECTCOUNT - i - 1) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCornerLeftBottom(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //绘制横向 SetRect(&rcSect, rectClient.left + (SECTCOUNT - i) * nSectWidth, rectClient.bottom - (SECTCOUNT - i) * nSectWidth, rectClient.right, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); //绘制竖向 SetRect(&rcSect, rectClient.left + i * nSectWidth, rectClient.top, rectClient.left + (i + 1) * nSectWidth, rectClient.bottom - i * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCrossCenter(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; int xCenter = rectClient.left + (rectClient.right - rectClient.left) / 2; int yCenter = rectClient.top + (rectClient.bottom - rectClient.top) / 2; int xLeft = xCenter - SECTCOUNT * nSectWidth / 2; int yTop = yCenter - SECTCOUNT * nSectWidth / 2; //绘制横向 for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); SetRect(&rcSect, rectClient.left, yTop + i * nSectWidth, rectClient.right, yTop + (i + 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } //绘制竖向 for (i=0; i<=SECTCOUNT / 2; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //上左 SetRect(&rcSect, xLeft + i * nSectWidth, rectClient.top, xLeft + (i + 1) * nSectWidth, yTop + i * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); //上右 SetRect(&rcSect, xLeft + (SECTCOUNT - i -1) * nSectWidth, rectClient.top, xLeft + (SECTCOUNT - i) * nSectWidth, yTop + i * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); //下左 SetRect(&rcSect, xLeft + i * nSectWidth, yTop + (SECTCOUNT - i) * nSectWidth, xLeft + (i + 1) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); //下右 SetRect(&rcSect, xLeft + (SECTCOUNT - i -1) * nSectWidth, yTop + (SECTCOUNT - i) * nSectWidth, xLeft + (SECTCOUNT - i) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCrossTop(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; int xCenter = rectClient.left + (rectClient.right - rectClient.left) / 2; //绘制横向 for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); SetRect(&rcSect, rectClient.left, rectClient.top + i * nSectWidth, rectClient.right, rectClient.top + (i + 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } //绘制竖向 int xLeft = xCenter - SECTCOUNT * nSectWidth / 2; for (i=0; i<=SECTCOUNT / 2; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //下左 SetRect(&rcSect, xLeft + i * nSectWidth, rectClient.top + (SECTCOUNT - i) * nSectWidth, xLeft + (i + 1) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); //下右 SetRect(&rcSect, xLeft + (SECTCOUNT - i - 1) * nSectWidth, rectClient.top + (SECTCOUNT - i) * nSectWidth, xLeft + (SECTCOUNT - i) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCrossRight(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; int yCenter = rectClient.top + (rectClient.bottom - rectClient.top) / 2; //绘制竖向 for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); SetRect(&rcSect, rectClient.right - (SECTCOUNT - i) * nSectWidth, rectClient.top, rectClient.right - (SECTCOUNT - i - 1) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } //绘制横向 int yTop = yCenter - SECTCOUNT * nSectWidth / 2; for (i=0; i<=SECTCOUNT / 2; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //上 SetRect(&rcSect, rectClient.left, yTop + i * nSectWidth, rectClient.right - (SECTCOUNT - i) * nSectWidth, yTop + (SECTCOUNT - i - 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); //下 SetRect(&rcSect, rectClient.left, yTop + (SECTCOUNT - i) * nSectWidth, rectClient.right - (SECTCOUNT - i) * nSectWidth, yTop + (SECTCOUNT - i - 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCrossBottom(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; int xCenter = rectClient.left + (rectClient.right - rectClient.left) / 2; //绘制横向 for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); SetRect(&rcSect, rectClient.left, rectClient.bottom - (i + 1) * nSectWidth, rectClient.right, rectClient.bottom - i * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } //绘制竖向 int xLeft = xCenter - SECTCOUNT * nSectWidth / 2; for (i=0; i<=SECTCOUNT / 2; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //下左 SetRect(&rcSect, xLeft + i * nSectWidth, rectClient.top, xLeft + (i + 1) * nSectWidth, rectClient.bottom - (SECTCOUNT - i) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); //下右 SetRect(&rcSect, xLeft + (SECTCOUNT - i - 1) * nSectWidth, rectClient.top, xLeft + (SECTCOUNT - i) * nSectWidth, rectClient.bottom - (SECTCOUNT - i) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } void CPipeCtrl::DrawCrossLeft(CDC *pDC, RECT &rectClient) { RECT rcSect; CBrush pBackBrush, *pOldBrush; int nSectWidth = m_nWidth / SECTCOUNT; int yCenter = rectClient.top + (rectClient.bottom - rectClient.top) / 2; //绘制竖向 for (int i=0; i<SECTCOUNT; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); SetRect(&rcSect, rectClient.left + (SECTCOUNT - i) * nSectWidth, rectClient.top, rectClient.left + (SECTCOUNT - i + 1) * nSectWidth, rectClient.bottom); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } //绘制横向 int yTop = yCenter - SECTCOUNT * nSectWidth / 2; for (i=0; i<=SECTCOUNT / 2; i++) { pBackBrush.CreateSolidBrush(GetSectColor(i)); pOldBrush = (CBrush *)pDC->SelectObject(&pBackBrush); //上 SetRect(&rcSect, rectClient.left + (SECTCOUNT - i) * nSectWidth, yTop + i * nSectWidth, rectClient.right, yTop + (SECTCOUNT - i - 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); //下 SetRect(&rcSect, rectClient.left + (SECTCOUNT - i) * nSectWidth, yTop + (SECTCOUNT - i) * nSectWidth, rectClient.right, yTop + (SECTCOUNT - i - 1) * nSectWidth); pDC->FillRect(&rcSect, &pBackBrush); pDC->SelectObject(pOldBrush); pBackBrush.DeleteObject(); } } COLORREF & CPipeCtrl::GetSectColor(const int nSect) { int nPos = 0; switch (nSect) { case 0: case SECTCOUNT - 1: nPos = 0; break; case 1: case SECTCOUNT - 2: nPos = 1; break; case 2: case SECTCOUNT - 3: nPos = 2; break; case 3: case SECTCOUNT - 4: nPos = 3; break; case 4: case SECTCOUNT - 5: nPos = 4; break; case 5: nPos = 5; break; } return m_nBackColor[nPos]; } BOOL CPipeCtrl::OnEraseBkgnd(CDC* pDC) { return TRUE; } BOOL CALLBACK CPipeCtrl::EnumChildFunc(HWND hwnd, LPARAM lParam) { CRgn *pRgn = (CRgn *)lParam; RECT rcChild; CRgn rgnChild, rgnCopy; ::GetWindowRect(hwnd, &rcChild); rgnCopy.CreateRectRgn(0, 0, 1, 1); rgnCopy.CopyRgn(pRgn); rgnChild.CreateRectRgn(rcChild.left, rcChild.top, rcChild.right, rcChild.bottom); pRgn->CombineRgn(&rgnCopy, &rgnChild, RGN_OR); return TRUE; } int CPipeCtrl::SetBackTransparent(CWnd *pWnd, bool bClientOnly) { CRgn rgn; if (bClientOnly) { CRgn rgnWindow, rgnClient; RECT rcWindow, rcClient; pWnd->GetWindowRect(&rcWindow); pWnd->GetClientRect(&rcClient); pWnd->ClientToScreen(&rcClient); rgnWindow.CreateRectRgn(rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom); rgnClient.CreateRectRgn(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); rgn.CreateRectRgn(0, 0, 1, 1); rgn.CombineRgn(&rgnWindow, &rgnClient, RGN_DIFF); } else { rgn.CreateRectRgn(0, 0, 0, 0); } ::EnumChildWindows(pWnd->GetSafeHwnd(), (WNDENUMPROC)EnumChildFunc, (LPARAM)(LPVOID)&rgn); return pWnd->SetWindowRgn(rgn, TRUE); }