⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rudderdevice.cpp

📁 上位机图形显示程序,可用于8051单片机的开发,通信及控制
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////
//			舵型指示设备RudderDevice封装类
//	版本:1.05
//	最后修改日期:2002.1.25
/////////////////////////////////////////////////////////

// RudderDevice.cpp : implementation file
//

#include "stdafx.h"
#include "RudderDevice.h"
#include "math.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// RudderDevice


/////////////////////////////////////////////////////////////////////////////////////////
//函数名:RudderDevice(CWnd * parent)
//输入参数:父窗口的指针
//返回值:无
//作用:构造函数,初始化变量的值,创建并显示对象
RudderDevice::RudderDevice(CWnd * parent)
{
	RD_Width = 120;		//默认的仪表宽度
	RD_Height = 120;	//默认的仪表高度

	RD_Origin.x = (RD_Width - 1) / 2;	//默认的原点是仪表窗口的中心
	RD_Origin.y = (RD_Height - 1) / 2;

	RD_AxleLength = (RD_Height - 1) / 2;	//默认的摆动轴长度为窗口高度的一半
	RD_AxleRadius = 8;		//默认的摆动轴截面半径

	RD_FrameThick = 20;		//滑槽边框的厚度
	RD_FrameRadius = 60;	//滑槽拱形边框的半径

	RD_MinLevel = 0;		//仪表内的最低档位
	RD_MaxLevel = 8;		//仪表内的最高档位
	RD_CurrentLevel = 2;	//仪表的当前档位
	RD_ObjectLevel = RD_CurrentLevel;	//仪表的目标档位

	RD_SweepAngle = 180;	//摆动轴的摆动幅度,采用角度值
	RD_CurrentAngle = 0;	//摆动轴的当前夹角,相对于Z轴正向,采用角度值

	RD_BkColor = GetSysColor(COLOR_3DFACE);	//默认的仪表背景色

	RD_Color = RGB(240, 240, 240);		//默认的仪表颜色

	RD_LampLightColor = RGB(255, 0, 0);	//默认的指示灯颜色
	RD_LampDarkColor = RGB(55, 0, 0);

	RD_TextLightColor = RGB(0, 0, 255);	//默认的文字颜色
	RD_TextDarkColor= RGB(0, 0, 0);

	RD_LampWidth = 40;	//指示灯的尺寸
	RD_LampHeight = 4;

	RD_LampOffset.x = -20;	//默认的指示灯位置(相对于原点)
	RD_LampOffset.y = RD_FrameRadius - 5;

	RD_TextOffset.x = 10;	//默认的文字相对于指示灯的偏移位置
	RD_TextOffset.y = - 7;

	RD_TextLeft = "档0,档1,档2,档3,档4,档5,档6,档7,档8";	//默认的标注文字
	RD_TextRight = "0节,1节,2节,3节,4节,5节,6节,7节,8节";	//默认的标注文字
	
	RD_RotateDirection = 1;	//默认的旋转方向是向上(正)
	
	RD_Status = RD_UPDATED;	//仪表默认的当前状态

	RD_HasAxle = 0;	//默认没有摆动轴

	RD_FontSize = 14;
	
	RD_Update();	//调用该函数对其他变量初始化

	//创建相应的静态控件并且显示
	CRect rect;			
	rect.left = rect.top = 0;
	rect.bottom = RD_Height - 1; 
	rect.right = RD_Width - 1;
	Create(NULL, WS_CHILD | WS_VISIBLE | SS_NOTIFY, rect, parent);	

	SetTimer(1, 50, NULL);	//设置工作时使用的计时器
}

RudderDevice::~RudderDevice()
{
	RD_Font.DeleteObject();
	KillTimer(1);
}


BEGIN_MESSAGE_MAP(RudderDevice, CStatic)
	//{{AFX_MSG_MAP(RudderDevice)
	ON_WM_PAINT()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// RudderDevice message handlers


/////////////////////////////////////////////////////////////////////////////////////////
//函数名:OnPaint()
//输入参数:无
//返回值:无
//作用:重载函数,绘制仪表界面
void RudderDevice::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	DrawFace();
	// Do not call CStatic::OnPaint() for painting messages
}


/////////////////////////////////////////////////////////////////////////////////////////
//函数名:DrawFace()
//输入参数:无
//返回值:无
//作用:绘制仪表界面
void RudderDevice::DrawFace()
{
	int i;
	CClientDC dc(this);
	CDC dcmem;	
	dcmem.CreateCompatibleDC(&dc);
	
	CBitmap bmpc;
	bmpc.CreateCompatibleBitmap(&dc, RD_Width, RD_Height);	//创建与系统兼容的位图
	BITMAP bmp;
	bmpc.GetBitmap(&bmp);
	
	CBrush brush, *pbrushold;
	CPen pen, *ppenold;
	CFont *pfontold;
	COLORREF temp_color;
	
	if(!RD_Font.m_hObject)
		RD_Font.CreateFont(RD_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"));	//创建一个默认的刻度数字字体

	brush.CreateSolidBrush(RD_BkColor);

	//绘制仪表的背景色
	CBitmap * pbitmapold = (CBitmap *)dcmem.SelectObject(&bmpc);
	pbrushold = (CBrush *)dcmem.SelectObject(&brush);
	dcmem.SelectStockObject(NULL_PEN);
	dcmem.Rectangle(0, 0, bmp.bmWidth + 1, bmp.bmHeight + 1);
	dcmem.SelectObject(pbrushold);
	brush.DeleteObject();
	
	//绘制拱形的滑槽
	temp_color = GetNextColor(RD_Color, 0.1);
	
	UINT maxcolor = GetRValue(temp_color);
	if(maxcolor < GetGValue(temp_color))
		maxcolor = GetGValue(temp_color);
	if(maxcolor < GetBValue(temp_color))
		maxcolor = GetBValue(temp_color);
	int h = (UINT)(RD_FrameRadius / maxcolor);
	if(h == 0)
		h = 1;
	int lt, rb;
	
	for(i = 0; i < (int)RD_FrameRadius; i ++)
	{
		brush.CreateSolidBrush(temp_color);
		pbrushold = (CBrush *)dcmem.SelectObject(&brush);
			
		lt = RD_Origin.y - RD_FrameRadius + i * h;
		rb = RD_Origin.y + RD_FrameRadius - i * h;
		if(lt > RD_Origin.y)
			lt = RD_Origin.y;
		if(rb < RD_Origin.y)
			rb= RD_Origin.y;
		dcmem.Rectangle(RD_Origin.x - RD_AxleRadius - RD_FrameThick, lt, RD_Origin.x + RD_AxleRadius + RD_FrameThick, rb);

		dcmem.SelectObject(pbrushold);
		brush.DeleteObject();
		temp_color = GetNextColor(temp_color, 1.1);
	}

	if(RD_HasAxle)	//如果有摆动轴,绘制黑色的滑槽内孔
	{
		dcmem.SelectStockObject(BLACK_BRUSH);
		dcmem.Rectangle(RD_Origin.x - RD_AxleRadius - 1, RD_Origin.y - RD_FrameRadius + 2, RD_Origin.x + RD_AxleRadius + 1, RD_Origin.y + RD_FrameRadius - 2);
	}

	//绘制档位指示灯以及文字
	int oldmode = dcmem.SetBkMode(TRANSPARENT);
	int index;
	CString text, allleft = RD_TextLeft, allright = RD_TextRight;
	pfontold = dcmem.SelectObject(&RD_Font);
	int space = RD_LampHeight + (2 * RD_FrameRadius - RD_SweepLevel * RD_LampHeight) / (RD_SweepLevel - 1) - 1;
	for(i = 0; i < (int)RD_SweepLevel; i ++)
	{
		if(i == (int)(RD_CurrentLevel - RD_MinLevel))
		{
			brush.CreateSolidBrush(RD_LampLightColor);
			dcmem.SetTextColor(RD_TextLightColor);
		}
		else
		{
			brush.CreateSolidBrush(RD_LampDarkColor);
			dcmem.SetTextColor(RD_TextDarkColor);
		}
		pbrushold = (CBrush *)dcmem.SelectObject(&brush);
		
		//绘制指示灯
		if(RD_HasAxle)	//有摆动轴,指示灯分列两边
		{
			dcmem.Rectangle(RD_Origin.x + RD_LampOffset.x, - i * space + RD_Origin.y + RD_LampOffset.y, RD_Origin.x + RD_LampOffset.x + RD_LampWidth, - i * space + RD_Origin.y + RD_LampOffset.y + RD_LampHeight);
			dcmem.Rectangle(RD_Origin.x - RD_LampOffset.x, - i * space + RD_Origin.y + RD_LampOffset.y, RD_Origin.x - RD_LampOffset.x - RD_LampWidth, - i * space + RD_Origin.y + RD_LampOffset.y + RD_LampHeight);
		}
		else	//没有摆动轴,绘制单列绘制指示灯
		{
			dcmem.Rectangle(RD_Origin.x + RD_LampOffset.x, - i * space + RD_Origin.y + RD_LampOffset.y, RD_Origin.x + RD_LampOffset.x + RD_LampWidth, - i * space + RD_Origin.y + RD_LampOffset.y + RD_LampHeight);	
		}

		//绘制左边的标注文字
		index = allleft.Find(",");	
		if(index != -1)
			text = allleft.Left(index);
		else
			text = allleft;	
		allleft = allleft.Right(allleft.GetLength() - text.GetLength() - 1);
		dcmem.SetTextAlign(TA_RIGHT | TA_TOP);
		dcmem.TextOut(RD_Origin.x - RD_LampOffset.x - RD_LampWidth - RD_TextOffset.x,  - i * space + RD_Origin.y + RD_LampOffset.y + RD_TextOffset.y, text);
		
		//绘制右边的标注文字
		index = allright.Find(",");	
		if(index != -1)
			text = allright.Left(index);
		else
			text = allright;		
		allright = allright.Right(allright.GetLength() - text.GetLength() - 1);
		dcmem.SetTextAlign(TA_LEFT | TA_TOP);
		dcmem.TextOut(RD_Origin.x + RD_LampOffset.x + RD_LampWidth + RD_TextOffset.x,  - i * space + RD_Origin.y + RD_LampOffset.y + RD_TextOffset.y, text);

		dcmem.SelectObject(pbrushold);
		brush.DeleteObject();			
	}
	dcmem.SetBkMode(oldmode);
	dcmem.SelectObject(pfontold);
	RD_Font.DeleteObject();

	//计算轴体的一些关键参数
	if(RD_HasAxle)
	{
		int len, shortaxle;
		shortaxle = (int)(RD_AxleRadius * cos(ANG * RD_CurrentAngle));
		RD_AxleCenter.y = RD_Origin.y - (long)(RD_AxleLength * sin(ANG * RD_CurrentAngle));	//摆动轴的y位置

		//绘制摆动轴的轴体
		temp_color = RD_Color;
		for(i = 0; i < (int)RD_AxleRadius; i ++)
		{
			len = (int)(sqrt(RD_AxleRadius * RD_AxleRadius - i * i) * cos(ANG * RD_CurrentAngle) - 1);
			if(RD_CurrentAngle < 0)
				len = - len;
			pen.CreatePen(PS_SOLID, 1, temp_color);
			ppenold = (CPen *)dcmem.SelectObject(&pen);
			dcmem.MoveTo(RD_AxleCenter.x + i - 1, RD_AxleCenter.y);
			dcmem.LineTo(RD_Origin.x + i - 1, RD_Origin.y + len);
			dcmem.MoveTo(RD_AxleCenter.x - i - 1, RD_AxleCenter.y);
			dcmem.LineTo(RD_Origin.x - i - 1, RD_Origin.y + len);
			
			dcmem.SelectObject(ppenold);
			pen.DeleteObject();
			temp_color = GetNextColor(temp_color, 0.9);
		}

		//绘制摆动轴截面的椭圆
		temp_color = GetNextColor(RD_Color, 0.6);
		brush.CreateSolidBrush(temp_color);
		pbrushold = (CBrush *)dcmem.SelectObject(&brush);
		dcmem.Ellipse(RD_AxleCenter.x - RD_AxleRadius, RD_AxleCenter.y - shortaxle, RD_AxleCenter.x + RD_AxleRadius, RD_AxleCenter.y + shortaxle);
		dcmem.SelectObject(pbrushold);
		brush.DeleteObject();
	}	//摆动轴绘制结束

	//将内存DC的内容一次画在屏幕DC上
	dc.BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &dcmem, 0, 0, SRCCOPY);

 	dcmem.SelectObject(pbitmapold);
	bmpc.DeleteObject();
	
	dcmem.DeleteDC();
}


