最近在学习一个时钟显示程序,觉得其中有好多值得细细体会、分析的地方。为了记住这些精妙之处,我把自己的这些理解和体会一并写在这个博客里,以备自己以后查询,也希望给正在学习这个程序的网友一个参考。

先上这个程序的运行效果图:

一、映射模式与时钟的“时针”、“分针”和“秒针”的摆动显示

时钟运行显示时间时,时、分和秒针在程序代码中摆动时,程序代码是如何绘制才符合时钟显示的运行规律的呢?这部分代码,是我学习这个程序时最让我难以理解的地方。程序中绘制时、分、秒针摆动的代码主要涉及两个函数:

1、绘制时针、分针的函数:

void CMainWindow::DrawHand (CDC* pDC, int nLength, int nScale,int nDegrees, COLORREF clrColor)

2、绘制秒针的函数:

void CMainWindow::DrawSecondHand (CDC* pDC, int nLength, int nScale,int nDegrees, COLORREF clrColor)

两个函数都需要解决以下几个问题:

1、时、分、秒针本身(外观形状)如何绘制?

2、怎样根据当时的时间(时、分、秒)把时针、分针和秒针绘制并指向对应时间点上呢?

经过仔细思考分析,我终于理解到了其中的思路:

首先,解决绘图的坐标系和绘图映射模式问题。

由于时钟显示时,钟的针是以圆心为轴,顺时针方向旋转摆动显示的。为了计算方便,有必要把坐标原点确定在时钟圆盘的中心,坐标系也要调整成x轴向右为正,y轴向上为正的模式。要实现这个目的,涉及到vc++绘图映射模式的设置。以下是代码实现:

 CRect rect;GetClientRect(&rect);CClientDC dc(this);dc.SetMapMode(MM_ISOTROPIC);dc.SetWindowExt(1000, 1000);dc.SetViewportExt(rect.Width(), -rect.Height());dc.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);

由于使用了MM_ISOTROPIC自定义映射模式, 它使得在横、纵两个方向的缩放比例相同。就是不管窗口的水平、垂直两个方向的长度如何变化,程序总是会自动调整并按短的一边(水平和垂直短的一边)为准显示,保持横、纵比例相同。

程序中把显示的逻辑窗口设置为(1000,1000)的区域,与之对应的视窗区域却是(rect.Width(),-rect.Height())。尽管窗口的水平和垂直两个方向的长度可能不同,由于映射模式为MM_ISOTROPIC模式,所以程序会自动调整显示。由于还设置了视窗中心为新的坐标原点(dc.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);),所以,(1000,1000)的逻辑区域总是会被显示到视窗区域的中心部分——一个正方形的区域,以短的一边(水平方向或垂直方向短的一边)为边长。看看下面程序运行的几种效果图即可知道了:

需要强调说明的是:SetViewportExt ()第二个参数为负值,因此逻辑坐标系在视窗显示时,相当于:原点位于视窗中心上,x轴向右为正,y轴向上为正。如下图所示:

明白这一点很重要,后面时钟的针的绘制显示才能正确理解。

其次,解决时钟的时、分和秒针的指向摆动问题。

时针一圈分12个小时,有12个刻度,每摆动一个刻度,角度为360/12=30度;

分钟一圈分60分,有60个刻度,每摆动一个刻度,角度为360/60=6度;

秒针一圈分60秒,有60个刻度,每摆动一个刻度,角度为360/60=6度。

摆动角度的规律很明显,但如何绘制一定时间对应的时针、分针和秒针呢?这里当然要用到“三角函数”了。不过且慢,三角函数中使用的角,是以x轴正方向为起始沿逆时针或顺时针旋转而成,而在本程序中,时钟针的起点以y轴正方向为起始,沿顺时针方向而成。假设以y轴正方向为起始,沿顺时针方向旋转的角度为a,针尖所在点为A,从原点到针A点的长度为r。则A点的坐标:(r*cos(a),r*sin(a))是完全不正确的,因为它不是我们平常所用的三角函数的那种角度,起始边不一样。怎么办呢?看下图:

