湖 南 农 业 大 学
VC++程序设计课程设计报告
时钟
学生姓名:XXX
学号:XXXXXXXXXXXX
QQ:XXXXXXXXX
班级:X班
年级专业:20##级计算机
指导老师及职称:X老师高级工程师
学院:XXXXXXXXXXXXXXX
湖南·长沙
提交日期:20##年6月
时钟
学生:XX
指导老师:XXX
(XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)
1.摘要:利用MFC设计制作一个能联网调时时钟,当按下F1键时,能打开或关闭帮助,单击左键是,能拖动窗口,双击左键时,能联网校时,滚动中轴时,能调整时间,单击右键,能随机变换背景颜色。
2.关键词:MFC;Clock;C++……
3.前言:
1.我们学习MFC,除了可以掌握一种Windows应用程序设计的基本方法之外,还可以使他们进一步全面、深刻地理解向对象程序设计的思想。而且MFC所蕴含的程序设计思想、代码实现技巧、则是其他开发工具所不能及的。
2.我们通过制作这个时钟,可以加深对MFC的设计思想的理解。也可以加强对C++的思想的理解。
4.正文:
4.1:窗口的创建于注册
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAlarmClockDlg dialog
CAlarmClockDlg::CAlarmClockDlg(CWnd* pParent /*=NULL*/)
: CDialog(CAlarmClockDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CAlarmClockDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_hThread = NULL;
m_bkColor = RGB(110, 200, 255);
m_bHelp = TRUE;
}
void CAlarmClockDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAlarmClockDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAlarmClockDlg, CDialog)
//{{AFX_MSG_MAP(CAlarmClockDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_LBUTTONDOWN()
ON_WM_TIMER()
ON_WM_ERASEBKGND()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_MOUSEWHEEL()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAlarmClockDlg message handlers
void CAlarmClockDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CAlarmClockDlg::OnQueryDragIcon()
{
return (HCURSOR)m_hIcon;
}
BOOL CAlarmClockDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
//1. 将窗口改成正方形
CRect rc;
this->GetWindowRect(&rc);
int iNewWH = min(rc.Width(), rc.Height());
this->MoveWindow(rc.left, rc.top, iNewWH, iNewWH);
//2. 设置绘图区域
this->GetWindowRect(&rc);
HRGN hRgn = ::CreateEllipticRgn(rc.left, rc.top, rc.right, rc.bottom);
this->SetWindowRgn(hRgn, TRUE);
//3. 设置定时器
this->SetTimer(110, 7000, NULL); //110 = Help
this->SetTimer(2359, 1000, NULL); //23:59 = move time
//4. 主动触发鼠标双击消息
this->PostMessage(WM_LBUTTONDBLCLK);
//5. 设置窗口标题
this->SetWindowText("Internet时钟");
return TRUE; // return TRUE unless you set the focus to a control
}
void CAlarmClockDlg::OnTimer(UINT nIDEvent)
{
if (nIDEvent == 2359)
{
this->Invalidate();
}
else if (nIDEvent == 110)
{
m_bHelp = FALSE;
this->KillTimer(110);
}
CDialog::OnTimer(nIDEvent);
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CAlarmClockDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
if (IsIconic())
{
SendMessage(WM_ICONERASEBKGND, (WPARAM)dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
OnDraw(&dc);
//CDialog::OnPaint();
}
}
BOOL CAlarmClockDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
// return CDialog::OnEraseBkgnd(pDC);
}
void CAlarmClockDlg::OnDraw(CDC *pDC)
{
// TODO: add draw code for native data here
/////////////////////////////////////////////////////////////////////////
//
//如下的做法能避免绘图闪烁, 强烈推荐使用. KouConghua.
//
//主要思想是将以前直接画在pDC上的图,改画到一个内存DC(如dcMem)中去,
//然后使用BitBlt函数,将dcMem这个内存中的图复制到当前屏幕即pDC中去.
//
//具体步骤如下, 其中a 和b 选择一步即可, 不可二者都做:
//a. 直接在OnDraw()中增加如下语句, 以改变窗口背景为透明色:
// ::SetClassLong(this->m_hWnd, GCL_HBRBACKGROUND,
// (LONG)(HBRUSH)::GetStockObject(NULL_BRUSH));
//b. 在CxxxView类中增加OnEraseBkgnd()消息响应函数,
// 将其中的代码改为: return TRUE;
// 直接返回TRUE表示告诉系统绘图时不再绘制背景,相当于设置窗口背景为NULL刷子.
//c. 为CxxxView类增加一个成员函数void OnDrawMem(CDC &dcMem),
// 并将你以前写在OnDraw()中的代码,移到OnDrawMem()中去即可.
//
/////////////////////////////////////////////////////////////////////////
// //1. 改变当前View窗口的背景为空刷子
// ::SetClassLong(this->m_hWnd, GCL_HBRBACKGROUND, (LONG)(HBRUSH)::GetStockObject(NULL_BRUSH));
//2. 获取当前绘图区的宽度和高度
CRect rcClient;
this->GetClientRect(&rcClient);
int nWidth = rcClient.Width();
int nHeight= rcClient.Height();
//3. 创建一个和pDC兼容的内存DC: dcMem
CDC dcMem;
dcMem.CreateCompatibleDC(pDC); //pDC换成NULL也可以,指定为显示器
//创建一个位图对象, 其宽度和高度就用当前绘图区的nWidth 和nHeight
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, nWidth, nHeight);
//将bmp选入到dcMem中, 只有选入了位图的dcMem才有地方绘图,画到指定的bmp位图上
CBitmap * pOldBit = dcMem.SelectObject(&bmp);
//4. 先用背景色将位图清除干净,这里我用的是m_bkColor作为背景
dcMem.FillSolidRect(0, 0, nWidth, nHeight, m_bkColor);
//5. 执行真正的绘图代码, 如dcMem.MoveTo(……); dcMem.LineTo(……); 等等
OnDrawMem(&dcMem);
//6. 将dcMem中的图拷贝到pDC上进行显示. 关键点.
pDC->BitBlt(0, 0, nWidth, nHeight, &dcMem, 0, 0, SRCCOPY);
//7. 绘图完成后的清理
bmp.DeleteObject();
dcMem.DeleteDC();
}
4.2:中心时间显示
void CAlarmClockDlg::OnDrawMem(CDC *pDC)
{
CRect rc;
this->GetClientRect(&rc); //获取客户区矩形
//1. 获取设备资源
CPen *pOldPen = pDC->GetCurrentPen();
CPen pen(PS_SOLID, 1, RGB(0,0,0));
pDC->SelectObject(&pen);
CBrush *pOldBrush = pDC->GetCurrentBrush();
CBrush brush; //使圆背景透明,不至于遮挡住圆心处显示的时间文本
brush.CreateStockObject(NULL_BRUSH);
pDC->SelectObject(&brush);
pDC->SetBkMode(TRANSPARENT); //设置文本背景为透明
pDC->SetTextColor(RGB(128, 0, 128)); //设置文本颜色
//2. 获取圆心和半径
POINT ptO; //圆心
int iR = min(rc.right - rc.left, rc.bottom-rc.top) / 2;
iR = iR - 10; //半径
ptO.x = (rc.right + rc.left) / 2;
ptO.y = (rc.bottom + rc.top) / 2;
//3. 取得时, 分, 秒
CString sTime;
SYSTEMTIME tm;
::GetLocalTime(&tm); //取得本地时间
float fSecond = tm.wSecond;
float fMinute = tm.wMinute + fSecond / 60.0f;
float fHour = tm.wHour % 12 + fMinute / 60.0f;
//在圆心附近显示时间
// CRect rtO(ptO.x - 40, ptO.y + 2, ptO.x + 40, ptO.y + 22);
CRect rtO(ptO.x - iR, ptO.y + 2, ptO.x + iR, ptO.y + iR);
sTime.Format("%.2d:%.2d:%.2d", tm.wHour, tm.wMinute, tm.wSecond);
pDC->DrawText(sTime, &rtO, DT_CENTER);
4.3:画时钟
算法:时钟的秒刻度分为60个刻度,每个刻度是6°
四个象限的刻度尺的算法如下:
//第一象限
for(int i=0;i<16;i++)
{
POINT pt0;
pt0.x = ptOrigin.x + iR * sin( PI/180 * 6*i) * 0.95f;
pt0.y = ptOrigin.y - iR * cos( PI/180 * 6*i) * 0.95f;
SetPixel(hdc,pt0.x,pt0.y,RGB(255,0,0));
}
//第四象限
for(i=1;i<16;i++)
{
POINT pt0;
pt0.x = ptOrigin.x + iR * cos( PI/180 * 6*i) * 0.95f;
pt0.y = ptOrigin.y + iR * sin( PI/180 * 6*i) * 0.95f;
SetPixel(hdc,pt0.x,pt0.y,RGB(255,0,0));
}
//第三象限
for(i=1;i<16;i++)
{
POINT pt0;
pt0.x = ptOrigin.x - iR * sin( PI/180 * 6*i) * 0.95f;
pt0.y = ptOrigin.y + iR * cos( PI/180 * 6*i) * 0.95f;
SetPixel(hdc,pt0.x,pt0.y,RGB(255,0,0));
}
//第二象限
for(i=1;i<15;i++)
{
POINT pt0;
pt0.x = ptOrigin.x - iR * cos( PI/180 * 6*i) * 0.95f;
pt0.y = ptOrigin.y - iR * sin( PI/180 * 6*i) * 0.95f;
SetPixel(hdc,pt0.x,pt0.y,RGB(255,0,0));
}
根据:
sin(PI/2+α)=cosα
cos(π/2+α)=-sinα
第四象限可以写成
for(int i=16;i<32;i++)
{
POINT pt0;
pt0.x = ptOrigin.x + iR * sin( PI/180 * 6*i) * 0.95f;
pt0.y = ptOrigin.y - iR * cos( PI/180 * 6*i) * 0.95f;
SetPixel(hdc,pt0.x,pt0.y,RGB(255,0,0));
}
根据:
sin(π+α)=-sinα
cos(π+α)=-cosα
第三象限可以写成:
for(int i=32;i<48;i++)
{
POINT pt0;
pt0.x = ptOrigin.x + iR * sin( PI/180 * 6*i) * 0.95f;
pt0.y = ptOrigin.y - iR * cos( PI/180 * 6*i) * 0.95f;
SetPixel(hdc,pt0.x,pt0.y,RGB(255,0,0));
}
根据:
sin(3π/2+α)=-cosα
cos(3π/2+α)=sinα
第二象限可以写成
for(int i=48;i<60;i++)
{
POINT pt0;
pt0.x = ptOrigin.x + iR * sin( PI/180 * 6*i) * 0.95f;
pt0.y = ptOrigin.y - iR * cos( PI/180 * 6*i) * 0.95f;
SetPixel(hdc,pt0.x,pt0.y,RGB(255,0,0));
}
最后统一成:
for(int i=0;i<60;i++)
{
POINT pt0;
pt0.x = ptOrigin.x + iR * sin( PI/180 * 6*i) * 0.95f;
pt0.y = ptOrigin.y - iR * cos( PI/180 * 6*i) * 0.95f;
SetPixel(hdc,pt0.x,pt0.y,RGB(255,0,0));
}
所以有程序代码如下:
// pDC->Ellipse(ptO.x - iR, ptO.y - iR, ptO.x + iR, ptO.y + iR);
//4.1 画秒刻度
pen.DeleteObject();
pen.CreatePen(PS_SOLID, 1, RGB(0,0,0));
pDC->SelectObject(&pen);
for (int i = 0; i < 60; i++)
{
POINT ptA, ptB;
ptA.x = ptO.x + iR * sin( PI/30 * i) * 0.98f;
ptA.y = ptO.y - iR * cos( PI/30 * i) * 0.98f;
ptB.x = ptO.x + iR * sin( PI/30 * i) * 1.00f;
ptB.y = ptO.y - iR * cos( PI/30 * i) * 1.00f;
pDC->MoveTo(ptA.x, ptA.y);
pDC->LineTo(ptB.x, ptB.y);
}
//4.2 画小时刻度
pen.DeleteObject();
pen.CreatePen(PS_SOLID, 2, RGB(0,0,0));
pDC->SelectObject(&pen);
for (i = 0; i < 60; i = i + 5)
{
POINT ptA, ptB;
ptA.x = ptO.x + iR * sin( PI/30 * i) * 0.95f;
ptA.y = ptO.y - iR * cos( PI/30 * i) * 0.95f;
ptB.x = ptO.x + iR * sin( PI/30 * i) * 1.00f;
ptB.y = ptO.y - iR * cos( PI/30 * i) * 1.00f;
pDC->MoveTo(ptA.x, ptA.y);
pDC->LineTo(ptB.x, ptB.y);
//写出小时数字
int j = i/5;
if (j == 0) j = 12;
CString sTime;
sTime.Format("%d", j);
POINT ptN;
ptN.x = ptO.x + iR * sin( PI/30 * i) * 0.87f;
ptN.y = ptO.y - iR * cos( PI/30 * i) * 0.87f;
CRect rtN(ptN.x - 10, ptN.y - 10, ptN.x + 10, ptN.y + 10);
pDC->DrawText(sTime, &rtN, DT_CENTER | DT_VCENTER);
}
//5. 画秒针 60s = 2*PI, 1s = PI / 30
pen.DeleteObject();
pen.CreatePen(PS_SOLID, 1, RGB(0,0,255));
pDC->SelectObject(&pen);
POINT ptSecond;
ptSecond.x = ptO.x + iR * sin( PI/30 * fSecond) * 0.94f;
ptSecond.y = ptO.y - iR * cos( PI/30 * fSecond) * 0.94f;
pDC->MoveTo(ptO.x, ptO.y);
pDC->LineTo(ptSecond.x, ptSecond.y);
//6. 画分针 60m = 2*PI, 1m = PI / 30
pen.DeleteObject();
pen.CreatePen(PS_SOLID, 2, RGB(255,0,0));
pDC->SelectObject(&pen);
POINT ptMinute;
ptMinute.x = ptO.x +iR * sin( PI/30 * fMinute) * 0.84f;
ptMinute.y = ptO.y - iR * cos( PI/30 * fMinute) * 0.84f;
pDC->MoveTo(ptO.x, ptO.y);
pDC->LineTo(ptMinute.x, ptMinute.y);
//7. 画时针 12h = 2*PI, 1h = PI / 6
pen.DeleteObject();
pen.CreatePen(PS_SOLID, 3, RGB(255,0,255));
pDC->SelectObject(&pen);
POINT ptHour;
ptHour.x = ptO.x + iR * sin( PI/6 * fHour) * 0.71f;
ptHour.y = ptO.y - iR * cos( PI/6 * fHour) * 0.71f;
pDC->MoveTo(ptO.x, ptO.y);
pDC->LineTo(ptHour.x, ptHour.y);
4.4:显示帮助信息及其相关操作
//帮助信息, 显示7s后关闭
if (m_bHelp)
{
CString sHelp;
sHelp += "按下F1键: 帮助开关\r\n";
sHelp += "单击左键: 拖动窗口\r\n";
sHelp += "双击左键: 联网校时\r\n";
sHelp += "滚动中轴: 调整时间\r\n";
sHelp += "单击右键: 随机背景\r\n";
sHelp += "按Esc 键: 退出程序\r\n";
if (int(fHour) % 12 >= 3 && (int)fHour % 12 < 9)
{
CRect rtHelp(ptO.x - iR, ptO.y - iR * 7 / 10, ptO.x + iR, ptO.y + iR * 3 / 10);
pDC->DrawText(sHelp, &rtHelp, DT_CENTER | DT_VCENTER);
}
else
{
CRect rtHelp(ptO.x - iR, ptO.y + iR / 5, ptO.x + iR, ptO.y + iR * 4 / 5);
pDC->DrawText(sHelp, &rtHelp, DT_CENTER | DT_VCENTER);
}
}
//8. 恢复现场, 释放资源
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
pen.DeleteObject();
brush.DeleteObject();
}
//移动无标题窗口
void CAlarmClockDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
this->SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0);
CDialog::OnLButtonDown(nFlags, point);
}
//Internet校时
void CAlarmClockDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
if (m_hThread) ::TerminateThread(m_hThread, -1);
m_hThread = ::CreateThread(NULL, 0, SetInternetTimeProc, this, 0, NULL);
CDialog::OnLButtonDblClk(nFlags, point);
}
//随机背景
void CAlarmClockDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
::srand(::GetTickCount());
m_bkColor = RGB(rand() * 100 % 255, rand() * 100 % 255, rand() * 100 % 255);
this->Invalidate();
CDialog::OnRButtonDown(nFlags, point);
}
//调整时间
BOOL CAlarmClockDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
// TODO: Add your message handler code here and/or call default
SYSTEMTIME tm;
::GetLocalTime(&tm);
COleDateTime now = COleDateTime::GetCurrentTime();
now += COleDateTimeSpan(0, 0, zDelta > 0 ? -1 : 1, 0); // 1 Minute exactly
tm.wHour = now.GetHour();
tm.wMinute = now.GetMinute();
tm.wSecond = 0;//now.GetSecond();
::SetLocalTime(&tm);
this->Invalidate();
return CDialog::OnMouseWheel(nFlags, zDelta, pt);
}
//键盘控制
void CAlarmClockDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
switch (nChar)
{
case VK_ESCAPE:
CDialog::OnOK();
break;
case VK_HOME:
this->SendMessage(WM_LBUTTONDBLCLK);
break;
case VK_END:
SYSTEMTIME tm;
::GetLocalTime(&tm);
tm.wHour = 0;
tm.wMinute = 0;
tm.wSecond = 0;
::SetLocalTime(&tm);
this->Invalidate();
break;
case VK_DOWN:
case VK_RIGHT:
case VK_NEXT:
OnMouseWheel(0, -1, 0);
break;
case VK_UP:
case VK_LEFT:
case VK_PRIOR:
OnMouseWheel(0, 1, 0);
break;
}
//CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}
//帮助信息
void CAlarmClockDlg::WinHelp(DWORD dwData, UINT nCmd)
{
// TODO: Add your specialized code here and/or call the base class
m_bHelp = !m_bHelp;
if (m_bHelp)
this->SetTimer(110, 7000, NULL);
else
this->KillTimer(110);
this->Invalidate();
//CDialog::WinHelp(dwData, nCmd);
}
//将当前系统时间设置为从Internet取得的标准时间
DWORD CAlarmClockDlg::SetInternetTimeProc(LPVOID lpParameter)
{
CAlarmClockDlg *pDlg = (CAlarmClockDlg *)lpParameter;
DWORD bRet = FALSE;
//创建TCP套接字
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
pDlg->m_hThread = NULL;
return FALSE;
}
//设置接收超时时间为2s
int nTimeout = 2000;
::setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(nTimeout));
//时间服务器IP地址
char *szServer[] = {
"128.138.140.44", "132.163.4.101", "132.163.4.102", "132.163.4.103",
"192.43.244.18", "131.107.1.10", "66.243.43.21",
"216.200.93.8", "208.184.49.9", "207.126.98.204",
"207.200.81.113", "205.188.185.33", "216.218.254.202", "209.81.9.7",
"time.stdtime.gov.tw","time-a.nist.gov","clepsydra.dec.com",
"time.windows.com", "5time.nist.gov", "clock.sgi.com", "tick.mit.edu",
"210.72.145.44", "129.6.15.29", "129.6.15.28", "time.nuri.net",
};
//尝试连接不同的服务器
BOOL bConnect = FALSE;
for (int i = 0; i < dim(szServer); i++)
{
SOCKADDR_IN sa;
sa.sin_family = AF_INET ;
sa.sin_port = htons(IPPORT_TIMESERVER);
sa.sin_addr.S_un.S_addr = inet_addr(szServer[i]) ; // sa.sin_addr.S_un.S_addr = inet_addr ("132.163.4.101") ;
if (0 == connect(sock, (SOCKADDR *)&sa, sizeof(sa)))
{
bConnect = TRUE;
TRACE("\r\nOK: %s\r\n\r\n", szServer[i]);
break;
}
}
if (!bConnect)
{
closesocket(sock) ;
pDlg->m_hThread = NULL;
return FALSE;
}
while (TRUE)
{
::Sleep(1);
ULONG ulTime = 0;
int iBytesRecv = recv(sock, (char *)&ulTime, sizeof(ulTime), 0);
if (iBytesRecv > 0)
{
ulTime = ntohl(ulTime); //ulTime += 8*60*60; //加8小时,就是北京时间
//ulTime = Now - 1900.1.1 00:00:00 此时的ulTime是自1900.1.1子夜到现在时间之间的秒数 !!!!!!!!!!
// 1900.1.1-->SYSTEMTIME-->FILETIME-->LARGE_INTEGER
SYSTEMTIME stNew;
stNew.wYear = 1900; stNew.wMonth = 1; stNew.wDay = 1;
stNew.wHour = 0; stNew.wMinute = 0; stNew.wSecond = 0 ; stNew.wMilliseconds = 0;
FILETIME ftNew;
SystemTimeToFileTime(&stNew, &ftNew);
LARGE_INTEGER liTime = *(LARGE_INTEGER *)&ftNew; //用64位大整数表示1900.1.1
//加上从服务器获取的秒数: ulTime
liTime.QuadPart += (LONGLONG)10000000 * ulTime; //1900.1.1 + ulTime
//LARGE_INTEGER-->FILETIME-->SYSTEMTIME-->2011.6.12.
ftNew = *(FILETIME *)&liTime;
FileTimeToSystemTime(&ftNew, &stNew);
//改变系统时间
// 将当前的Internet时间转化为 20080101 和 235959 这种数字型格式
LONGLONG llNetDate = stNew.wYear * 10000 + stNew.wMonth * 100 + stNew.wDay;
//LONGLONG llNetTime = stNew.wHour * 10000 + stNew.wMinute * 100 + stNew.wSecond;
if (llNetDate > 19000101)
{
bRet = SetSystemTime(&stNew);
break;
}
}
}
closesocket (sock) ;
sock = NULL;
pDlg->m_hThread = NULL;
return bRet;
}
5.结论:通过这次的课程设计的训练,深刻体会到了自己在这方面还很不足,需要加强,就像老师说的还有很大的提升空间,同时,也感觉学好C++很有用的,编出程序的那一刻还是很高兴的,因此,这次的最大的收获就是培养出了自己对C++的兴趣。我通过这次的学习,知道了,学习C++,最重要的是自己动手的能力,光靠课堂上的知识是无法编出自己的程序的,在课后,我们一定要自己多动手,这样才有可能学好C++。
参考文献
[1] 任哲等编著《MFC Windows应用程序设计(第二版)》,出版年:20##年9月,卷(期):第二版。
[2] 课堂上提供的程序代码。
致 谢
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX