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

📄 clockctrl.cpp

📁 《Visual C++.NET MFC类库应用详解》程序实例
💻 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 + -