由上图可知:不管角度a位于哪一个象限,都可以相当于:--a这个以x轴正方向开始的,沿顺时针方向形成的角的三角函数值,根据三角函数公式,即可推出A点坐标为(sin(a),cos(a))。(以上坐标是 r 假设为1的值,程序中r实际为450)这样,时针分针秒针的针尖点的坐标就根据角度得到了。代码实现为:

        CPoint point[4];double nRadians = (double)nDegrees*0.017453292;point[0].x = (int)(nLength*sin(nRadians));point[0].y = (int)(nLength*cos(nRadians));point[2].x = -point[0].x / nScale;point[2].y = -point[0].y / nScale;point[1].x = -point[2].y;point[1].y = point[2].x;point[3].x = -point[1].x;point[3].y = -point[1].y;

其中,nRadians表示角度的弧度值。point[0]即为时分秒针的尖点坐标。

另外:point[2]点与point[0]关于原点对称,只不过离坐标原点的距离是针尖点离坐标原点的距离的几分之一而已。

point[1]是point[2]点逆时针旋转90度而形成,因此它的横坐标值是point[2]纵坐标的相反数,它的纵坐标值是point[2]的横坐标值。

point[4]与point[1]关于坐标原点对称,其坐标值刚好都与point[1]的坐标值相反。

这些坐标点最后连结成线形成的形状,就是时针、分针和秒针的外观,并且针尖点指向对应的时、分和秒钟的时间刻度!

以上即是时钟显示时,时钟外观显示及指向摆动问题的解决思路。也是这个程序里面最核心的问题所在。

以下为部分原代码:

void CMainWindow::DrawHand (CDC* pDC, int nLength, int nScale,int nDegrees, COLORREF clrColor)
{CPoint point[4];double nRadians = (double)nDegrees*0.017453292;point[0].x = (int)(nLength*sin(nRadians));point[0].y = (int)(nLength*cos(nRadians));point[2].x = -point[0].x / nScale;point[2].y = -point[0].y / nScale;point[1].x = -point[2].y;point[1].y = point[2].x;point[3].x = -point[1].x;point[3].y = -point[1].y;CPen pen(PS_SOLID, 0, clrColor);CPen *pOldPen = pDC->SelectObject(&pen);pDC->MoveTo(point[0]);pDC->LineTo(point[1]);pDC->LineTo(point[2]);pDC->LineTo(point[3]);pDC->LineTo(point[0]);pDC->SelectObject(pOldPen);}void CMainWindow::DrawSecondHand (CDC* pDC, int nLength, int nScale,int nDegrees, COLORREF clrColor)
{double nRadians = (double)nDegrees * 0.017453292;CPoint point[2];point[0].x = (int)(nLength * sin(nRadians));point[0].y = (int)(nLength * cos(nRadians));point[1].x = -point[0].x / nScale;point[1].y = -point[0].y / nScale;CPen pen(PS_SOLID, 0, clrColor);CPen *pOldPen=pDC->SelectObject(&pen);pDC->MoveTo(point[0]);pDC->LineTo(point[1]);pDC->SelectObject(pOldPen);}

二、定时器及定时器消息

时钟程度,必须要时时根据时间的变化而更新时钟的显示。时间的更新,是用定时器每秒(或更短的时间)产生的WM_TIMER事件来实现的。vc++中实现的函数为:

CWnd::SetTimer

UINT_PTR SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) );

CWnd::KillTimer

BOOL KillTimer( int nIDEvent );

前一个函数是建立定时器,后一个是删除定时器函数。

创建定时器,第一个参数为定时器的id值,用以标志定时器。删除定时器时,也是以这个id值来删除的。第二个参数为时间间隔,设置两个定时器事件之间的时间间隔。第三个参数为NULL或回调函数。NULL时,定时器产生WM_TIMER事件;如果是回调函数,定时器事件的处理就交给回调函数去处理。

回调函数的原型为:

static void CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT_PTR nIDEvent, DWORD dwTime);

其中TimerProc是回调函数的名称,可以自己任意设置。回调函数应为静态函数!!!切记!!!

定时器事件的处理,原代码为:

void CMainWindow::OnTimer(UINT_PTR nIDEvent)
{if (IsIconic())return;CTime time = CTime::GetCurrentTime();int nHour = time.GetHour()%12;int nMinute= time.GetMinute();int nSecond = time.GetSecond();if ((nHour == m_nPrevHour) &&(nMinute == m_nPrevMinute) &&(nSecond == m_nPrevSecond))return;COLORREF clrColor = ::GetSysColor(COLOR_3DFACE );CRect rect;GetClientRect(&rect);CClientDC dc(this);dc.SetMapMode(MM_ISOTROPIC);dc.SetWindowExt(1000, 1000);dc.SetViewportExt(rect.Width(), -rect.Height());dc.SetViewportOrg(rect.Width() / 2, rect.Height() / 2);if (nMinute != m_nPrevMinute) {DrawHand(&dc, 200, 4, (m_nPrevHour * 30) + (m_nPrevMinute / 2), clrColor);DrawHand(&dc, 400, 8, m_nPrevMinute * 6, clrColor);m_nPrevHour = nHour;m_nPrevMinute = nMinute;}if (nSecond != m_nPrevSecond) {DrawSecondHand(&dc, 400, 8, m_nPrevSecond * 6, clrColor);DrawHand(&dc, 200, 4, (nHour * 30) + (nMinute / 2), RGB(0, 0, 0));DrawHand(&dc, 400, 8, nMinute * 6, RGB(0, 0, 0));DrawSecondHand(&dc, 400, 8, nSecond * 6, RGB(0, 0, 0));m_nPrevSecond = nSecond;}CFrameWnd::OnTimer(nIDEvent);
}

另外,时钟显示还需要有一个时钟圆盘作为一个背景。这个是在OnPaint()事件中完成的,原代码为:

void CMainWindow::OnPaint ()
{CRect rect;GetClientRect (&rect);CPaintDC dc (this);dc.SetMapMode (MM_ISOTROPIC);dc.SetWindowExt (1000, 1000);dc.SetViewportExt (rect.Width (), -rect.Height ());dc.SetViewportOrg (rect.Width () / 2, rect.Height () / 2);DrawClockFace (&dc);DrawHand (&dc, 200, 4, (m_nPrevHour * 30) +(m_nPrevMinute / 2), RGB (0, 0, 0));DrawHand (&dc, 400, 8, m_nPrevMinute * 6, RGB (0, 0, 0));DrawSecondHand (&dc, 400, 8, m_nPrevSecond * 6, RGB (0, 0, 0));}void CMainWindow::DrawClockFace (CDC* pDC)
{static CPoint point[12] = {CPoint (   0,  450),    // 12 o'clockCPoint ( 225,  390),    //  1 o'clockCPoint ( 390,  225),    //  2 o'clockCPoint ( 450,    0),    //  3 o'clockCPoint ( 390, -225),    //  4 o'clockCPoint ( 225, -390),    //  5 o'clockCPoint (   0, -450),    //  6 o'clockCPoint (-225, -390),    //  7 o'clockCPoint (-390, -225),    //  8 o'clockCPoint (-450,    0),    //  9 o'clockCPoint (-390,  225),    // 10 o'clockCPoint (-225,  390),    // 11 o'clock};pDC->SelectStockObject (NULL_BRUSH);for (int i=0; i<12; i++)pDC->Rectangle (point[i].x - SQUARESIZE,point[i].y + SQUARESIZE, point[i].x + SQUARESIZE,point[i].y - SQUARESIZE);
}

三、程序窗口信息的保存及恢复

可以通过注册表把窗口的信息保存下来,程序启动时根据之前保存的信息来确定窗口的位置、大小等,从而使程序启动时窗口总能恢复到最后一次关闭时的状态。这种功能还是很有用处的。

怎样把信息写入注册表呢?又怎样从注册表中读取保存的信息呢?

1、CWinApp::SetRegistryKey

void SetRegistryKey( LPCTSTR lpszRegistryKey );

void SetRegistryKey( UINT nIDRegistryKey );

此函数导致应用程序设置存储在注册表中而不是INI文件中。

SetRegistryKey(_T("Programming Windows with MFC"));

此函数在注册表创建了一个键:HKEY\CURRENT USER\SOFTWARE\Programming Windows with MFC 。

2、CWinApp::GetProfileInt

UINT GetProfileInt( LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault );

从注册表中读取键值。

BOOL CMainWindow::RestoreWindowState ()
{//fdd edit//read profile//键值字符串对象CString version = _T("Version 1.0");//根据键值读取储存的值m_bFullWindow = myApp.GetProfileIntW(version, _T("FullWindow"), 0);//根据m_bFullWindow值更新窗口样式SetTitleBarState();//根据键值读取储存的值m_bStayOnTop = myApp.GetProfileIntW(version, _T("StayOnUp"), 0);//根据m_bFullWindow值更新窗口样式SetTopMostState();//设置窗口的其它初始状态:WINDOWPLACEMENTWINDOWPLACEMENT wp;wp.length = sizeof(WINDOWPLACEMENT);GetWindowPlacement(&wp);//根据注册表读取窗口相关信息if (((wp.flags=myApp.GetProfileIntW(version,_T("flags"),-1))!=-1)&&((wp.showCmd=myApp.GetProfileIntW(version,_T("showCmd"),-1))!=-1)&&((wp.rcNormalPosition.left=myApp.GetProfileIntW(version,_T("x1"),-1))!=-1)&&((wp.rcNormalPosition.top=myApp.GetProfileIntW(version,_T("y1"),-1))!=-1)&&((wp.rcNormalPosition.right=myApp.GetProfileIntW(version,_T("x2"),-1))!=-1)&&((wp.rcNormalPosition.bottom=myApp.GetProfileIntW(version,_T("y2"),-1))!=-1)) {//若读取成功,进行相关设置//确保窗口位置在可见范围内wp.rcNormalPosition.left = min(wp.rcNormalPosition.left,::GetSystemMetrics(SM_CXSCREEN) - ::GetSystemMetrics(SM_CXICON));wp.rcNormalPosition.top = min(wp.rcNormalPosition.top,::GetSystemMetrics(SM_CYSCREEN) - ::GetSystemMetrics(SM_CYICON));SetWindowPlacement(&wp);return TRUE;}return FALSE;}

CWinApp::GetProfileString

CString GetProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault = NULL );

CWinApp::WriteProfileInt

BOOL WriteProfileInt( LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue );

此函数把键值写入到注册表中。

void CMainWindow::SaveWindowState ()
{CString version = _T("Version 1.0");myApp.WriteProfileInt(version, _T("FullWindow"), m_bFullWindow);myApp.WriteProfileInt(version, _T("StayOnUp"), m_bStayOnTop);WINDOWPLACEMENT wp;wp.length = sizeof(WINDOWPLACEMENT);GetWindowPlacement(&wp);myApp.WriteProfileInt(version, _T("flags"), wp.flags);myApp.WriteProfileInt(version, _T("showCmd"), wp.showCmd);myApp.WriteProfileInt(version, _T("x1"), wp.rcNormalPosition.left);myApp.WriteProfileInt(version, _T("y1"), wp.rcNormalPosition.top);myApp.WriteProfileInt(version, _T("x2"), wp.rcNormalPosition.right);myApp.WriteProfileInt(version, _T("y2"), wp.rcNormalPosition.bottom);}

CWinApp::WriteProfileString

BOOL WriteProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue );

下面是在注册表中产生的结果:

四、系统菜单及系统菜单命令处理

(一)系统菜单修改:

        //// Customize the system menu.//CMenu* pMenu = GetSystemMenu (FALSE);pMenu->AppendMenu (MF_SEPARATOR);pMenu->AppendMenu (MF_STRING, IDM_SYSMENU_FULL_WINDOW,_T ("Remove &Title"));pMenu->AppendMenu (MF_STRING, IDM_SYSMENU_STAY_ON_TOP,_T ("Stay on To&p"));

(二) 系统菜单命令的处理:

void CMainWindow::OnSysCommand (UINT nID, LPARAM lParam)
{UINT nMaskedID = nID & 0xFFF0;if (nMaskedID == IDM_SYSMENU_FULL_WINDOW) {m_bFullWindow = m_bFullWindow ? 0 : 1;SetTitleBarState ();return;}else if (nMaskedID == IDM_SYSMENU_STAY_ON_TOP) {m_bStayOnTop = m_bStayOnTop ? 0 : 1;SetTopMostState ();return;}CFrameWnd::OnSysCommand (nID, lParam);
}

(三)上下文菜单的处理:

void CMainWindow::OnContextMenu (CWnd* pWnd, CPoint point)
{CRect rect;GetClientRect (&rect);ClientToScreen (&rect);if (rect.PtInRect (point)) {CMenu* pMenu = GetSystemMenu (FALSE);UpdateSystemMenu (pMenu);int nID = (int) pMenu->TrackPopupMenu (TPM_LEFTALIGN |TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x,point.y, this);if (nID > 0)SendMessage (WM_SYSCOMMAND, nID, 0);return;}CFrameWnd::OnContextMenu (pWnd, point);
}void CMainWindow::UpdateSystemMenu (CMenu* pMenu)
{static UINT nState[2][5] = {{ MFS_GRAYED,  MFS_ENABLED, MFS_ENABLED,MFS_ENABLED, MFS_DEFAULT },{ MFS_DEFAULT, MFS_GRAYED,  MFS_GRAYED,MFS_ENABLED, MFS_GRAYED  }};if (IsIconic ()) // Shouldn't happen, but let's be safereturn;int i = 0;if (IsZoomed ())i = 1;CString strMenuText;pMenu->GetMenuString (SC_RESTORE, strMenuText, MF_BYCOMMAND);pMenu->ModifyMenu (SC_RESTORE, MF_STRING | nState[i][0], SC_RESTORE,strMenuText);pMenu->GetMenuString (SC_MOVE, strMenuText, MF_BYCOMMAND);pMenu->ModifyMenu (SC_MOVE, MF_STRING | nState[i][1], SC_MOVE,strMenuText);pMenu->GetMenuString (SC_SIZE, strMenuText, MF_BYCOMMAND);pMenu->ModifyMenu (SC_SIZE, MF_STRING | nState[i][2], SC_SIZE,strMenuText);pMenu->GetMenuString (SC_MINIMIZE, strMenuText, MF_BYCOMMAND);pMenu->ModifyMenu (SC_MINIMIZE, MF_STRING | nState[i][3], SC_MINIMIZE,strMenuText);pMenu->GetMenuString (SC_MAXIMIZE, strMenuText, MF_BYCOMMAND);pMenu->ModifyMenu (SC_MAXIMIZE, MF_STRING | nState[i][4], SC_MAXIMIZE,strMenuText);SetMenuDefaultItem (pMenu->m_hMenu, i ? SC_RESTORE :SC_MAXIMIZE, FALSE);
}

(四)窗口去标题栏、窗口置于最顶层:

void CMainWindow::SetTitleBarState ()
{CMenu* pMenu = GetSystemMenu (FALSE);if (m_bFullWindow ) {ModifyStyle (WS_CAPTION, 0);pMenu->ModifyMenu (IDM_SYSMENU_FULL_WINDOW, MF_STRING,IDM_SYSMENU_FULL_WINDOW, _T ("Restore &Title"));}else {ModifyStyle (0, WS_CAPTION);pMenu->ModifyMenu (IDM_SYSMENU_FULL_WINDOW, MF_STRING,IDM_SYSMENU_FULL_WINDOW, _T ("Remove &Title"));}SetWindowPos (NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |SWP_NOZORDER | SWP_DRAWFRAME);
}void CMainWindow::SetTopMostState ()
{CMenu* pMenu = GetSystemMenu (FALSE);if (m_bStayOnTop) {SetWindowPos (&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);pMenu->CheckMenuItem (IDM_SYSMENU_STAY_ON_TOP, MF_CHECKED);}       else {SetWindowPos (&wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);pMenu->CheckMenuItem (IDM_SYSMENU_STAY_ON_TOP, MF_UNCHECKED);}
}

五、窗口通过鼠标在客户区也能实现拖动

LRESULT CMainWindow::OnNcHitTest(CPoint point)
{// TODO: 在此添加消息处理程序代码和/或调用默认值LRESULT nHitTest = CFrameWnd::OnNcHitTest(point);if ((nHitTest == HTCLIENT) && (::GetAsyncKeyState(MK_LBUTTON) < 0))nHitTest = HTCAPTION;return nHitTest;return CFrameWnd::OnNcHitTest(point);
}

有关vc++ 时钟程序的学习与体会相关推荐

  1. 大学四年嵌入式学习心得体会

    我所在学校是普通的本科院校,从大一开始加入嵌入式实验室,一直在实验室呆了三年半,从大一的懵懂无知,天天看着 C 语言书自己敲代码,到后来学习51单片机,STM32,做过3-4个项目,参加各种比赛,轻轻 ...

  2. c语言实验报告绘制钟表,单片机时钟程序实验报告

    单片机原理与应用 课程名称:    单片机原理与应用 设计题目:    LCD电子钟 院    系:    电子信息工程学院 班    级:    自动化0706 设 计 者:    全宏宇 指导教师 ...

  3. 计算机基础与应用(上)笔记总结,计算机基础学习心得体会范文(通用3篇)

    计算机基础学习心得体会范文(通用3篇) 当我们对人生或者事物有了新的思考时,好好地写一份心得体会,这样可以记录我们的思想活动.那么要如何写呢?以下是小编精心整理的计算机基础学习心得体会范文(通用3篇) ...

  4. c语言程序设计课程设计心得体会,C语言程序课程设计心得体会

    在科技高度发展的今天,计算机在人们之中的作用越来越突出,学习它,有助于我们更好的了解计算机,与计算机进行交流,因此,c语言的学习对我们尤其重要. 在这个星期里,我们专业的学生在专业老师的带领下进行了c ...

  5. java容器doc_关于Java容器类学习心得体会.doc

    关于Java容器类学习心得体会 由于小编对C++比较熟悉所以学习Java应该重点体会Java带来的新概念本文基本上是Java标准库中集合框架的基本概念没有例子写本文的目的在于方便小编很长时间后若是忘了 ...

  6. 计算机网络讨论课感悟,计算机网络课程学习心得体会

    计算机网络课程学习心得体会 当我们积累了新的体会时,可以将其记录在心得体会中,这样能够给人努力向前的动力.那么好的心得体会是什么样的呢?下面是小编为大家收集的计算机网络课程学习心得体会,供大家参考借鉴 ...

  7. 推荐几个程序员学习网站

    推荐几个程序员学习网站   推荐编程学习网站  VB GOOD http://www.vbgood.com/  VB爱好者乐园,国内最好的VB编程交流网站  太平洋电脑网 www.pconline.c ...

  8. GTK+图形化应用程序开发学习笔记(五)—组装盒、组合表、固定容器构件

    GTK+图形化应用程序开发学习笔记(五)-组装盒.组合表.固定容器构件 一.组装盒 组装盒(GtkBox)也称为组合构件.使用组装盒可以将多个构件放在一个容器中.容器可以把组装盒看作是一个构件.不像按 ...

  9. html表单的课后心得体会,web前端学习心得体会范文

    <web前端学习心得体会范文>由会员分享,可在线阅读,更多相关<web前端学习心得体会范文(2页珍藏版)>请在装配图网上搜索. 1.web前端学习心得体会范文web前端学习心得 ...

  10. 电脑硬件知识学习_关于网络学习心得体会集锦七篇

    关于网络学习心得体会集锦七篇 当在某些事情上我们有很深的体会时,好好地写一份心得体会,通过写心得体会,可使我们今后少走弯路.那么心得体会怎么写才能感染读者呢?以下是小编为大家收集的网络学习心得体会7篇 ...

最新文章

  1. 实现if_如何解决开发中 if...esle 代码过多的问题,强烈推荐!
  2. 自学python需要多长时间-自学Python要学多久可以学会?
  3. xdm,把我大学四年能用到的软件都分享给你。
  4. 页面定时跳转(读秒)
  5. 使用简单工厂模式demo
  6. 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)
  7. java被放弃了_为什么学Java那么容易放弃?
  8. MySQL日期类型的处理总结
  9. Fortan写出数据到CSV文件中
  10. 单循环赛 贝格尔编排法实现
  11. RobotFramework教程使用笔记——Selenium2Library库
  12. 计算机一级pdf百度云,计算机一级(实操).pdf
  13. vertica数据库监控
  14. Unity3D学习日记6
  15. Android7 WIFI系统 PNO机制流程详解和隐藏BUG修改
  16. 【好书推荐】第一本无人驾驶技术书
  17. 秘技·真·一键卸载JDK,刷新你的的世界观!
  18. 移动端web开发---Touch事件详解
  19. obs nginx-rtmp-module搭建流媒体服务器实现直播 ding
  20. 如何平衡机器学习中偏差与方差

热门文章

  1. Python——单因素方差分析表
  2. Vue 记录一次安装插件引起的项目崩溃(This is probably not a problem with npm,there is likely additional logging outp)
  3. 安卓原生页面与react-native页面相互跳转实现
  4. 刘德华--2初恋时节
  5. jersey 过滤_Jersey 开发RESTful(十五) Jersey的拦截器
  6. vc如何引入lib库
  7. 10个python办公黑科技,助你办公效率提高100倍
  8. mysql身份证号的类型_MySQL--隐藏手机号、身份证号三种方式
  9. K近邻法(KNN)与k-Means的区别
  10. 《2020年国际会计事务所排名》