/////////////////////////////////////////////////////////////////////////////////////////
//函数名:RD_MoveWindow(int x, int y)
//输入参数:仪表窗口左上角的目标位置坐标
//返回值:无
//作用:移动仪表窗口
void RudderDevice::RD_MoveWindow(int x, int y)
{
	CRect rect;
	GetWindowRect(&rect);
	MoveWindow(x, y, rect.Width(), rect.Height(), true);
}


/////////////////////////////////////////////////////////////////////////////////////////
//函数名:RD_Update()
//输入参数:无
//返回值:无
//作用:该函数对其他不能用函数设置的变量进行设置,应该在其他变量设置完全后再最后调用
void RudderDevice::RD_Update()
{
	RD_SweepLevel = RD_MaxLevel - RD_MinLevel + 1;		//仪表的档位总数
	RD_AnglePerLevel = RD_SweepAngle / (RD_SweepLevel - 1);	//每档之间变化的角度值
	RD_AxleCenter.x = RD_Origin.x;						//摆动轴的x位置和仪表原点相同
	RD_AxleCenter.y = RD_Origin.y - (long)(RD_AxleLength * sin(ANG * RD_CurrentAngle));	//摆动轴的y位置
	RD_CurrentAngle = RD_SweepAngle / 2 - (RD_MaxLevel - RD_CurrentLevel) * RD_AnglePerLevel;
}


/////////////////////////////////////////////////////////////////////////////////////////
//函数名:OnTimer(UINT nIDEvent) 
//输入参数:定时器触发事件的ID
//返回值:无
//作用:重载函数,负责对自检状态和工作状态下仪表的显示更新
void RudderDevice::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	switch(RD_Status)
	{
	case RD_TEST:
		if(RD_CurrentLevel >= RD_MaxLevel || RD_CurrentLevel <= RD_MinLevel)
			RD_RotateDirection = - RD_RotateDirection;
		RD_CurrentAngle += RD_AnglePerLevel * RD_RotateDirection;
		RD_CurrentLevel += RD_RotateDirection;
		DrawFace();
		break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -