支持毫秒的时间控件类, 帮我写个demo

网上下载了这个支持毫秒的时间控件类,不知道怎么使用? 请帮我用VS2008 Unicode+mfc写个demo,谢谢!

#pragma once
#include "afxwin.h"

class CTimeWnd :
    public CWnd
{
public:
    enum Value
    {
        valHours = 0,
        valMinutes,
        valSeconds,
        valMilliseconds,
        valCount
    };

    DECLARE_MESSAGE_MAP()

    int m_nValue[valCount];
    int m_nValueMax[valCount];
    double m_dPower[valCount];
private:
    CRect m_Rect[valCount];
    int m_nCurSel;
    int m_nOldSel;
    CFont *m_pFont;
    bool m_bFocus;
    CSpinButtonCtrl m_Spin;

public:
    CTimeWnd(void);
    virtual ~CTimeWnd(void);
    CString GetString(int nType);
    void SetFont(CFont *pFont, BOOL bRedraw =false);
    CFont *GetFont();    
    double GetTime();
    int GetValue(int nType);
    void SetValue(int nType, int nVal);
    void SetTime(double dTime);
    virtual BOOL PreTranslateMessage(MSG *pMsg);
    virtual void PreSubclassWindow();
    afx_msg void OnPaint();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnKillFocus(CWnd *pNewWnd);
    afx_msg void OnDeltaposSpin1(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnCaptureChanged(CWnd *pWnd);
    afx_msg void OnEnable(BOOL bEnable);
private:
    bool IsCountValid(int nCount);
    void ChangeChar(UINT nChar, int refer);
    void ChangeSpin(int nDelta);
    void DrawSingleString(CDC *pDC, CString &str, CRect &rc, int *pOffset = NULL, bool bSelect = false);
    int GetNumberCount(int num);
    bool IsFocus();
    void ReDraw(bool bNeedBk = true);
};


#include "StdAfx.h"
#include "TimeWnd.h"

CTimeWnd::CTimeWnd(void)
{
    for (int i=0; i0;
        m_Rect[i].SetRectEmpty();
    }
    m_nValueMax[valHours] = 24;
    m_nValueMax[valMinutes] = 60;
    m_nValueMax[valSeconds] = 60;
    m_nValueMax[valMilliseconds] = 1000;

    m_dPower[valHours] = 3600;
    m_dPower[valMinutes] = 60;
    m_dPower[valSeconds] = 1;
    m_dPower[valMilliseconds] = 0.001;

    m_nCurSel = -1;
    m_nOldSel = 0;
    m_pFont = NULL;
    m_bFocus = false;
}

CTimeWnd::~CTimeWnd(void)
{
}

BEGIN_MESSAGE_MAP(CTimeWnd, CWnd)

ON_WM_PAINT()
    ON_WM_CREATE()
    ON_WM_LBUTTONDOWN()
    ON_WM_KEYDOWN()
    ON_NOTIFY(UDN_DELTAPOS, 1051, &CTimeWnd::OnDeltaposSpin1)
    ON_WM_KILLFOCUS()
    ON_WM_SIZE()
    ON_WM_CAPTURECHANGED()
    ON_WM_ENABLE()
END_MESSAGE_MAP()

void CTimeWnd::OnDeltaposSpin1(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMUPDOWN pNMUpDown = reinterpret_cast(pNMHDR);
    *pResult = 0;
    SetFocus();
    ChangeSpin(pNMUpDown->iDelta*(-1));
}

void CTimeWnd::ChangeSpin(int nDelta)
{
    if(m_nCurSel == -1)
    {
        m_nCurSel = m_nOldSel;
    }
    if (nDelta > 0)
    {
        m_nValue[m_nCurSel] = (m_nValue[m_nCurSel]+nDelta)%m_nValueMax[m_nCurSel];
    }
    else
    {
        m_nValue[m_nCurSel] = (m_nValue[m_nCurSel]+nDelta+m_nValueMax[m_nCurSel])%m_nValueMax[m_nCurSel];
    }
    ReDraw(true);
}

void CTimeWnd::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    CRect rcBounds;   
    GetClientRect(&rcBounds);   
    CPen penWhite;   
    penWhite.CreatePen(PS_SOLID, 1, RGB(127,157,185));   
    CPen *pOldPen = dc.SelectObject(&penWhite); 
    dc.FillSolidRect(rcBounds, RGB(255,255,255));
    dc.MoveTo(rcBounds.left, rcBounds.top);   
    dc.LineTo(rcBounds.right-1, rcBounds.top);   
    dc.LineTo(rcBounds.right-1, rcBounds.bottom-1);   
    dc.LineTo(rcBounds.left, rcBounds.bottom-1);   
    dc.LineTo(rcBounds.left, rcBounds.top);  
    CString    str = NULL;
    int xoffset = 5;
    CRect rc;
    rc.SetRectEmpty();
    for(int i=0; iif (i != valCount-1)
        {
            rc = rcBounds;
            str = _T(":");
            DrawSingleString(&dc, str, rc, &xoffset);
        }
    }
    dc.SelectObject(pOldPen); 
}

void CTimeWnd::PreSubclassWindow()
{
    CWnd::PreSubclassWindow();
}

int CTimeWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    m_Spin.Create(UDS_ALIGNRIGHT|UDS_AUTOBUDDY|WS_VISIBLE, CRect(0,0,20,19), this, 1051);
    m_Spin.SetBuddy(this);

    return 0;
}

void CTimeWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
    for (int i=0; iif (m_Rect[i].PtInRect(point))
        {
            if (m_nCurSel == i)break;
            ReDraw(false);
            m_nCurSel = i;
            ReDraw(true);
            break;
        }
    }
    SetFocus();
    m_bFocus = true;
    CWnd::OnLButtonDown(nFlags, point);
}

void CTimeWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
     if (m_nCurSel == -1)
    {
        m_nCurSel = m_nOldSel;
    }
    if ((nChar>='0') && (nChar<='9'))
    {
        ChangeChar(nChar, '0');
    }
    else if ((nChar>=VK_NUMPAD0) && (nChar<=VK_NUMPAD9))
    {
        ChangeChar(nChar, VK_NUMPAD0);
    }
    ReDraw(true);
    CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

CString CTimeWnd::GetString(int nType)
{
    CString str = NULL;
    int nCount = 0;
    int nZero = 0;
    nCount = GetNumberCount(m_nValueMax[nType]-1);
    nZero = nCount - GetNumberCount(m_nValue[nType]) ;
    m_nValue[nType] %= m_nValueMax[nType];
    str.Format(_T("%d"), m_nValue[nType]);
    while (nZero--)
    {
        str = _T("0") + str;
    }
    return str;
}

void CTimeWnd::DrawSingleString(CDC *pDC, CString &str, CRect &rc, int *pOffset/*= -1*/, bool bSelect/* = false*/)
{
    int nHeight = rc.Height();
    int offset = 0;
    if (pOffset == NULL)
    {
        offset = rc.left;
    }
    else
    {
        offset = *pOffset;
    }
    CFont *pOldFont = NULL;
    if (m_pFont)
    {
        pOldFont = pDC->SelectObject(m_pFont);
    }
    pDC->DrawText(str, rc, DT_CALCRECT);
    rc.MoveToXY(offset, (nHeight - rc.Height())/2);
    COLORREF clr;
    int nMode = 0;
    BOOL bEnable = IsWindowEnabled();
    if (bSelect && bEnable)
    {
        pDC->FillSolidRect(rc, RGB(49,106,197));
        clr = pDC->SetTextColor(RGB(255,255,255));
        nMode = pDC->SetBkMode(TRANSPARENT);
    }
    else
    {
        pDC->FillSolidRect(rc, RGB(255,255,255));
    }
    if (bEnable)
         pDC->DrawState(CPoint(rc.left, rc.top), CSize(rc.Width(), rc.Height()), str, DSS_NORMAL, TRUE, 0, (HBRUSH)NULL);
    else
        pDC->DrawState(CPoint(rc.left, rc.top), CSize(rc.Width(), rc.Height()), str, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
    offset += rc.Width();
    if (bSelect)
    {
        pDC->SetTextColor(clr);
        pDC->SetBkMode(nMode);
    }
    if (pOffset) *pOffset = offset;
    if (pOldFont) pDC->SelectObject(pOldFont);
}

void CTimeWnd::OnKillFocus(CWnd *pNewWnd)
{
    CWnd::OnKillFocus(pNewWnd);
    ReDraw(false);
    m_nOldSel = m_nCurSel;
    m_nCurSel = -1;
    m_bFocus = false; 
}

void CTimeWnd::ReDraw(bool bNeedBk/*= true*/)
{
    if (m_nCurSel == -1)
    {
        return;
    }
    CDC *pDC = GetDC();
    CString str = GetString(m_nCurSel);
    CRect   rcBounds;   
    GetClientRect(&rcBounds);   
    rcBounds.left = m_Rect[m_nCurSel].left;
    rcBounds.right = m_Rect[m_nCurSel].right;
    DrawSingleString(pDC, str, rcBounds, NULL, bNeedBk);
    ReleaseDC(pDC);
}

void CTimeWnd::SetFont(CFont *pFont, BOOL bRedraw/*=false*/)
{
    m_pFont = pFont;
    if (bRedraw)
    {
        Invalidate();
    }
}

CFont *CTimeWnd::GetFont()
{
    return m_pFont;
}

void CTimeWnd::ChangeChar(UINT nChar, int refer)
{
    if (!IsCountValid(m_nCurSel)) return;
    int iCharValue = nChar - refer;
    int iTemVal = m_nValue[m_nCurSel] * 10 + iCharValue;
    m_nValue[m_nCurSel] = (iTemVal >= m_nValueMax[m_nCurSel]) ? iCharValue : iTemVal;
}


BOOL CTimeWnd::PreTranslateMessage(MSG *pMsg)
{
    if (pMsg->message == WM_KEYDOWN)
    {
        if (pMsg->wParam == VK_UP)
        {
            ChangeSpin(1);
            return true;
        }
        if (pMsg->wParam == VK_DOWN)
        {
            ChangeSpin(-1);
            return true;
        }
        if (pMsg->wParam == VK_LEFT)
        {
            ReDraw(false);
            m_nCurSel = (m_nCurSel + valCount - 1) % valCount;
            ReDraw(true);
            return true;
        }
        if (pMsg->wParam == VK_RIGHT)
        {
            ReDraw(false);
            m_nCurSel = (m_nCurSel + 1) % valCount;
            ReDraw(true);
            return true;
        }
        if (pMsg->wParam == VK_END)
        {        
            m_nValue[m_nCurSel] = m_nValueMax[m_nCurSel];
        }
        if (pMsg->wParam == VK_HOME)
        {
            m_nValue[m_nCurSel] = 0;
        }
    }
    return CWnd::PreTranslateMessage(pMsg);
}

double CTimeWnd::GetTime()
{
    double dTime = 0;
    for (int i=0; ireturn dTime;
}

int CTimeWnd::GetValue(int nType)
{
    if (!IsCountValid(nType)) 
        return 0;
    else 
        return m_nValue[nType];
}

void CTimeWnd::SetValue(int nType, int nVal)
{
    if ((!IsCountValid(nType)) || nVal<0) return;
    else m_nValue[nType] = nVal % m_nValueMax[nType];
}

void CTimeWnd::SetTime(double dTime)
{
    int nTemVal = 0;
    for (int i=0; iint)((dTime - nTemVal) / m_dPower[i]);
        nTemVal += m_nValue[i];
        m_nValue[i] %= m_nValueMax[i]; 
    }
}

bool CTimeWnd::IsFocus()
{
    return m_bFocus;
}

void CTimeWnd::OnSize(UINT nType, int cx, int cy)
{
    CWnd::OnSize(nType, cx, cy);
    m_Spin.MoveWindow(cx-19, 1, 18, cy-2);
}

void CTimeWnd::OnCaptureChanged(CWnd *pWnd)
{
    CWnd::OnCaptureChanged(pWnd);
}

void CTimeWnd::OnEnable(BOOL bEnable)
{
    CWnd::OnEnable(bEnable);
    Invalidate();
    m_Spin.EnableWindow(bEnable);
}

int CTimeWnd::GetNumberCount(int num)
{
    int i = 0;
    if (num == 0)
    {
        return 1;
    }
    while (num)
    {
        num /= 10;    
        i++;
    };
    return i;
}

bool CTimeWnd::IsCountValid(int nCount)
{
    if ((nCount>=0) && (nCountreturn true;
    }
    return false;
}

demo上传到csdn了https://download.csdn.net/download/b2b160/87537455

img

//CTimeWndDemoDlg.h定义
#include "TimeWnd.h"

CTimeWnd m_wndTime;

//CTimeWndDemoDlg.cpp
//创建
if( !m_wndTime.Create( _T("Static"),_T(""),WS_CHILD|WS_VISIBLE|SS_NOTIFY,rt,this,1001) )
        MessageBox(_T("Error"));

//获取时间
double dTime = m_wndTime.GetTime();
    CString str;
    str.Format( _T("Time:%f, %d:%d:%d:%d"), dTime,m_wndTime.GetValue(0),m_wndTime.GetValue(1),m_wndTime.GetValue(2),m_wndTime.GetValue(3) );
    MessageBox(str);

“Devil组”引证GPT后的撰写:

  • 为了使用这个支持毫秒的时间控件类,要创建一个新的 MFC 应用程序并将 TimeWnd.h 和 TimeWnd.cpp 文件添加到项目中。然后,可以在代码中创建 CTimeWnd 对象并使用它的成员函数来操作时间。

下面是一个示例程序,它创建一个 CTimeWnd 对象并将其添加到主窗口中。在程序中,用户可以使用箭头键或鼠标来更改时间,然后单击“显示时间”按钮以将当前时间显示在控制台窗口中。

// MainFrm.h

#pragma once

#include "TimeWnd.h"

class CMainFrame : public CFrameWnd
{
public:
    CMainFrame();
    virtual ~CMainFrame();
protected:
    DECLARE_MESSAGE_MAP()
private:
    CTimeWnd m_TimeWnd;
    CButton m_ShowTimeButton;
public:
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnShowTime();
};

// MainFrm.cpp

#include "stdafx.h"
#include "MainFrm.h"

IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ON_WM_CREATE()
    ON_COMMAND(ID_SHOW_TIME, &CMainFrame::OnShowTime)
END_MESSAGE_MAP()

CMainFrame::CMainFrame()
{
}

CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    // create time window
    if (!m_TimeWnd.Create(NULL, L"Time Window", WS_CHILD | WS_VISIBLE, CRect(10, 10, 200, 100), this, 0))
        return -1;

    // create show time button
    if (!m_ShowTimeButton.Create(L"Show Time", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(10, 120, 100, 140), this, ID_SHOW_TIME))
        return -1;

    return 0;
}

void CMainFrame::OnShowTime()
{
    CString str;
    double dTime = m_TimeWnd.GetTime();
    str.Format(L"The current time is %.3f seconds.", dTime);
    AfxMessageBox(str);
}


创建了一个名为“Time Window”的 CTimeWnd 对象,并将其添加到主窗口中。该窗口将显示一个带有四个可调节数字的矩形,分别表示小时、分钟、秒和毫秒。用户可以使用键盘或鼠标来更改这些数字,然后单击“显示时间”按钮以将当前时间显示在控制台窗口中。

这是一个控件,在MFC窗口上放个标签控件,绑定这个控件的实例就行了

参考GPT的内容,这是一个自定义的 MFC 控件类 CTimeWnd,提供了一个支持毫秒的时间控制,可以选择和设置小时、分钟、秒和毫秒。

这个类可以作为单独的控件使用,或者作为对话框、视图或窗体的一部分。

下面是对一些关键函数的解释:

GetString(int nType):返回选定类型(小时、分钟、秒或毫秒)的字符串,例如,如果当前选择小时,则返回值为“小时”,如果选择分钟,则返回值为“分钟”等。
GetTime():返回以秒为单位的时间。即所有时间(小时、分钟、秒和毫秒)的总秒数。
GetValue(int nType):返回指定类型的时间值。
SetValue(int nType, int nVal):将指定类型的时间值设置为指定的值。
SetTime(double dTime):将时间设置为指定的秒数。
PreTranslateMessage(MSG *pMsg):用于处理并将消息传递给父类窗口。
PreSubclassWindow():在控件子类化之前调用的函数。
OnPaint():用于重绘控件。
这里提供一个使用这个类的简单的示例,包括创建一个对话框、添加 CTimeWnd 控件并设置其属性。

打开 Visual Studio 2008,创建一个 MFC 对话框应用程序,勾选“空白项目”,将字符集设置为 Unicode。

1.添加一个按钮,命名为 IDC_TIME_BUTTON,将 ID 设置为 IDC_TIME_BUTTON。

2.添加一个包含控件代码的新源文件,命名为 TimeWnd.cpp,将以下代码复制到该文件中:

#include "stdafx.h"
#include "TimeWnd.h"

#define IDC_TIME_WND 1001

class CTimeDlg : public CDialogEx
{
public:
    CTimeDlg(CWnd* pParent = NULL)
        : CDialogEx(IDD_TIME_DIALOG, pParent)
    {
    }

    enum { IDD = IDD_TIME_DIALOG };

protected:
    virtual void DoDataExchange(CDataExchange* pDX)
    {
        CDialogEx::DoDataExchange(pDX);
    }

    virtual BOOL OnInitDialog()
    {
        CDialogEx::OnInitDialog();

        // 创建时间控件
        CRect rcTime(10, 10, 250, 200);
        m_wndTime.Create(NULL, _T("时间控件"), WS_CHILD | WS_VISIBLE, rcTime, this, IDC_TIME_WND);

        // 设置字体
        CFont font;
        font.CreatePointFont(100, _T("宋体"));
        m_wndTime.SetFont(&font);

        return TRUE;
    }

    afx_msg void OnBnClickedTimeButton()
    {
        // 显示选定的时间
        CString strTime;
        double dTime = m_wndTime.GetTime();
        strTime.Format(_T("%.2f 秒"), dTime);
        MessageBox(strTime, _T("选定时间"));
    }

    DECLARE_MESSAGE_MAP()

private:
    CTimeWnd m_wndTime;
};

BEGIN_MESSAGE_MAP(CTimeDlg, CDialogEx)
    ON_BN_CLICKED(IDC_TIME_BUTTON, &CTimeDlg::OnBnClickedTimeButton)
END_MESSAGE_MAP()

建议您查看该时间控件的文档或寻求相关社区的帮助。一般来说,使用这种控件需要先将其添加到项目中并进行必要的初始化,然后在代码中调用相应的函数来实现所需的功能。您可以参考该控件的示例代码或其他类似控件的代码来编写您自己的 Demo

下面是一个简单的使用示例,展示如何在MFC应用程序中使用该控件类。假设你已经将该控件类的头文件和实现文件添加到你的MFC项目中。

首先,打开你的 MFC 应用程序的主窗口类头文件(通常是 YourAppName.h)并添加以下代码:

#include "TimeWnd.h"
// ...
class CYourAppNameDlg : public CDialogEx
{
// ...
private:
CTimeWnd m_TimeCtrl;
}

在 CYourAppNameDlg 类的 OnInitDialog() 函数中创建控件并设置初始值:

BOOL CYourAppNameDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 创建控件
m_TimeCtrl.Create(NULL, NULL, WS_CHILD | WS_VISIBLE, CRect(10, 10, 210, 60), this, 1001);

// 设置初始值
m_TimeCtrl.SetValue(CTimeWnd::valHours, 1);
m_TimeCtrl.SetValue(CTimeWnd::valMinutes, 23);
m_TimeCtrl.SetValue(CTimeWnd::valSeconds, 45);
m_TimeCtrl.SetValue(CTimeWnd::valMilliseconds, 678);

// ...

return TRUE;
}

在 CYourAppNameDlg 的 DoDataExchange() 函数中添加以下代码:

void CYourAppNameDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, 1001, m_TimeCtrl);
}

现在你已经在你的 MFC 应用程序中创建了一个支持毫秒的时间控件,并设置了初始值。你可以使用 SetValue() 和 GetValue() 函数来读写控件中的值,例如:

下面是一个简单的使用示例,展示如何在MFC应用程序中使用该控件类。假设你已经将该控件类的头文件和实现文件添加到你的MFC项目中。

首先,打开你的 MFC 应用程序的主窗口类头文件(通常是 YourAppName.h)并添加以下代码:

#include "TimeWnd.h"
// ...
class CYourAppNameDlg : public CDialogEx
{
// ...
private:
CTimeWnd m_TimeCtrl;
}

在 CYourAppNameDlg 类的 OnInitDialog() 函数中创建控件并设置初始值:

BOOL CYourAppNameDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();

objectivec
Copy code
// ...

// 创建控件
m_TimeCtrl.Create(NULL, NULL, WS_CHILD | WS_VISIBLE, CRect(10, 10, 210, 60), this, 1001);

// 设置初始值
m_TimeCtrl.SetValue(CTimeWnd::valHours, 1);
m_TimeCtrl.SetValue(CTimeWnd::valMinutes, 23);
m_TimeCtrl.SetValue(CTimeWnd::valSeconds, 45);
m_TimeCtrl.SetValue(CTimeWnd::valMilliseconds, 678);

// ...

return TRUE;
}

在 CYourAppNameDlg 的 DoDataExchange() 函数中添加以下代码:

void CYourAppNameDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, 1001, m_TimeCtrl);
}

现在你已经在你的 MFC 应用程序中创建了一个支持毫秒的时间控件,并设置了初始值。你可以使用 SetValue()GetValue() 函数来读写控件中的值,例如:

// 获取当前时间
double dTime = m_TimeCtrl.GetTime();

// 获取小时值
int nHours = m_TimeCtrl.GetValue(CTimeWnd::valHours);

// 设置分钟值
m_TimeCtrl.SetValue(CTimeWnd::valMinutes, 59);

你还可以在你的代码中添加消息处理函数来响应控件的各种事件,例如:

// 用户在控件上按下鼠标左键
void CYourAppNameDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
CDialogEx::OnLButtonDown(nFlags, point);
// 获取用户选择的部分(小时、分钟、秒、毫秒)
int nSelected = m_TimeCtrl.m_nCurSel;

// ...
}

注意:该控件类仅提供时间选择功能,如果你需要显示日期,请使用 CDateTimeCtrl 类。