?? pointerdevice.cpp
字號:
/////////////////////////////////////////////////////////
// 指針式測量設(shè)備PointerDevice封裝類
// 版本:1.08
// 最后修改日期:2002.1.25
/////////////////////////////////////////////////////////
// PointerDevice.cpp : implementation file
//
#include "stdafx.h"
#include "PointerDevice.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// PointerDevice
/////////////////////////////////////////////////////////////////////////////////////////
//函數(shù)名:PointerDevice(CWnd *parent)
//輸入?yún)?shù):父窗口的指針
//返回值:無
//作用:為PointerDevice類的構(gòu)造函數(shù),將類的內(nèi)部變量設(shè)置成默認(rèn)值,創(chuàng)建類的實(shí)例并顯示子窗體
PointerDevice::PointerDevice(CWnd *parent)
{
PD_Width = 200; //儀表默認(rèn)寬度
PD_Height = 200; //儀表默認(rèn)高度
//設(shè)置儀表的原點(diǎn)為窗體的中心
PD_Origin.x = (long)((PD_Width - 1) / 2);
PD_Origin.y = (long)((PD_Height - 1) / 2);
PD_Direction = 1; //默認(rèn)為逆時(shí)針轉(zhuǎn)動(dòng),該變量表示正方向
PD_CurrentDirection = 1;//默認(rèn)方向和正向一樣
PD_UseBitmap = 0; //默認(rèn)下儀表不使用位圖作為背景。
PD_BitmapID = 0; //儀表背景位圖的資源ID,默認(rèn)下不使用
PD_CenterAngle = 90; //設(shè)置表盤的弧度中心默認(rèn)位置為Y軸(90度)方向
PD_SweepAngle = 360; //設(shè)置表盤弧度的默認(rèn)跨度為360度
PD_FaceSweepAngle = 360;//設(shè)置表盤面板弧度跨度
PD_TextStartAngle = 0; //刻度文字的起始位置默認(rèn)為弧度中心位置
PD_SmallGridLength = 4; //設(shè)置表盤小刻度線長度
PD_SmallGridNum = 50; //設(shè)置表盤默認(rèn)小刻度格數(shù)
PD_BigGridLength = 8; //設(shè)置表盤大刻度線長度為
PD_BigGridNum = 10; //設(shè)置表盤默認(rèn)大刻度格數(shù)
PD_FontSize = 12; //刻度標(biāo)注字體大小,默認(rèn)采用12點(diǎn)字體
PD_OutputFontSize = 16; //輸出框內(nèi)文字大小,默認(rèn)采用16點(diǎn)字體
PD_Title = ""; //標(biāo)題文字(默認(rèn)為空)
PD_TitleOffset.x = 0; //標(biāo)題相對儀表窗口左上角的位置
PD_TitleOffset.y = 0;
PD_TitleColor = RGB(0, 0, 0); //默認(rèn)的標(biāo)題顏色
PD_TitleFontSize = 0; //標(biāo)題欄字體大小(默認(rèn)為0,表示不需要標(biāo)題)
PD_TextSpace = 10; //默認(rèn)文字與刻度線距離
PD_CenterNumber = 0; //默認(rèn)刻度中心的數(shù)字為0
PD_DeltaNumber = 1; //默認(rèn)刻度數(shù)字增量為1
PD_BorderWidth = 12; //圓形邊界的寬度
PD_StepLength = 5; //指針默認(rèn)的最小旋轉(zhuǎn)量
PD_FaceRadius = (UINT)((PD_Width - 1) / 2) - PD_BorderWidth; //設(shè)置表盤弧度的默認(rèn)半徑為儀表邊長的一半(扣除邊界尺寸)
PD_Radius = PD_FaceRadius - 10; //默認(rèn)情況下,讓刻度顯離開邊緣10個(gè)象素
PD_InnerRadius = 0; //默認(rèn)情況不加空心內(nèi)圓
PD_AxleRadius = 0; //指針轉(zhuǎn)軸的半徑
PD_PointerWidth = 1; //默認(rèn)表針為1象素粗
PD_PointerLength = PD_Radius - PD_BigGridLength - 1; //默認(rèn)的指針長度
PD_HasPointerShadow = 0; //默認(rèn)沒有指針陰影
PD_PointerShadowColor = RGB(100, 100, 100); //默認(rèn)的指針陰影顏色
PD_PointerShadowOffset.x = 3; //指針陰影相對于指針的偏移量
PD_PointerShadowOffset.y = 2;
PD_PointerColor = RGB(0, 255, 0); //默認(rèn)儀表指針顏色為綠色
PD_AxleColor = RGB(150, 150, 150); //默認(rèn)儀表指針的軸顏色
PD_BkColor = GetSysColor(COLOR_3DFACE); //默認(rèn)儀表背景顏色和對話框背景顏色一致
PD_CalibrationColor = RGB(255, 255, 255); //默認(rèn)儀表刻度顏色為白色
PD_FaceColor = RGB(0, 0, 0); //默認(rèn)儀表表盤顏色為黑色
PD_TextColor = PD_CalibrationColor; //默認(rèn)刻度文字和刻度線顏色相同
PD_BorderColor = RGB(150, 150, 150); //定義邊界顏色為灰色
PD_Timer = 30; //儀表內(nèi)部定時(shí)器的觸發(fā)時(shí)間間隔,默認(rèn)為40毫秒
PD_Status = PD_UPDATED; //儀表的默認(rèn)狀態(tài)設(shè)置成測試狀態(tài)
PD_IsLoop = false; //默認(rèn)情況下,儀表的指針不能循環(huán)轉(zhuǎn)動(dòng)
PD_RotateDir = false; //默認(rèn)情況下,儀表的指針是逆時(shí)針轉(zhuǎn)動(dòng)
PD_CurrentAngle = 0; //默認(rèn)情況下,儀表的指針和刻度弧的中線重合
PD_CurrentNumber = 0; //設(shè)置量程和當(dāng)前示數(shù)
PD_MaxNumber = 10;
PD_MinNumber = 0;
PD_PointerSide.x = 3; //設(shè)置默認(rèn)的指針形狀
PD_PointerSide.y = 6;
PD_PointerTail = 10;
PD_OutputPos.x = 0; //設(shè)置默認(rèn)的輸出框位置
PD_OutputPos.y = - ((int)PD_Radius / 2) + 5;
PD_OutputWidth = (PD_Radius / 2); //設(shè)置默認(rèn)的輸出框大小
PD_OutputHeight = 20;
PD_OutputBkColor = RGB(0, 0, 55); //設(shè)置輸出框的外觀
PD_OutputBdColor = RGB(255, 255, 255);
PD_OutputTextColor = RGB(255, 255, 0);
PD_OutputTextPos.x = 0;
PD_OutputTextPos.y = PD_OutputPos.y - PD_OutputFontSize / 2;
PD_OutputAccuracy = 1; //默認(rèn)輸出框采用一位小數(shù)精度
PD_Accuracy = 1; //默認(rèn)刻度文字用一位小數(shù)精度
PD_Style = PD_3DSTYLE; //默認(rèn)采用3D邊框
PD_Update(); //調(diào)用該函數(shù)對其他變量進(jìn)行初始化
//創(chuàng)建相應(yīng)的靜態(tài)控件并且顯示
CRect rect;
rect.left = rect.top = 0;
rect.bottom = PD_Height - 1;
rect.right = PD_Width - 1;
Create(NULL, WS_CHILD | WS_VISIBLE | SS_NOTIFY, rect, parent);
SetTimer(1, PD_Timer, NULL); //設(shè)置定時(shí)器
}
/////////////////////////////////////////////////////////////////////////////////////////
//函數(shù)名:~PointerDevice()
//輸入?yún)?shù):無
//返回值:無
//作用:析構(gòu)函數(shù)
PointerDevice::~PointerDevice()
{
PD_Font.DeleteObject();
PD_OutputFont.DeleteObject();
KillTimer(1);
}
BEGIN_MESSAGE_MAP(PointerDevice, CStatic)
//{{AFX_MSG_MAP(PointerDevice)
ON_WM_PAINT()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// PointerDevice message handlers
/////////////////////////////////////////////////////////////////////////////////////////
//函數(shù)名:OnPaint()
//輸入?yún)?shù):無
//返回值:無
//作用:重載函數(shù),繪制儀表盤的界面
void PointerDevice::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
DrawFace();
// Do not call CStatic::OnPaint() for painting messages
}
/////////////////////////////////////////////////////////////////////////////////////////
//函數(shù)名:OnPaint()
//輸入?yún)?shù):定時(shí)器事件的ID
//返回值:無
//作用:重載函數(shù),處理定時(shí)器消息,完成指針某時(shí)刻的位置指定,更新界面顯示
void PointerDevice::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch(PD_Status) //儀表將根據(jù)不同的狀態(tài)作出反應(yīng)
{
case PD_TEST: //測試狀態(tài),轉(zhuǎn)動(dòng)指針
PD_CurrentAngle += PD_StepLength * PD_CurrentDirection;
if(PD_IsLoop == false && (PD_CurrentAngle >= (PD_SweepAngle / 2) || PD_CurrentAngle <= - (PD_SweepAngle / 2)))
{
PD_CurrentDirection = - PD_CurrentDirection;
}
DrawFace(); //更新顯示
break;
case PD_UPDATED: //等候狀態(tài),等待數(shù)據(jù)的變動(dòng)
break;
case PD_UPDATING: //更新過程狀態(tài),指針尚未擺動(dòng)到合適的位置
if(PD_CurrentAngle < PD_ObjectAngle) //當(dāng)前角度小于目標(biāo)角度
{
PD_CurrentAngle += PD_StepLength * PD_Direction;
if(PD_CurrentAngle > PD_ObjectAngle)
{
PD_CurrentAngle = PD_ObjectAngle;
PD_Status = PD_UPDATED;
}
}
else //當(dāng)前角度大于目標(biāo)角度
{
PD_CurrentAngle -= PD_StepLength * PD_Direction;
if(PD_CurrentAngle < PD_ObjectAngle)
{
PD_CurrentAngle = PD_ObjectAngle;
PD_Status = PD_UPDATED;
}
}
DrawFace(); //更新顯示
break;
case PD_SHUTDOWN: //關(guān)閉狀態(tài),不作響應(yīng)
break;
default:
break;
}
CStatic::OnTimer(nIDEvent);
}
/////////////////////////////////////////////////////////////////////////////////////////
//函數(shù)名:DrawFace()
//輸入?yún)?shù):無
//返回值:無
//作用:繪制整個(gè)儀表的界面
void PointerDevice::DrawFace()
{
CClientDC dc(this);
CDC dcmem;
BITMAP bmp;
CBitmap bmpc, *pbitmapold;
CPen pen, *ppenold;
CBrush brush0, brush, *pbrushold;
COLORREF temp_color;
int j;
if(PD_UseBitmap == 1) //使用位圖背景
bmpc.LoadBitmap(PD_BitmapID);
else if(PD_UseBitmap == 2) //使用映射位圖作為背景
bmpc.LoadMappedBitmap(PD_BitmapID);
else //不使用位圖背景
bmpc.CreateCompatibleBitmap(&dc, PD_Width, PD_Height); //創(chuàng)建與系統(tǒng)兼容的位圖
bmpc.GetBitmap(&bmp);
if(!PD_Font.m_hObject)
PD_Font.CreateFont(PD_FontSize, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS, _T("Arial")); //創(chuàng)建一個(gè)默認(rèn)的刻度數(shù)字字體
if(!PD_OutputFont.m_hObject)
PD_OutputFont.CreateFont(PD_OutputFontSize, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS, _T("Arial")); //創(chuàng)建一個(gè)默認(rèn)的刻度數(shù)字字體
if(!PD_TitleFont.m_hObject)
PD_TitleFont.CreateFont(PD_TitleFontSize, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS, _T("Arial")); //創(chuàng)建一個(gè)默認(rèn)的刻度數(shù)字字體
dcmem.CreateCompatibleDC(&dc);
pbitmapold = (CBitmap *)dcmem.SelectObject(&bmpc);
if(PD_UseBitmap != 1 && PD_UseBitmap != 2) //如果不使用位圖或者映射位圖作為背景,就用矢量繪制整個(gè)面板
{
//繪制“透明”的位圖底色
brush0.CreateSolidBrush(PD_BkColor);
CBrush * pbrushold = (CBrush *)dcmem.SelectObject(&brush0);
dcmem.SelectStockObject(NULL_PEN);
dcmem.Rectangle(0, 0, bmp.bmWidth + 1, bmp.bmHeight + 1);
dcmem.SelectObject(pbrushold);
//繪制3D圓形外框
temp_color = PD_BorderColor;
brush.CreateSolidBrush(PD_BorderColor);
pbrushold = (CBrush *)dcmem.SelectObject(&brush);
dcmem.Pie(PD_Origin.x - PD_FaceRadius - PD_BorderWidth, PD_Origin.y - PD_FaceRadius - PD_BorderWidth, PD_Origin.x + PD_FaceRadius + PD_BorderWidth, PD_Origin.y + PD_FaceRadius + PD_BorderWidth, PD_FaceStartPoint.x, PD_FaceStartPoint.y, PD_FaceEndPoint.x, PD_FaceEndPoint.y);
dcmem.SelectObject(pbrushold);
brush.DeleteObject();
if(PD_BorderWidth)
{
int halfbdw = (int)(PD_BorderWidth / 2);
for(j = 0; j < (int)PD_BorderWidth; j ++)
{
if(j >= halfbdw)
temp_color = GetNextColor(temp_color, 0.9);
else
temp_color = GetNextColor(temp_color, 1.1);
pen.CreatePen(PS_SOLID, 1, temp_color);
ppenold = (CPen *)dcmem.SelectObject(&pen);
dcmem.MoveTo(PD_FaceStartPoint);
dcmem.AngleArc(PD_Origin.x, PD_Origin.y, PD_FaceRadius + j, (float)(PD_RightAngle - (PD_FaceSweepAngle - PD_SweepAngle)/ 2), (float)PD_FaceSweepAngle); //繪制刻度弧
dcmem.SelectObject(ppenold);
pen.DeleteObject();
}
}
//繪制扇形(圓形)刻度盤
brush.CreateSolidBrush(PD_FaceColor);
pbrushold = (CBrush *)dcmem.SelectObject(&brush);
pen.CreatePen(PS_SOLID, 1, PD_FaceColor);
ppenold = (CPen *)dcmem.SelectObject(&pen);
dcmem.Pie(PD_Origin.x - PD_FaceRadius, PD_Origin.y - PD_FaceRadius, PD_Origin.x + PD_FaceRadius, PD_Origin.y + PD_FaceRadius, PD_FaceStartPoint.x, PD_FaceStartPoint.y, PD_FaceEndPoint.x, PD_FaceEndPoint.y);
dcmem.SelectObject(pbrushold);
brush.DeleteObject();
dcmem.SelectObject(ppenold);
pen.DeleteObject();
//繪制內(nèi)圓
if(PD_InnerRadius)
{
pbrushold = (CBrush *)dcmem.SelectObject(&brush0);
dcmem.Ellipse(PD_Origin.x - PD_InnerRadius, PD_Origin.y - PD_InnerRadius, PD_Origin.x + PD_InnerRadius, PD_Origin.y + PD_InnerRadius);
dcmem.SelectObject(pbrushold);
}
brush0.DeleteObject();
}
pen.CreatePen(PS_SOLID, 1, PD_CalibrationColor);
ppenold = (CPen *)dcmem.SelectObject(&pen);
//繪制刻度弧線,這里先暫時(shí)不用
//dcmem.MoveTo(PD_StartPoint.x, PD_StartPoint.y);
//dcmem.AngleArc(PD_Origin.x, PD_Origin.y, PD_Radius, PD_RightAngle, PD_SweepAngle); //繪制刻度弧
//繪制大刻度分割線
UINT i;
UINT R1 = PD_Radius - PD_BigGridLength;
double delta = PD_SweepAngle / PD_BigGridNum;
double current_angle = PD_RightAngle;
CPoint in, out;
for(i = 0; i < PD_BigGridNum; i ++)
{
out.x = PD_Origin.x + (long)(PD_Radius * cos(ANG * current_angle));
out.y = PD_Origin.y - (long)(PD_Radius * sin(ANG * current_angle));
in.x = PD_Origin.x + (long)(R1 * cos(ANG * current_angle));
in.y = PD_Origin.y - (long)(R1 * sin(ANG * current_angle));
dcmem.MoveTo(in);
dcmem.LineTo(out);
current_angle += delta;
}
//繪制小刻度分割線
R1 = PD_Radius - PD_SmallGridLength;
delta = PD_SweepAngle / PD_SmallGridNum;
current_angle = PD_RightAngle;
int tmp = PD_SmallGridNum / PD_BigGridNum;
for(i = 0; i < PD_SmallGridNum; i ++)
{
if(i % tmp == 0)
{
current_angle += delta;
continue;
}
out.x = PD_Origin.x + (long)(PD_Radius * cos(ANG * current_angle));
out.y = PD_Origin.y - (long)(PD_Radius * sin(ANG * current_angle));
in.x = PD_Origin.x + (long)(R1 * cos(ANG * current_angle));
in.y = PD_Origin.y - (long)(R1 * sin(ANG * current_angle));
dcmem.MoveTo(in);
dcmem.LineTo(out);
current_angle += delta;
}
dcmem.SelectObject(ppenold);
pen.DeleteObject();
//寫入刻度文字
R1 = PD_Radius - ((PD_BigGridLength > PD_SmallGridLength) ? PD_BigGridLength : PD_SmallGridLength);
CFont * pfontold = (CFont *)dcmem.SelectObject(&PD_Font);
int oldmode = dcmem.SetBkMode(TRANSPARENT);
COLORREF oldcolor = dcmem.SetTextColor(PD_TextColor);
CString text, format;
CPoint textpos;
double tmpnum;
current_angle = PD_TextStartAngle + PD_CenterAngle;
delta = PD_SweepAngle / PD_BigGridNum;
for(i = 0; i <= PD_BigGridNum; i ++)
{
textpos.x = PD_Origin.x + (long)((R1 - PD_TextSpace) * cos(ANG * current_angle));
textpos.y = PD_Origin.y - (long)((R1 - PD_TextSpace) * sin(ANG * current_angle));
tmpnum = PD_CenterNumber + i * PD_DeltaNumber;
if((int)tmpnum == tmpnum)
{
text.Format("%d", (int)tmpnum);
}
else
{
format.Format("%%.%dlf", PD_OutputAccuracy);
text.Format(format, tmpnum);
}
if(current_angle < 180 && current_angle > 0)
{
dcmem.SetTextAlign(TA_CENTER | TA_TOP);
dcmem.TextOut(textpos.x + 2, textpos.y - 5, text);
}
else
{
dcmem.SetTextAlign(TA_CENTER | TA_BOTTOM);
dcmem.TextOut(textpos.x + 2, textpos.y + 5, text);
}
current_angle += delta;
if(current_angle - PD_TextStartAngle - PD_CenterAngle >= 360)
break;
if(PD_SweepAngle < 360 && current_angle >= PD_LeftAngle)
break;
}
current_angle = PD_TextStartAngle + PD_CenterAngle;
if(PD_SweepAngle < 360) //對于非圓形的表盤,還要畫出負(fù)數(shù)部分
{
for(i = 0; i <= PD_BigGridNum; i ++)
{
textpos.x = PD_Origin.x + (long)((R1 - PD_TextSpace) * cos(ANG * current_angle));
textpos.y = PD_Origin.y - (long)((R1 - PD_TextSpace) * sin(ANG * current_angle));
tmpnum = PD_CenterNumber - i * PD_DeltaNumber;
if((int)tmpnum == tmpnum)
{
text.Format("%d", (int)tmpnum);
}
else
{
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -