📄 clockctrl.cpp
字号:
// ClockCtrl.cpp : CClockCtrl ActiveX 控件类的实现。
#include "stdafx.h"
#include "Clock.h"
#include "ClockCtrl.h"
#include "ClockPropPage.h"
#include "NewPropPage.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
const double PI=3.1415926;
IMPLEMENT_DYNCREATE(CClockCtrl, COleControl)
// 消息映射
BEGIN_MESSAGE_MAP(CClockCtrl, COleControl)
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
ON_WM_CREATE()
ON_WM_TIMER()
END_MESSAGE_MAP()
// 调度映射
BEGIN_DISPATCH_MAP(CClockCtrl, COleControl)
DISP_FUNCTION_ID(CClockCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
DISP_STOCKPROP_BACKCOLOR()
DISP_STOCKPROP_FORECOLOR()
DISP_PROPERTY_NOTIFY_ID(CClockCtrl, "hourPosColor", dispidhourPosColor, m_hourPosColor, OnhourPosColorChanged, VT_COLOR)
DISP_PROPERTY_NOTIFY_ID(CClockCtrl, "PenWidth", dispidPenWidth, m_PenWidth, OnPenWidthChanged, VT_I2)
DISP_PROPERTY_NOTIFY_ID(CClockCtrl, "FactoryName", dispidFactoryName, m_FactoryName, OnFactoryNameChanged, VT_BSTR)
DISP_FUNCTION_ID(CClockCtrl, "StartTimekeeper", dispidStartTimekeeper, StartTimekeeper, VT_EMPTY, VTS_NONE)
DISP_FUNCTION_ID(CClockCtrl, "KillTimekeeper", dispidKillTimekeeper, KillTimekeeper, VT_I4, VTS_NONE)
DISP_FUNCTION_ID(CClockCtrl, "SetActiveTime", dispidSetActiveTime, SetActiveTime, VT_EMPTY, VTS_I2 VTS_I2 VTS_I2)
END_DISPATCH_MAP()
// 事件映射
BEGIN_EVENT_MAP(CClockCtrl, COleControl)
EVENT_STOCK_CLICK()
EVENT_STOCK_DBLCLICK()
EVENT_STOCK_KEYDOWN()
EVENT_STOCK_KEYPRESS()
EVENT_STOCK_KEYUP()
EVENT_STOCK_MOUSEDOWN()
EVENT_STOCK_MOUSEMOVE()
EVENT_STOCK_MOUSEUP()
EVENT_STOCK_ERROREVENT()
EVENT_CUSTOM_ID("ActiveWhen", eventidActiveWhen, ActiveWhen, VTS_I2 VTS_I2 VTS_I2)
END_EVENT_MAP()
// 属性页
// TODO: 按需要添加更多属性页。请记住增加计数!
BEGIN_PROPPAGEIDS(CClockCtrl, 3)
PROPPAGEID(CClockPropPage::guid)
PROPPAGEID(CLSID_CColorPropPage)
PROPPAGEID(CNewPropPage::guid)
END_PROPPAGEIDS(CClockCtrl)
// 初始化类工厂和 guid
IMPLEMENT_OLECREATE_EX(CClockCtrl, "CLOCK.ClockCtrl.1",
0x704186e9, 0x470c, 0x480c, 0x90, 0x36, 0xd3, 0x9, 0xb9, 0xb7, 0xac, 0xcf)
// 键入库 ID 和版本
IMPLEMENT_OLETYPELIB(CClockCtrl, _tlid, _wVerMajor, _wVerMinor)
// 接口 ID
const IID BASED_CODE IID_DClock =
{ 0x8B547525, 0x468E, 0x451E, { 0x98, 0x75, 0x69, 0xFE, 0x99, 0x10, 0xBE, 0xD6 } };
const IID BASED_CODE IID_DClockEvents =
{ 0x893DFA19, 0x866C, 0x4D2C, { 0x9B, 0xB1, 0x8F, 0xC9, 0x22, 0x33, 0x69, 0x3B } };
// 控件类型信息
static const DWORD BASED_CODE _dwClockOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CClockCtrl, IDS_CLOCK, _dwClockOleMisc)
// CClockCtrl::CClockCtrlFactory::UpdateRegistry -
// 添加或移除 CClockCtrl 的系统注册表项
BOOL CClockCtrl::CClockCtrlFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: 验证您的控件是否符合单元模型线程处理规则。
// 有关更多信息,请参考 MFC 技术说明 64。
// 如果您的控件不符合单元模型规则,则
// 必须修改如下代码,将第六个参数从
// afxRegApartmentThreading 改为 0。
if (bRegister)
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_CLOCK,
IDB_CLOCK,
afxRegApartmentThreading,
_dwClockOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
// CClockCtrl::CClockCtrl - 构造函数
CClockCtrl::CClockCtrl()
{
InitializeIIDs(&IID_DClock, &IID_DClockEvents);
// TODO: 在此初始化控件的实例数据。
m_oldHour=0;
m_oldMin=0;
m_oldSec=0;
m_hourAngle=0.0;
m_minAngle=0.0;
m_secAngle=0.0;
m_setHour=-1;
m_setMin=-1;
m_setSec=-1;
}
// CClockCtrl::~CClockCtrl - 析构函数
CClockCtrl::~CClockCtrl()
{
// TODO: 在此清理控件的实例数据。
}
// CClockCtrl::OnDraw - 绘图函数
void CClockCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,
const CRect& rcInvalid)
{
// TODO: 用您自己的绘图代码替换下面的代码。
//pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
//pdc->Ellipse(rcBounds);
// 先用GetBackColor获取控件的背景颜色属性,然后用该颜色来生成画刷,
// 填充钟表所占的区域(由rcBounds指定)
CBrush brush(TranslateColor(GetBackColor()));
pdc->FillRect(rcBounds, &brush);
// 计算表盘中心和半径
int r,xc,yc;
if(rcBounds.Width()>rcBounds.Height())
r=rcBounds.Height()/2;
else
r=rcBounds.Width()/2;
xc=rcBounds.right/2;
yc=rcBounds.bottom/2;
// 用控件的前景色属性画出分针和秒针刻度
CPen pen1(PS_SOLID,1,TranslateColor(GetForeColor()));
CPen *oldPen=pdc->SelectObject(&pen1);
int i;
for(i=0;i<60;i++)
{
pdc->MoveTo(xc+(r-16)*sin(PI*i/30.0),yc-(r-16)*cos(PI*i/30.0));
pdc->LineTo(xc+(r-10)*sin(PI*i/30.0),yc-(r-10)*cos(PI*i/30.0));
}
// 用自定义属性m_hourPosColor和m_penWidth画出时针刻度
CPen pen2(PS_SOLID,m_PenWidth,TranslateColor(m_hourPosColor));
oldPen=pdc->SelectObject(&pen2);
for(i=0;i<12;i++)
{
pdc->MoveTo(xc+(r-24)*sin(PI*i/6.0),yc-(r-24)*cos(PI*i/6.0));
pdc->LineTo(xc+(r-10)*sin(PI*i/6.0),yc-(r-10)*cos(PI*i/6.0));
}
pdc->SelectObject(oldPen);
// 画出当前时刻的时针、分针和秒针
DrawPointer(pdc,rcBounds,40,8,10,m_hourAngle);
DrawPointer(pdc,rcBounds,20,6,10,m_minAngle);
DrawPointer(pdc,rcBounds,10,3,15,m_secAngle);
//画出时针、分针和秒针的轴
pdc->Ellipse(xc-4,yc-4,xc+4,yc+4);
// 用自定义属性m_factoryName显示钟表的制造厂商
pdc->TextOut(xc-40,yc+20,m_FactoryName);
}
// CClockCtrl::DoPropExchange - 持久性支持
void CClockCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: 为每个持久的自定义属性调用 PX_ 函数。
PX_Color(pPX,"hourPosColor",m_hourPosColor,RGB(0,255,255));
PX_Short(pPX,"PenWidth",m_PenWidth,2);
PX_String(pPX,"FactoryName",m_FactoryName,"Made in China");
}
// CClockCtrl::OnResetState - 将控件重置为默认状态
void CClockCtrl::OnResetState()
{
COleControl::OnResetState(); // 重置 DoPropExchange 中找到的默认值
// TODO: 在此重置任意其他控件状态。
}
// CClockCtrl::AboutBox - 向用户显示“关于”框
void CClockCtrl::AboutBox()
{
CDialog dlgAbout(IDD_ABOUTBOX_CLOCK);
dlgAbout.DoModal();
}
// CClockCtrl 消息处理程序
void CClockCtrl::OnhourPosColorChanged(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加属性处理程序代码
InvalidateControl();
SetModifiedFlag();
}
void CClockCtrl::OnPenWidthChanged(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加属性处理程序代码
InvalidateControl();
SetModifiedFlag();
}
void CClockCtrl::OnFactoryNameChanged(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加属性处理程序代码
InvalidateControl();
SetModifiedFlag();
}
void CClockCtrl::StartTimekeeper(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加调度处理程序代码
struct tm *osTime;
CTime t=CTime::GetCurrentTime(); // 获得当前时间
osTime=t.GetLocalTm(NULL);
m_oldHour=osTime->tm_hour; // 保存当前时间
m_oldMin=osTime->tm_min;
m_oldSec=osTime->tm_sec;
SetPointerPos(); //计算时针、分针、秒针在表盘上的位置
InvalidateControl();
}
LONG CClockCtrl::KillTimekeeper(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加调度处理程序代码
long seconds;
struct tm *osTime;
CTime t=CTime::GetCurrentTime();
osTime=t.GetLocalTm(NULL);
seconds=(osTime->tm_hour-m_oldHour)*3600+
(osTime->tm_min-m_oldMin)*60+osTime->tm_sec-m_oldSec;
m_oldHour=0;
m_oldMin=0;
m_oldSec=0;
SetPointerPos();
InvalidateControl();
return (long)seconds;
}
void CClockCtrl::SetPointerPos()
{
struct tm *osTime;
CTime t=CTime::GetCurrentTime(); // 获得当前时间
osTime=t.GetLocalTm(NULL);
short hour,min,sec;
hour=osTime->tm_hour-m_oldHour; // 计算计时开始时到现在的时间差,
min=osTime->tm_min-m_oldMin; //若为非计时状态,则为当前时间值
sec=osTime->tm_sec-m_oldSec;
m_hourAngle=PI*(hour+min/60.0)/6.0; // 计算时针的位置
m_minAngle=PI*(min+sec/60.0)/30.0; //计算分针的位置
m_secAngle=PI*sec/30.0; //计算秒针的位置
if(osTime->tm_hour==m_setHour && osTime->tm_min==m_setMin &&
osTime->tm_sec==m_setSec)
ActiveWhen(m_setHour,m_setMin,m_setSec);
}
void CClockCtrl::SetActiveTime(SHORT hour, SHORT min, SHORT sec)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加调度处理程序代码
m_setHour=hour;
m_setMin=min;
m_setSec=sec;
}
void CClockCtrl::DrawPointer(CDC *pDC,CRect rect,double d1,
double d2,double d3,double angle)
{
int r,xc,yc;
if(rect.Width()>rect.Height())
r=rect.Height()/2;
else
r=rect.Width()/2;
xc=rect.right/2;
yc=rect.bottom/2;
CPoint points[4];
points[0].x=xc+(r-d1)*sin(angle);
points[0].y=yc-(r-d1)*cos(angle);
points[1].x=xc-d2*cos(angle);
points[1].y=yc-d2*sin(angle);
points[2].x=xc-d3*sin(angle);
points[2].y=yc+d3*cos(angle);
points[3].x=xc+d2*cos(angle);
points[3].y=yc+d2*sin(angle);
pDC->SetBkMode(TRANSPARENT);
pDC->Polygon(points,4);
}
int CClockCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
m_timer=SetTimer(1,1000,NULL);
return 0;
}
void CClockCtrl::OnTimer(UINT nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
SetPointerPos();
InvalidateControl();
COleControl::OnTimer(nIDEvent);
}
BOOL CClockCtrl::DestroyWindow()
{
// TODO: 在此添加专用代码和/或调用基类
KillTimer(m_timer);
return COleControl::DestroyWindow();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -