?? wymeterctl.cpp
字號:
#include "stdafx.h"
#include "Meter.h"
#include "wyMeterCtl.h"
#include "wyMeterPpg.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CwyMeterCtrl, COleControl)
// 消息映射
BEGIN_MESSAGE_MAP(CwyMeterCtrl, COleControl)
//{{AFX_MSG_MAP(CwyMeterCtrl)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_MESSAGE(OCM_COMMAND, OnOcmCommand)
ON_OLEVERB(AFX_IDS_VERB_EDIT, OnEdit)
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()
// 調度映射
BEGIN_DISPATCH_MAP(CwyMeterCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CwyMeterCtrl)
DISP_PROPERTY_NOTIFY(CwyMeterCtrl, "dMaxValue", m_dMaxValue, OnDMaxValueChanged, VT_R8)
DISP_PROPERTY_NOTIFY(CwyMeterCtrl, "dMinValue", m_dMinValue, OnDMinValueChanged, VT_R8)
DISP_PROPERTY_NOTIFY(CwyMeterCtrl, "dCurrentValue", m_dCurrentValue, OnDCurrentValueChanged, VT_R8)
DISP_PROPERTY_NOTIFY(CwyMeterCtrl, "nScaleDecimals", m_nScaleDecimals, OnNScaleDecimalsChanged, VT_I2)
DISP_PROPERTY_NOTIFY(CwyMeterCtrl, "nValueDecimals", m_nValueDecimals, OnNValueDecimalsChanged, VT_I2)
DISP_PROPERTY_NOTIFY(CwyMeterCtrl, "colorNeedle", m_colorNeedle, OnColorNeedleChanged, VT_COLOR)
DISP_PROPERTY_NOTIFY(CwyMeterCtrl, "strUnits", m_strUnits, OnStrUnitsChanged, VT_BSTR)
DISP_FUNCTION(CwyMeterCtrl, "SetCurrentValue", SetCurrentValue, VT_EMPTY, VTS_R8)
//}}AFX_DISPATCH_MAP
DISP_FUNCTION_ID(CwyMeterCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()
// 事件映射
BEGIN_EVENT_MAP(CwyMeterCtrl, COleControl)
//{{AFX_EVENT_MAP(CwyMeterCtrl)
//}}AFX_EVENT_MAP
END_EVENT_MAP()
// 屬性頁
BEGIN_PROPPAGEIDS(CwyMeterCtrl, 1)
PROPPAGEID(CwyMeterPropPage::guid)
END_PROPPAGEIDS(CwyMeterCtrl)
// 初始化類工廠和 GUID
IMPLEMENT_OLECREATE_EX(CwyMeterCtrl, "METER.wyMeterCtrl.1",
0x15491a65, 0x5b63, 0x11d5, 0xad, 0xd3, 0, 0x10, 0x88, 0xab, 0x5d, 0x33)
// 類型庫 ID 和 版本
IMPLEMENT_OLETYPELIB(CwyMeterCtrl, _tlid, _wVerMajor, _wVerMinor)
// 接口 IDs
const IID BASED_CODE IID_DwyMeter =
{ 0x15491a63, 0x5b63, 0x11d5, { 0xad, 0xd3, 0, 0x10, 0x88, 0xab, 0x5d, 0x33 } };
const IID BASED_CODE IID_DwyMeterEvents =
{ 0x15491a64, 0x5b63, 0x11d5, { 0xad, 0xd3, 0, 0x10, 0x88, 0xab, 0x5d, 0x33 } };
// 控件類型信息
static const DWORD BASED_CODE _dwwyMeterOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CwyMeterCtrl, IDS_WYMETER, _dwwyMeterOleMisc)
// 增加和刪除系統注冊記錄
BOOL CwyMeterCtrl::CwyMeterCtrlFactory::UpdateRegistry(BOOL bRegister)
{
// 注冊控件
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_WYMETER,
IDB_WYMETER,
afxRegInsertable | afxRegApartmentThreading,
_dwwyMeterOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
//控件構造函數
CwyMeterCtrl::CwyMeterCtrl()
{
InitializeIIDs(&IID_DwyMeter, &IID_DwyMeterEvents);
//設定控件的初始大小
SetInitialSize( 90, 90 );
}
//控件析構函數
CwyMeterCtrl::~CwyMeterCtrl()
{
}
//控件繪制函數
void CwyMeterCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
// DoSuperclassPaint(pdc, rcBounds);
CBrush brush(TranslateColor(GetBackColor()));
pdc->FillRect(rcBounds,&brush);
DrawMeterBackground(pdc, rcBounds) ;
DrawNeedle(pdc) ;
DrawValue(pdc) ;
}
// 持久性支持
void CwyMeterCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
PX_Color(pPX,"colorNeedle",m_colorNeedle,RGB(255,0,0));
PX_String(pPX,"strUnits" ,m_strUnits,"v");
PX_Short(pPX,"nScaleDecimals" ,m_nScaleDecimals,0);
PX_Short(pPX,"nValueDecimals" ,m_nValueDecimals,1);
PX_Double(pPX,"dMaxValue" ,m_dMaxValue,10.0);
PX_Double(pPX,"dMinValue" ,m_dMinValue,0.0);
PX_Double(pPX,"dCurrentValue" ,m_dCurrentValue,0.0);
}
// 恢復初始狀態
void CwyMeterCtrl::OnResetState()
{
COleControl::OnResetState(); // Resets defaults found in DoPropExchange
}
//顯示About對話框
void CwyMeterCtrl::AboutBox()
{
CDialog dlgAbout(IDD_ABOUTBOX_WYMETER);
dlgAbout.DoModal();
}
// 設置窗口初始參數
BOOL CwyMeterCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
cs.lpszClass = _T("STATIC");
return COleControl::PreCreateWindow(cs);
}
// 說明是否使用基類控件
BOOL CwyMeterCtrl::IsSubclassedControl()
{
return TRUE;
}
//處理命令消息
LRESULT CwyMeterCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)
{
#ifdef _WIN32
WORD wNotifyCode = HIWORD(wParam);
#else
WORD wNotifyCode = HIWORD(lParam);
#endif
return 0;
}
//繪制指針
void CwyMeterCtrl::DrawNeedle(CDC *pDC)
{
int nResult ;
double dAngleRad ;
double dTemp ;
CBrush brushFill, *pBrushOld ;
CPen penDraw, *pPenOld ;
CPoint pointNeedle[3] ;
//這個函數繪制三角指針.基本指針是一個水平線,它通過弧線的中點
//繪制在儀表上,指尖所在的角度通過當前值和標尺計算得到.
//指針由三點構成的多邊形組成,三角形繪制在儀表的區域內.
// 計算指針的第一個和最后一個點
pointNeedle[0].x = m_nBottomCX + m_nBottomRadius/20 ;
pointNeedle[0].y = m_nBottomCY ;
pointNeedle[2].x = m_nBottomCX - m_nBottomRadius/20 ;
pointNeedle[2].y = m_nBottomCY ;
// 計算指尖的角度
dAngleRad = (m_dCurrentValue-m_dMinValue)*(m_dRightAngleRad-m_dLeftAngleRad)/
(m_dMaxValue-m_dMinValue) + m_dLeftAngleRad ;
// 如果角度超出儀表,使用最大或最小角度
dAngleRad = max(dAngleRad, m_dRightAngleRad) ;
dAngleRad = min(dAngleRad, m_dLeftAngleRad) ;
// 計算指尖的 X 坐標
dTemp = m_nBottomCX + m_nTopRadius*cos(dAngleRad) ;
pointNeedle[1].x = ROUND(dTemp) ;
// 計算指尖的 Y 坐標
dTemp = m_nBottomCY - m_nTopRadius*sin(dAngleRad) ;
pointNeedle[1].y = ROUND(dTemp) ;
// 基于儀表選擇剪貼區域
pDC->SelectClipRgn(&m_rgnBoundary) ;
// 按照指針顏色創建畫筆和刷子
brushFill.CreateSolidBrush(m_colorNeedle) ;
penDraw.CreatePen(PS_SOLID, 1, m_colorNeedle) ;
// 選擇畫筆和刷子
pPenOld = pDC->SelectObject(&penDraw) ;
pBrushOld = pDC->SelectObject(&brushFill) ;
// 繪制指針
pDC->Polygon(pointNeedle, 3) ;
// 恢復剪貼區域
nResult = pDC->SelectClipRgn(NULL) ;
// 恢復畫筆和刷子
pDC->SelectObject(pPenOld) ;
pDC->SelectObject(pBrushOld) ;
}
//輸出數值
void CwyMeterCtrl::DrawValue(CDC *pDC)
{
CFont *pFontOld ;
CString strTemp ;
// 選取字體,字體根據背景大小設定
pFontOld = pDC->SelectObject(&m_fontValue) ;
// 設定字體背景色和文本色
pDC->SetTextColor(m_colorText) ;
pDC->SetBkColor(m_colorButton) ;
// 輸出文本,文本與中點和基線對齊
pDC->SetTextAlign(TA_CENTER|TA_BASELINE) ;
strTemp.Format("%.*f", m_nValueDecimals, m_dCurrentValue) ;
pDC->TextOut(m_nValueCenter, m_nValueBaseline, strTemp) ;
// 恢復原背景色和字體
pDC->SetBkColor(m_colorWindow) ;
pDC->SelectObject(pFontOld) ;
}
//繪制背景
void CwyMeterCtrl::DrawMeterBackground(CDC *pDC, const CRect &rect)
{
int i, nAngleDeg, nRef ;
int nHeight ;
int nHalfPoints ;
int nStartAngleDeg, nEndAngleDeg ;
int nTickDeg ;
int nAngleIncrementDeg ;
double dTemp, dAngleRad, dX, dY ;
double dRadPerDeg ;
CString strTemp ;
CPoint pointRecess[BOUNDARY_POINTS] ;
CBrush brushFill, *pBrushOld ;
CFont *pFontOld ;
CPen penDraw, *pPenOld ;
TEXTMETRIC tm ;
// 計算儀表半徑的中點
m_nBottomCX = rect.right-5;
m_nBottomCY = rect.bottom -5;
// 計算儀表半徑
m_nTopRadius = rect.Height()*6/8 ;
m_nBottomRadius = m_nTopRadius/2 ;
// 每度表示的弧度數
dRadPerDeg = 4.0*atan(1.0)/180.0 ;
// 設置儀表表面區域范圍
nStartAngleDeg =90; // 60 ;
nEndAngleDeg =180; // 120 ;
nTickDeg = 15 ;
// 弧上繪制點個數
nAngleIncrementDeg = 5 ;
// 角度轉換為弧度
m_dLeftAngleRad = nEndAngleDeg*dRadPerDeg ;
m_dRightAngleRad = nStartAngleDeg*dRadPerDeg ;
// 構造儀表表面區域,它是一個多邊形區域
nRef = 0 ;
for (nAngleDeg=nStartAngleDeg; nAngleDeg<=nEndAngleDeg; nAngleDeg+=nAngleIncrementDeg)
{
// 計算當前角度的弧度數
dAngleRad = nAngleDeg*dRadPerDeg ;
// 計算 X 坐標
dTemp = m_nBottomCX + m_nTopRadius*cos(dAngleRad) ;
m_pointBoundary[nRef].x = ROUND(dTemp) ;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -