📄 myroundsliderctrl2.cpp
字号:
// MyRoundSliderCtrl2.cpp : implementation file
//
#include "stdafx.h"
#include "MyRoundSliderCtrl2.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//包含头文件
#include <math.h>
//#include "MyRoundSliderCtrl2.h"
//
//////////引用别人的函数*********
static const double pi = 2*asin(1);
// The following 3 functions were taken from 'CRoundButton.cpp', written and
// copyright (c) 1997,1998 by Chris Maunder.
// To be honest, I never had a look at their implementation, I just use them.
// This is cut-and-paste-programming at its best... if it works... :) (Daniel)
// prototypes
COLORREF GetColour(double dAngle, COLORREF crBright, COLORREF crDark);
void DrawCircle(CDC* pDC, CPoint p, LONG lRadius, COLORREF crColour, BOOL bDashed = FALSE);
void DrawCircle(CDC* pDC, CPoint p, LONG lRadius, COLORREF crBright, COLORREF crDark);
// Calculate colour for a point at the given angle by performing a linear
// interpolation between the colours crBright and crDark based on the cosine
// of the angle between the light source and the point.
//
// Angles are measured from the +ve x-axis (i.e. (1,0) = 0 degrees, (0,1) = 90 degrees )
// But remember: +y points down!
COLORREF GetColour(double dAngle, COLORREF crBright, COLORREF crDark)
{
#define Rad2Deg 180.0/3.1415
#define LIGHT_SOURCE_ANGLE -2.356 // -2.356 radians = -135 degrees, i.e. From top left
ASSERT(dAngle > -3.1416 && dAngle < 3.1416);
double dAngleDifference = LIGHT_SOURCE_ANGLE - dAngle;
if (dAngleDifference < -3.1415) dAngleDifference = 6.293 + dAngleDifference;
else if (dAngleDifference > 3.1415) dAngleDifference = 6.293 - dAngleDifference;
double Weight = 0.5*(cos(dAngleDifference)+1.0);
BYTE Red = (BYTE) (Weight*GetRValue(crBright) + (1.0-Weight)*GetRValue(crDark));
BYTE Green = (BYTE) (Weight*GetGValue(crBright) + (1.0-Weight)*GetGValue(crDark));
BYTE Blue = (BYTE) (Weight*GetBValue(crBright) + (1.0-Weight)*GetBValue(crDark));
//TRACE("LightAngle = %0.0f, Angle = %3.0f, Diff = %3.0f, Weight = %0.2f, RGB %3d,%3d,%3d\n",
// LIGHT_SOURCE_ANGLE*Rad2Deg, dAngle*Rad2Deg, dAngleDifference*Rad2Deg, Weight,Red,Green,Blue);
return RGB(Red, Green, Blue);
}
//画圆,实线圆或虚线圆,没有阴影效果的
void DrawCircle(CDC* pDC, CPoint p, LONG lRadius, COLORREF crColour, BOOL bDashed)
{
const int nDashLength = 1;
LONG lError, lXoffset, lYoffset;
int nDash = 0;
BOOL bDashOn = TRUE;
//Check to see that the coordinates are valid
ASSERT( (p.x + lRadius <= LONG_MAX) && (p.y + lRadius <= LONG_MAX) );
ASSERT( (p.x - lRadius >= LONG_MIN) && (p.y - lRadius >= LONG_MIN) );
//Set starting values
lXoffset = lRadius;
lYoffset = 0;
lError = -lRadius;
do {
if (bDashOn) {
pDC->SetPixelV(p.x + lXoffset, p.y + lYoffset, crColour);
pDC->SetPixelV(p.x + lXoffset, p.y - lYoffset, crColour);
pDC->SetPixelV(p.x + lYoffset, p.y + lXoffset, crColour);
pDC->SetPixelV(p.x + lYoffset, p.y - lXoffset, crColour);
pDC->SetPixelV(p.x - lYoffset, p.y + lXoffset, crColour);
pDC->SetPixelV(p.x - lYoffset, p.y - lXoffset, crColour);
pDC->SetPixelV(p.x - lXoffset, p.y + lYoffset, crColour);
pDC->SetPixelV(p.x - lXoffset, p.y - lYoffset, crColour);
}
//Advance the error term and the constant X axis step
lError += lYoffset++;
//Check to see if error term has overflowed
if ((lError += lYoffset) >= 0)
lError -= --lXoffset * 2;
if (bDashed && (++nDash == nDashLength)) {
nDash = 0;
bDashOn = !bDashOn;
}
} while (lYoffset <= lXoffset); //Continue until halfway point
}
//画圆型阴影效果边框
void DrawCircle(CDC* pDC, CPoint p, LONG lRadius, COLORREF crBright, COLORREF crDark)
{
LONG lError, lXoffset, lYoffset;
//Check to see that the coordinates are valid
ASSERT( (p.x + lRadius <= LONG_MAX) && (p.y + lRadius <= LONG_MAX) );
ASSERT( (p.x - lRadius >= LONG_MIN) && (p.y - lRadius >= LONG_MIN) );
//Set starting values
lXoffset = lRadius;
lYoffset = 0;
lError = -lRadius;
do {
const double Pi = 3.141592654,
Pi_on_2 = Pi * 0.5;
// Three_Pi_on_2 = Pi * 1.5;
COLORREF crColour;
double dAngle = atan2(lYoffset, lXoffset);
//Draw the current pixel, reflected across all eight arcs
crColour = GetColour(dAngle, crBright, crDark);
pDC->SetPixelV(p.x + lXoffset, p.y + lYoffset, crColour);
crColour = GetColour(Pi_on_2 - dAngle, crBright, crDark);
pDC->SetPixelV(p.x + lYoffset, p.y + lXoffset, crColour);
crColour = GetColour(Pi_on_2 + dAngle, crBright, crDark);
pDC->SetPixelV(p.x - lYoffset, p.y + lXoffset, crColour);
crColour = GetColour(Pi - dAngle, crBright, crDark);
pDC->SetPixelV(p.x - lXoffset, p.y + lYoffset, crColour);
crColour = GetColour(-Pi + dAngle, crBright, crDark);
pDC->SetPixelV(p.x - lXoffset, p.y - lYoffset, crColour);
crColour = GetColour(-Pi_on_2 - dAngle, crBright, crDark);
pDC->SetPixelV(p.x - lYoffset, p.y - lXoffset, crColour);
crColour = GetColour(-Pi_on_2 + dAngle, crBright, crDark);
pDC->SetPixelV(p.x + lYoffset, p.y - lXoffset, crColour);
crColour = GetColour(-dAngle, crBright, crDark);
pDC->SetPixelV(p.x + lXoffset, p.y - lYoffset, crColour);
//Advance the error term and the constant X axis step
lError += lYoffset++;
//Check to see if error term has overflowed
if ((lError += lYoffset) >= 0)
lError -= --lXoffset * 2;
} while (lYoffset <= lXoffset); //Continue until halfway point
}
//////////end 引用别人的函数 **************
/////////////////////////////////////////////////////////////////////////////
// CMyRoundSliderCtrl2
CMyRoundSliderCtrl2::CMyRoundSliderCtrl2()
{
//初始化变量****
//针对客户**
m_dMaxValue = 1.0;//客户指定最大值
m_dMinValue = 0.0;//客户指定最小值
m_dPlusValue = 0.02;//增益
//对程序设计者**
m_nMaxAngle = 215;//终止角度(最大角度)---对应最小值
m_nMinAngle = -35;//起始角度(最小角度)---对应最大值
//绘图变量
m_bkClr = RGB(0,255,0);//按钮颜色
m_scaleClr = RGB(250,100,0);//刻度颜色
m_pointerClr = RGB(255,0,0);//指针颜色
m_scaleTextClr = RGB(0,0,255);//刻度上指示值颜色
m_textClr = RGB(0,255,0);//输出值的颜色
//
m_bLButtonDown = FALSE;
m_bMouseMove = FALSE;
//初始化m_dCurrentValue,m_nDivNum,m_nAngleDiv,m_nCurrentAngle
Init();
//end 初始化变量****
}
//初始化m_dCurrentValue,m_nDivNum,m_nAngleDiv,m_nCurrentAngle
void CMyRoundSliderCtrl2::Init()
{
m_dCurrentValue = m_dMinValue;//当前值
m_nDivNum = (int)((m_dMaxValue - m_dMinValue)/m_dPlusValue); //总格数
m_nAngleDiv = (m_nMaxAngle - m_nMinAngle)/m_nDivNum;//每小格度数
m_nCurrentAngle = m_nMaxAngle;//当前位置---对应当前值的最小值
}
CMyRoundSliderCtrl2::~CMyRoundSliderCtrl2()
{
//释放资源,清理内存
m_rgn.DeleteObject();
if(m_memDC.GetSafeHdc())
{
m_memDC.SelectObject(m_pOldBitmap);
m_memBitmap.DeleteObject();
m_memDC.DeleteDC();
//delete m_pOldBitmap;//不能有
}
}
BEGIN_MESSAGE_MAP(CMyRoundSliderCtrl2, CSliderCtrl)
//{{AFX_MSG_MAP(CMyRoundSliderCtrl2)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_WM_ERASEBKGND()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMyRoundSliderCtrl2 message handlers
void CMyRoundSliderCtrl2::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
CSliderCtrl::PreSubclassWindow();
//resize the window to make it square
GetClientRect(&m_clientRect);
//
ChangeSize();
}
void CMyRoundSliderCtrl2::ChangeSize()
{
m_clientRect.right = m_clientRect.bottom ;
//改变窗口形状
m_rgn.DeleteObject();
m_rgn.CreateEllipticRgnIndirect(&m_clientRect);
SetWindowRgn(m_rgn, TRUE);
//先确定各半径大小--可更改
m_nBigRadius = m_clientRect.Height()/2;
m_nSmallRadius = m_nBigRadius*1/2;
m_nPointerRadius = 3;//指针半径
//
m_centerPoint = CPoint(m_clientRect.right/2-1,m_clientRect.bottom/2-1);
//准备内存DC
CClientDC dc(this);
if(m_memDC.m_hDC){
m_memDC.DeleteDC();
m_memBitmap.DeleteObject();
}
m_memDC.CreateCompatibleDC(&dc);
m_memBitmap.CreateCompatibleBitmap(&dc,
m_clientRect.Width(), m_clientRect.Height());
m_pOldBitmap = m_memDC.SelectObject(&m_memBitmap);
}
void CMyRoundSliderCtrl2::OnPaint()
{
CPaintDC dc(this); // device context for painting
//用双缓存 m_memDC
// TODO: Add your message handler code here
CBrush bkBrush(m_bkClr);
//注意此处一定要重新创建m_rgn,因为很奇怪,似乎m_rgn不能保存自己
m_rgn.DeleteObject();
m_rgn.CreateEllipticRgnIndirect(&m_clientRect);
m_memDC.FillRgn(&m_rgn, &bkBrush);
//画大边界框****
//法2---多画几层是为了是轮廓及阴影看起来更厚重(若仍觉不够,可以再多画几层)
DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius-1,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius-1,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius-2,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius-2,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius-3,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius-2,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius-3,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nBigRadius-3,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
//中间突起部分圆****
/*//画表面颜色
m_rgn.DeleteObject();
CRect rect(m_clientRect.right/2-20,m_clientRect.bottom/2-20,
m_clientRect.right/2+20,m_clientRect.bottom/2+20);
m_rgn.CreateEllipticRgnIndirect(&rect);
CBrush brush(RGB(100,0,0));
dc.FillRgn(&m_rgn, &brush);
*///
//画阴影圆框
//法1
//DrawCircle(&dc, m_centerPoint, 20,
// RGB(255,0,0),RGB(0,0,0));
//法2---多画几层是为了是轮廓及阴影看起来更厚重
DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius-1,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius-1,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius-2,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius-2,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius-3,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius-3,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius-4,
::GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW));
// DrawCircle(&m_memDC, m_centerPoint, m_nSmallRadius-4,
// ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW));
//画刻度****
CPen* pOldPen;
CPen scalePen(PS_SOLID,1,m_scaleClr);
pOldPen = m_memDC.SelectObject(&scalePen);
//刻度圈
m_memDC.MoveTo(m_centerPoint.x+(int)(m_nSmallRadius*cos(m_nMinAngle*pi/180.0)),
m_centerPoint.y-(int)(m_nSmallRadius*sin(m_nMinAngle*pi/180.0)));
m_memDC.AngleArc( m_centerPoint.x, m_centerPoint.y,
m_nSmallRadius, m_nMinAngle, m_nMaxAngle - m_nMinAngle );
//从根部往上画每格小刻度-----从右边开始画
//处理长刻度指示值字***
CString strValue;//
double d = 0.02;
strValue.Format("%.2f",d);
CFont font, *pOldFont;
//选择字体
font.CreateFont(10,0,0,0,0,FALSE,FALSE,0,ANSI_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
DEFAULT_PITCH|FF_SWISS,"Arial");
pOldFont = m_memDC.SelectObject(&font);
//颜色和排列方式
m_memDC.SetBkMode(TRANSPARENT );
m_memDC.SetTextColor(m_scaleTextClr);
m_memDC.SetTextAlign(TA_LEFT);//可有可无,因为是默认方式
CSize pointerTextSize ;
CPoint pointerTextPoint;//字的左上角坐标
if(m_nDivNum < 50){
for(int i=0; i<=m_nDivNum; i++){//m_nDivNum格,m_nDivNum+1根线
//全画为长刻度
m_memDC.MoveTo(m_centerPoint.x+(int)(m_nSmallRadius*cos((m_nMinAngle+m_nAngleDiv*i)*pi/180.0)),
m_centerPoint.y-(int)(m_nSmallRadius*sin((m_nMinAngle+m_nAngleDiv*i)*pi/180.0)));
m_memDC.LineTo(m_centerPoint.x+(int)((m_nSmallRadius+6)*cos((m_nMinAngle+m_nAngleDiv*i)*pi/180.0)),
m_centerPoint.y-(int)((m_nSmallRadius+6)*sin((m_nMinAngle+m_nAngleDiv*i)*pi/180.0)));
//处理字
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -