PoEdu培训 Windows班 第一课 MFC控件的使用
文章类别: 培训笔记 0 评论

PoEdu培训 Windows班 第一课 MFC控件的使用

文章类别: 培训笔记 0 评论

MFC控件的使用

MFC是什么

Windows 下的应用程序开发框架.
MFC现在无法提供一个完善的界面, 但是可以提供一个可用的界面.
MFC足够简单.
MFC是一种经典.

MFC编程注意事项

在MFC编程中, 控件的ID属性是十分重要的.
一定要起一个规范的, 简单易懂的 ID.
无论是Win32编程还是MFC编程, 在Windows下, 核心的机制就是消息机制
在使用的控件比较频繁的时候, 建议以添加变量的方式来进行控件的操作
当对控件的使用不频繁的时候, 可以直接用 GetDlgItem 方法

Edit Control

编辑框控件

有几个需要注意的属性:

Button Control

按钮控件

Static Control

静态文本控件

// Edit, Button, Static综合示例

// 双击按钮, 添加的事件
void CEditDemoDlg::OnBnClickedBtnCount()
{
    // TODO: 在此添加控件通知处理程序代码
    CString szInput;
    // 获得 Edit 中的内容, 并判断字数
    if (0 == GetDlgItemTextW(IDC_EDT_INPUT, szInput))
    {
        // 将文本设置到 ID为 IDC_STATIC_OUTPUT 的控件上, 在这里就是 Static
        SetDlgItemTextW(IDC_STATIC_OUTPUT, L"获取统计资料失败!");
        return;
    }
    CString szOutput;
    szOutput.Format(L"%d", szInput.GetLength());
    SetDlgItemTextW(IDC_STATIC_OUTPUT, szOutput);
}

Check Box Control

多选框控件

Radio Button Control

单选按钮控件

Combo Box Control

组合框控件

List Box Control

列表框控件

// ListBox和ComboBox的添加和删除数据

// 添加数据
void CComboBoxDemoDlg::OnBnClickedBtnAdd()
{
    // TODO: 在此添加控件通知处理程序代码
    CString szInput;
    // 获取文本框里的值 当做数据添加
    if (0 != GetDlgItemTextW(IDC_EDT_INPUT, szInput))
    {
        int nIndex = m_cbDemo.AddString(szInput);
        m_cbDemo.SetCurSel(nIndex);
        nIndex = m_lstDemo.AddString(szInput);
        m_lstDemo.SetCurSel(nIndex);
        SetDlgItemTextW(IDC_EDT_INPUT, L"");
        GetDlgItem(IDC_EDT_INPUT)->SetFocus();
    }
}

// 删除数据
void CComboBoxDemoDlg::OnBnClickedBtnDel()
{
    // TODO: 在此添加控件通知处理程序代码
    int nIndex = m_cbDemo.GetCurSel();
    
    if (nIndex > -1)
    {
        m_cbDemo.DeleteString(nIndex);
        if (nIndex < m_cbDemo.GetCount())
            m_cbDemo.SetCurSel(nIndex);
        else
            m_cbDemo.SetCurSel(0);
    }
    else
    {
        MessageBoxW(L"下拉框未选中待删除的项!", L"花心胡萝卜工作室提示", MB_OK | MB_ICONINFORMATION);
    }
    nIndex = m_lstDemo.GetCurSel();
    if (nIndex > -1)
    {
        m_lstDemo.DeleteString(nIndex);
        if (nIndex < m_lstDemo.GetCount())
            m_lstDemo.SetCurSel(nIndex);
        else
            m_lstDemo.SetCurSel(0);
    }
    else
    {
        MessageBoxW(L"列表未选中待删除的项!", L"花心胡萝卜工作室提示", MB_OK | MB_ICONINFORMATION);
    }
}

ScrollBar Control

滚动条控件

默认添加的滚动条控件, 不写任何代码, 是不能使用的.
要使用滚动条, 必须进行代码编写实现.
必须响应 WM_HSCROLL 或者 WM_VSCROLL 消息

滚动条有一系列内部的行为的命令定义代码, 比如:

// 水平滚动条使用的例子
BOOL CScrollBarDemoDlg::OnInitDialog()
{
    // .....省略无关代码

    // TODO: 在此添加额外的初始化代码
    SCROLLINFO scrollInfo = { 0 };
    scrollInfo.cbSize = sizeof(SCROLLINFO);
    // 表示滚动条需要有 滚动范围, 可以按页滚动
    scrollInfo.fMask = SIF_RANGE | SIF_PAGE;
    // 设置范围
    scrollInfo.nMax = 100;
    scrollInfo.nMin = 0;
    // 按页滚动的大小
    scrollInfo.nPage = 10;
    // m_hScrollBar是一个SCROLLBAR控件的变量
    m_hScrollBar.SetScrollInfo(&scrollInfo);

    // .....省略无关代码
}


void CScrollBarDemoDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    SCROLLINFO scrollInfo = { 0 };
    scrollInfo.cbSize = sizeof(SCROLLINFO);
    scrollInfo.fMask = SIF_ALL;
    pScrollBar->GetScrollInfo(&scrollInfo);

    int nNewPos = scrollInfo.nPos;

    switch (nSBCode)
    {
    case SB_THUMBTRACK:        // 用户拖动滚动消息
        nNewPos = nPos;
        break;
    case SB_LINELEFT:        // 左边的按钮被按下
        nNewPos -= 1;
        break;
    case SB_LINERIGHT:        // 右边的按钮被按下
        nNewPos += 1;
        break;
    case SB_PAGELEFT:        // 左翻页
        nNewPos -= scrollInfo.nPage;
        break;
    case SB_PAGERIGHT:        // 右翻页
        nNewPos += scrollInfo.nPage;
        break;
    default:
        break;
    }

    if (nNewPos > scrollInfo.nMax)
        nNewPos = scrollInfo.nMax;
    if (nNewPos < scrollInfo.nMin)
        nNewPos = scrollInfo.nMin;

    scrollInfo.nPos = nNewPos;
    pScrollBar->SetScrollInfo(&scrollInfo);

    CString szPos;
    szPos.Format(L"滚动条当前位置:%d", nNewPos);
    SetDlgItemTextW(IDC_STATIC_POS, szPos);

    CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}

Spin Control

数值控件, 必须与其他控件组合使用, 一般都与Edit控件一起使用

使用步骤

代码调整


BOOL CSpinDemoDlg::OnInitDialog()
{
    // ... 省略无关代码

    // TODO: 在此添加额外的初始化代码
    // 获取Spin的一个控件
    CSpinButtonCtrl* pSpinDec = (CSpinButtonCtrl*)GetDlgItem(IDC_SPIN_DEC);
    // 设置范围
    pSpinDec->SetRange32(0, 100);

    CSpinButtonCtrl* pSpinHex = (CSpinButtonCtrl*)GetDlgItem(IDC_SPIN_HEX);
    pSpinHex->SetRange32(0, 100);
    // 设置16进制
    pSpinHex->SetBase(16);

    // ... 省略无关代码
    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

Progress Control

进度条控件

// 进度条的应用
// 使用 Timer 进行进度条的进度走动


BOOL CProgressDemoDlg::OnInitDialog()
{
    // ... 省略无关代码

    // TODO: 在此添加额外的初始化代码
    m_progressBar.SetRange32(0, 100);
    m_progressBar.SetStep(1);

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 开始按钮 1
void CProgressDemoDlg::OnBnClickedBtnBegin()
{
    // TODO: 在此添加控件通知处理程序代码
    m_progressBar.SetPos(0);
    SetTimer(1, 100, nullptr);
    GetDlgItem(IDC_BTN_BEGIN)->EnableWindow(FALSE);
    GetDlgItem(IDC_BTN_START)->EnableWindow(FALSE);
}

// 开始按钮 2
void CProgressDemoDlg::OnBnClickedBtnStart()
{
    // TODO: 在此添加控件通知处理程序代码
    m_progressBar.SetPos(0);
    SetTimer(2, 100, nullptr);
    GetDlgItem(IDC_BTN_BEGIN)->EnableWindow(FALSE);
    GetDlgItem(IDC_BTN_START)->EnableWindow(FALSE);
}

void CProgressDemoDlg::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    switch (nIDEvent)
    {
    case 1:
    {
        //方法1
        int nMin, nMax, nPos;
        m_progressBar.GetRange(nMin, nMax);
        nPos = m_progressBar.GetPos();
        ++nPos;
        if (nPos > nMax)
        {
            KillTimer(1);
            GetDlgItem(IDC_BTN_BEGIN)->EnableWindow();
            GetDlgItem(IDC_BTN_START)->EnableWindow();
        }
        m_progressBar.SetPos(nPos);
        break;
    }
    case 2:
    {
        // 方法2
        int nMin, nMax, nPos;
        m_progressBar.GetRange(nMin, nMax);
        nPos = m_progressBar.StepIt();
        if (nPos + 1 >= nMax)
        {
            GetDlgItem(IDC_BTN_BEGIN)->EnableWindow();
            GetDlgItem(IDC_BTN_START)->EnableWindow();
            KillTimer(2);
        }
        break;
    }
    default:
        break;
    }

    CDialogEx::OnTimer(nIDEvent);
}

Slider Control

滑块控件

// 使用示例

// 横向滑块的消息响应
void CSliderDemoDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    int nNowPos = m_hSlider.GetPos();
    CString szInfo;
    szInfo.Format(L"当前水平滑块位置为:[%d]", nNowPos);
    SetDlgItemTextW(IDC_STATIC_INFO, szInfo);

    CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
}

// 纵向滑块的消息响应
void CSliderDemoDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    int nNowPos = m_vSlider.GetPos();
    CString szInfo;
    szInfo.Format(L"当前垂直滑块位置为:[%d]", nNowPos);
    SetDlgItemTextW(IDC_STATIC_INFO, szInfo);

    CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
}

HotKey Control

热键控件, 可以自动获取按下的键

// 热键控件使用示例

void CHotKeyDemoDlg::OnBnClickedBtnSetHotkey()
{
    // TODO: 将HotKey控件中按下的热键注册到系统中
    WORD wVK, wMod;
    m_hotkey.GetHotKey(wVK, wMod);
    if (RegisterHotKey(m_hWnd, 1, wMod, wVK))
    {
        ShowWindow(SW_HIDE);
    }
    else
    {
        MessageBoxW(L"热键注册失败!", L"花心胡萝卜工作室提示", MB_OK | MB_ICONINFORMATION);
    }
}

void CHotKeyDemoDlg::OnHotKey(UINT nHotKeyId, UINT nKey1, UINT nKey2)
{
    // TODO: 响应热键消息
    switch (nHotKeyId)
    {
    case 1:
        ShowWindow(SW_SHOW);
        // 不需要使用了 就反注册
        UnregisterHotKey(m_hWnd, 1);
        break;
    default:
        break;
    }
    
    CDialogEx::OnHotKey(nHotKeyId, nKey1, nKey2);
}

List Control

列表控件, 注意, 不是 ListBox, 是List

// 使用示例

// m_list 为 List Control 的添加变量
// 头文件中声明变量 CImageList m_imageList;
BOOL CListCtrlDemoDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // ... 省略无关代码

    // TODO: 在此添加额外的初始化代码
    // 设置风格
    //LONG lStyle;
    //lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口style
    //lStyle &= ~LVS_TYPEMASK; //清除显示方式位
    //lStyle |= LVS_REPORT; //设置style
    //SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置style

    // 设置扩展风格
    //DWORD dwStyle = m_list.GetExtendedStyle();
    //dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl)
    //dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl)
    //dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件
    //m_list.SetExtendedStyle(dwStyle); //设置扩展风格
    // 整行选中 + 网格线 + 跟踪选中
    m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TRACKSELECT);
    // 初始化列
    // 由于第一列不会对齐 所以先随意插入一列 然后在干掉
    m_list.InsertColumn(0, L"", LVCFMT_CENTER, 0);
    m_list.InsertColumn(1, L"第一列", LVCFMT_CENTER, 150);
    m_list.InsertColumn(2, L"第二列", LVCFMT_CENTER, 150);
    m_list.DeleteColumn(0);
    // 初始化图标组
    m_imageList.Create(32, 32, ILC_COLOR32, 1, 1);
    m_imageList.Add(m_hIcon);
    // 设置小图标组
    m_list.SetImageList(&m_imageList, LVSIL_SMALL);
    // 设置大图标组
    m_list.SetImageList(&m_imageList, LVSIL_NORMAL);

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 往 List Control 中添加行
void CListCtrlDemoDlg::OnBnClickedBtnAdd()
{
    // TODO: 在此添加控件通知处理程序代码
    int nCount = m_list.GetItemCount();
    int nTmp = 1;

    // 进行列表行的插入
    CString szBuf;
    // 第一列的设置
    szBuf.Format(L"第 %d 行的第 %d 列", nCount + 1, nTmp++);
    m_list.InsertItem(nCount, szBuf, 0);
    // 第二列的设置
    szBuf.Format(L"第 %d 行的第 %d 列", nCount + 1, nTmp++);
    m_list.SetItemText(nCount, 1, szBuf);
}

// 从 List Control 中删除当前选中的行
void CListCtrlDemoDlg::OnBnClickedBtnDel()
{
    // TODO: 在此添加控件通知处理程序代码

    // 方式1
    //int nCount = m_list.GetItemCount();
    //for (int i = nCount - 1; i >=0; --i)
    //{
    //    if (m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED)
    //    {
    //        m_list.DeleteItem(i);
    //        break;
    //    }
    //}

    //方法二:
    POSITION pos = m_list.GetFirstSelectedItemPosition();
    if (pos != NULL)
    {
        //while (pos)
        //{
        //    int nItem = m_list.GetNextSelectedItem(pos);
        //    m_list.DeleteItem(nItem);
        //    break;
        //}
        int nItem = m_list.GetNextSelectedItem(pos);
        m_list.DeleteItem(nItem);
    }
}

// 动态改变 List Control 的视图样式
void CListCtrlDemoDlg::OnSelchangeComboListMode()
{
    // TODO: 在此添加控件通知处理程序代码
    CComboBox* pCombo = (CComboBox*)GetDlgItem(IDC_COMBO_LIST_MODE);

    DWORD dwStyle = 0;

    switch (pCombo->GetCurSel())
    {
    case 0:    // 大图标
        dwStyle = LVS_ICON;
        break;
    case 1:    // 小图标
        dwStyle = LVS_SMALLICON;
        break;
    case 2:    // 列表
        dwStyle = LVS_LIST;
        break;
    case 3:    // 详细信息
        dwStyle = LVS_REPORT;
        break;
    default:
        break;
    }
    m_list.ModifyStyle(LVS_TYPEMASK, dwStyle);
}

Tree Control

树形控件

// 树形控件的使用示例

// m_tree 是 Tree Control 的添加变量

void CTreeCtrlDemoDlg::OnBnClickedBtnAdd()
{
    // TODO: 新增数据到Tree
    CString szInput;
    GetDlgItemTextW(IDC_EDIT_INPUT, szInput);

    HTREEITEM hItem = m_tree.GetSelectedItem();
    if (!hItem)
        hItem = TVI_ROOT;

    TVINSERTSTRUCTW ts = { 0 };
    ts.hParent = hItem;
    // 可以用如下方式来搞一搞, CString重载了LPCTSTR的转换
    ts.item.pszText = (LPWSTR)(LPCTSTR)szInput;
    ts.item.mask = TVIF_TEXT;
    ts.hInsertAfter = TVI_LAST;

    HTREEITEM hNewItem = m_tree.InsertItem(&ts);
    m_tree.SelectItem(hNewItem);
    // 保证新添加的可以显示
    m_tree.EnsureVisible(hNewItem);
}


void CTreeCtrlDemoDlg::OnBnClickedBtnDel()
{
    // TODO: 删除Tree中选中的节点
    HTREEITEM hItem = m_tree.GetSelectedItem();
    if (!hItem)
        return;
    HTREEITEM hParentItem = m_tree.GetParentItem(hItem);
    m_tree.DeleteItem(hItem);
    m_tree.SelectItem(hParentItem);
    
}


void CTreeCtrlDemoDlg::OnBnClickedBtnModify()
{
    // TODO: 修改Tree中选中的节点

    HTREEITEM hItem = m_tree.GetSelectedItem();
    if (hItem)
    {
        CString szInput;
        GetDlgItemTextW(IDC_EDIT_INPUT, szInput);
        m_tree.SetItemText(hItem, szInput);
    }
}


void CTreeCtrlDemoDlg::OnSelchangedTree(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    // TODO: 点击Tree节点之后的事件

    HTREEITEM hItem = m_tree.GetSelectedItem();
    if (hItem)
    {
        CString szInput = m_tree.GetItemText(hItem);
        SetDlgItemTextW(IDC_EDIT_INPUT, szInput);
    }

    *pResult = 0;
}

RichEdit Control

富文本框控件
可以为文本附加额外的格式.

注意, 要使用 RichEdit 控件, 必须在 InitInstance() 方法中调用 AfxInitRichEdit2() 方法.

// RichEdit Control 使用示例

// m_richEdit是RichEdit的添加变量

void CRichEditDemoDlg::OnBnClickedBtnColor()
{
    // TODO: 设置RichEdit的文字颜色
    CHARFORMAT cf = { 0 };
    cf.cbSize = sizeof(CHARFORMAT);
    
    m_richEdit.GetSelectionCharFormat(cf);

    CColorDialog colorDlg(cf.crTextColor);
    if (colorDlg.DoModal() == IDOK)
    {
        cf.crTextColor = colorDlg.GetColor();
        cf.dwMask = CFM_COLOR;
        cf.dwEffects = 0;
        m_richEdit.SetSelectionCharFormat(cf);
    }
}

void CRichEditDemoDlg::OnBnClickedBtnFont()
{
    // TODO: 设置RichEdit的文字字体
    CHARFORMAT cf = { 0 };
    cf.cbSize = sizeof(CHARFORMAT);

    m_richEdit.GetSelectionCharFormat(cf);

    CFontDialog fontDlg(cf);
    if (fontDlg.DoModal() == IDOK)
    {
        fontDlg.GetCharFormat(cf);
        m_richEdit.SetSelectionCharFormat(cf);
    }
}

Tab Control

选项卡控件

// Tab使用示例

// m_tab 为 Tab 的添加变量
// m_dlgPage1 和 m_dlgPage2 是自己新建的 Dialog 的对应的类

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

    // ... 省略无关代码

    // TODO: 在此添加额外的初始化代码

    m_tab.InsertItem(0, L"第一页");
    m_tab.InsertItem(1, L"第二页");
    // 创建标签页
    m_dlgPage1.Create(MAKEINTRESOURCE(IDD_DIALOG_PAGE1), &m_tab);
    m_dlgPage2.Create(MAKEINTRESOURCE(IDD_DIALOG_PAGE2), &m_tab);
    // 设置标签页
    CRect rect;
    m_tab.GetClientRect(rect);
    // 进行一点处理
    rect.top += 25;
    // 设置标签页的大小
    m_dlgPage1.MoveWindow(rect);
    m_dlgPage2.MoveWindow(rect);
    // 显示一个标签页
    m_dlgPage1.ShowWindow(SW_SHOW);

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CTabCtrlDemoDlg::OnSelchangeTabMain(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 选项卡标签页切换

    switch (m_tab.GetCurSel())
    {
        // 可以搞个enum
    case 0:
        m_dlgPage1.ShowWindow(SW_SHOW);
        m_dlgPage2.ShowWindow(SW_HIDE);
        break;
    case 1:
        m_dlgPage2.ShowWindow(SW_SHOW);
        m_dlgPage1.ShowWindow(SW_HIDE);
        break;
    default:
        break;
    }

    *pResult = 0;
}

Animate Control

动画控件

// 示例

// 打开文件
void CAnimateDemoDlg::OnBnClickedBtnSel()
{
    // TODO: 在此添加控件通知处理程序代码
    CFileDialog dlgFile(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, L"*.avi|*.avi|*.*|*.*", this);
    if (dlgFile.DoModal() == IDOK)
    {
        SetDlgItemTextW(IDC_EDIT_FILEPATH, dlgFile.GetPathName());
    }
}

// 播放文件
void CAnimateDemoDlg::OnBnClickedBtnPlay()
{
    // TODO: 在此添加控件通知处理程序代码
    CString szPath;
    GetDlgItemTextW(IDC_EDIT_FILEPATH, szPath);

    if (m_animate.Open(szPath))
    {
        m_animate.Play(0, -1, -1);
    }
    else
    {
        MessageBoxW(L"打开文件失败!", L"花心胡萝卜工作室", MB_OK | MB_ICONERROR);
    }
}

DateTime Control

日期选择控件

// 使用示例

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

    // ... 省略无关代码
    // TODO: 在此添加额外的初始化代码

    // 设置显示格式
    m_dateCtrlBegin.SetFormat(L"yyyy-MM-dd HH:mm:ss");
    m_dateCtrlEnd.SetFormat(L"yyyy-MM-dd HH:mm:ss");

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}


// 计算日期时间之间的间隔
void CDataTimeDemoDlg::SpanCount()
{
    SYSTEMTIME timeBegin = { 0 };
    SYSTEMTIME timeEnd = { 0 };
    // 获取当前控件时间
    m_dateCtrlBegin.GetTime(&timeBegin);
    // 获取另外的一个时间
    m_dateCtrlEnd.GetTime(&timeEnd);
    // 计算时间差
    FILETIME ftBegin, ftEnd;
    SystemTimeToFileTime(&timeBegin, &ftBegin);
    SystemTimeToFileTime(&timeEnd, &ftEnd);

    ULARGE_INTEGER uBegin, uEnd;
    uBegin.u.HighPart = ftBegin.dwHighDateTime;
    uBegin.u.LowPart = ftBegin.dwLowDateTime;
    uEnd.u.HighPart = ftEnd.dwHighDateTime;
    uEnd.u.LowPart = ftEnd.dwLowDateTime;

    ULONGLONG ullSpan = uEnd.QuadPart >= uBegin.QuadPart
        ? uEnd.QuadPart - uBegin.QuadPart
        : uBegin.QuadPart - uEnd.QuadPart;

    ULONGLONG ullSeconds = ullSpan / 10000000;    // 转换到秒
    ULONGLONG nMins = ullSeconds / 60;
    int nHours = nMins / 60;
    int nDays = nHours / 24;

    //WCHAR szBuf[MAXBYTE] = { 0 };
    //wsprintf(szBuf, L"两个时间间隔: \r\n秒数: %ull, \r\n分钟数: %d, \r\n小时数: %d, \r\n天数: %d",
    //    ullSeconds, nMins, nHours, nDays);
    //CString szOutput(szBuf);
    CString szOutput;
    szOutput.Format(L"两个时间间隔: \r\n秒数: %d, \r\n分钟数: %d, \r\n小时数: %d, \r\n天数: %d",
        (int)ullSeconds, (int)nMins, nHours, nDays);
    SetDlgItemTextW(IDC_EDIT_OUTPUT, szOutput);
}

// DateTime控件的选择事件
void CDataTimeDemoDlg::OnDatetimechangeDatetimepickerBegin(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMDATETIMECHANGE pDTChange = reinterpret_cast<LPNMDATETIMECHANGE>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    SpanCount();

    *pResult = 0;
}

// DateTime控件的选择事件
void CDataTimeDemoDlg::OnDatetimechangeDatetimepickerEnd(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMDATETIMECHANGE pDTChange = reinterpret_cast<LPNMDATETIMECHANGE>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    SpanCount();

    *pResult = 0;
}

Calendar Control

日历控件

// 使用示例

void CCalendarDemoDlg::OnSelchangeMonthcalendar(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMSELCHANGE pSelChange = reinterpret_cast<LPNMSELCHANGE>(pNMHDR);
    // TODO: 点击日期的时候的处理
    SYSTEMTIME st = { 0 };
    m_calendar.GetCurSel(&st);

    CTime time(st);
    int nDayOfWeek = time.GetDayOfWeek();

    CString szOutput;
    szOutput.Format(L"%d年%d月%d日, 是星期 %d. \r\n星期 0是星期日的意思.", st.wYear, st.wMonth, st.wDay, nDayOfWeek - 1);
    SetDlgItemTextW(IDC_STATIC_OUTPUT, szOutput);
    *pResult = 0;
}

完整工程下载

以上控件的所有工程测试代码, 点我下载
一个可被 Animate控件播放的 AVI文件, 点我下载

工程说明:

如有错误,请提出指正!谢谢.

回复