65.9K
CodeProject 正在变化。 阅读更多。
Home

MS Outlook 风格的日期重复模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (20投票s)

2002年4月14日

CPOL

8分钟阅读

viewsIcon

333804

downloadIcon

4843

具有类似于 MS Outlook 的用户界面的日期重复模式引擎

Sample Image

Sample Image

致谢

感谢 Keith Rule 提供的 MemDC 类。感谢所有提供反馈和代码的 CP 用户,这些反馈和代码用于我之前发布的 DateEditMiniCalendar 项目。

关于日期重复模式

许多应用程序都需要能够安排约会、研讨会或申请等。当涉及的日期超过几个时,能够以重复模式安排这些项目是必须的。

我曾寻找过相关的源代码,但对找到的内容不满意。市面上有很多解决方案(可在 Google 上搜索),但我查看过的那些要么不值那个价钱,要么写得不好,要么不能正常工作,要么过于有限。

日期重复模式最大的技术难题在于,存在无数种可能的模式,每种都需要单独编程。大多数重复模式代码(包括我自己的)会选择最常用的几种模式并提供支持。此外,它们很少支持将各种模式组合起来(例如,每月的第一、第三和最后一个星期五)。我的实现基于 MS Outlook,并支持 MS Outlook 中的 7 种模式。此外,我的实现不包括组合模式的支持。

抛开技术问题不谈,事件很少完全按照特定的定义模式发生。经常会出现这样的情况:一个事件原定于星期五,但被重新安排到星期四。此外,假期、休假和其他事件会干扰和修改这些事件的时间安排。我所合作的用户正是出于这个原因而避免使用 MS Outlook 的重复模式。相反,他们会为涉及的各个日期安排单独的约会。这通常是一个繁琐的过程,在某些情况下,容易出错。

关于本实现

如上所述,我的实现基于 MS Outlook。我处理这个项目的方式是提供与 MS Outlook 相同的支持级别作为起点。然后,我审查了各种能够使我受益的增强功能。

我研究了**组合日期模式**的能力,其问题不在于技术层面,而在于用户界面和可用性。用户界面需要看起来和工作起来是什么样的?普通用户能理解吗?我需要提供一个二级用户界面供高级用户使用吗?如果有人设置了组合模式,其他人能理解吗?我决定不实现组合支持,因为我无法充分回答这些问题。我开发的引擎应该能够轻松地容纳组合,假设我(或其他人)能够令人满意地回答这些问题。

我审查的下一个增强功能是在主重复模式中实现**跳过模式**的支持。跳过模式允许自动从生成模式中删除特殊日期(例如,假期、休假等),并自动将适当的日期添加到模式中。例如,“跳过圣诞节,改在下一个星期一举行”。我在核心引擎中实现了对该功能的支持。然而,我还没有开发配套的用户界面,因为这(根据我的用户)优先级较低。我计划在后续版本中添加此功能。

我还审查了为用户提供对模式中包含日期的**精细控制**。这将允许用户从模式中删除特定日期,并将特定日期添加回模式中。在与我的用户合作后,我认为这是最需要提供的功能。我的实现对此提供了支持,并且用户界面提供了一种简单的方式供用户控制模式。

实现概述

CFPSRecurringDates 类提供了核心日期模式生成器支持。这是一个实用类,没有直接的用户界面。提供了访问模式详细信息和修改它的方法。该类公开了一个 Serialize 函数,因此可以轻松地集成到许多项目中。(但是,您可能需要实现支持将配置数据持久化到数据库。)

CPrShtDateRecurCPrPgDateRecurBasicCPrPgDateRecurPreview 类提供了用于操作模式引擎的用户界面。这些类需要 IDD_DATE_RECUR_BASICIDD_DATE_RECUR_PREVIEWIDB_RECUR_IMAGES 资源对象。

此外,我还使用了之前开发的迷你日历控件和日期编辑/选择控件。这些项目可在 Code Project 上找到,在此处在此处

入门

将重复日期支持添加到您的项目中

  1. 复制下面列出的 .cpp 和 .h 文件,并将它们包含在您的项目中。

      FPSDatePickerCtrl.h
      FPSDatePickerCtrl.cpp
      FPSDateTimeButtonCtrl.h
      FPSDateTimeButtonCtrl.cpp
      FPSDateTimeCtrl.h
      FPSDateTimeCtrl.cpp
      FPSDateTimePopupCtrl.h
      FPSDateTimePopupCtrl.cpp
      FPSMiniCalendarCtrl.h
      FPSMiniCalendarCtrl.cpp
      FPSMiniCalendarListCtrl.h
      FPSMiniCalendarListCtrl.cpp
      FPSRecurringDates.h
      FPSRecurringDates.cpp
      MemDC.h
      OleDateTimeEx.h
      OleDateTimeEx.cpp
      PrPgDateRecurPreview.h
      PrPgDateRecurPreview.cpp
      PrShtDateRecur.h
      PrShtDateRecur.cpp
      PrShtDateRecurBasic.h
      PrShtDateRecurBasic.cpp
  2. DateRecur.rc 文件(在演示项目中)复制 IDD_DATE_RECUR_BASICIDD_DATE_RECUR_PREVIEWIDB_RECUR_IMAGEIDB_DATEPICKER_BUTTON 资源到您的项目中。

实现细节

CFPSRecurringDates

核心日期重复引擎。

重要方法

GeneratePattern(CPtrList& List) 调用此函数来执行重复模式并检索结果集。
如果日期模式配置为无结束日期,则此函数只会生成模式中的前 31 个出现。如果这不够,您需要使用其他 GeneratePattern 函数之一。
GeneratePattern(CPtrList& List, COleDateTime& dtEndBy) 调用此函数来执行重复模式,并检索直到 dtEndBy 参数指定的截止日期为止的结果集。
GeneratePattern(CPtrList& List, int iMaxOccurences) 调用此函数来执行重复模式,并检索直到指定的最大出现次数的截止日期为止的结果集。
CleanupDateList(CPtrList &List) GeneratePattern 函数接受一个 CPtrList& 参数,并用指向 COleDateTime 对象的指针填充它。在列表被销毁之前,有必要清理该列表。
IsDateInPattern(COleDateTime& dtCheck) 调用此函数以确定指定日期是否存在于模式中。
此版本的函数用于低频率检查(例如,一次或两次),但不应用于循环中,因为它可能非常慢,因为它必须在每次调用时重新生成模式。
IsDateInPattern(CPtrList& List, COleDateTime &dtCheck) 调用此函数以确定指定日期是否存在于先前生成并存储在 List 中的模式中。
与前一个版本相比,此版本在性能上更优。

持续开发

本项目仍在开发中,但我发布的代码已经过测试,并且在我所知范围内能正常工作。

我目前正在努力将跳过模式的支持集成到用户界面中。此外,我还将核心引擎封装成了一个 COM 组件,并添加了数据库持久化支持。此工作是为了实现 ASP(以及可能的 ASP.NET)版本的用户界面。一旦我完成了 ASP(ASP.NET?)版本的项目,我将把它发布到 Code Project。

我还在与该组件的用户合作,以确定还需要哪些其他功能/增强功能。我不知道这会揭示什么,但如果存在重大更改,我将把它们发布到 Code Project。

注释

您可以自由地在您的项目中使用此代码,无论是个人项目还是专业项目。它可以用于免费软件、共享软件或商业软件,无需许可费等。此代码按“原样”提供,可能会导致宇宙崩溃,因此请谨慎使用。对于由此崩溃的任何结果,我概不负责。我唯一的要求是您在您的应用程序的致谢中包含我的名字,并且在源代码中保留标题注释。

变更历史

2002年4月20日 感谢 Neville Franks 识别出数值输入方式存在的问题。
此外,感谢 Martin Bohring 指出了某些本地化问题。
  • 修改了基本配置对话框,对数值字段进行输入过滤。这可以防止由于 DDX_ 函数映射到整数而导致的对话框消息框弹出。
  • 修改了 CFPSDateTimeCtrl,使其自动根据控制面板中的区域设置设置日期格式。
  • COleDateTimeEx 函数中添加了用于检索控制面板中设置的日期/时间格式并将值转换为 C 样式的函数。
  • 修改了用于填充开始/结束时间组合框的方法,以使用控制面板中设置的适当时间格式。
2002年4月22日 感谢 Michael A. Barnhart 提出了一个新的月度模式。
  • 添加了一个新的月度模式选项。此选项允许 [第一个|第二个|第三个|第四个|最后一个] [日期|工作日|周末日|星期日|等] 的每 X 个月 [加|减] X 天
2002年4月23日 感谢 Michael A. Barnhart 发现了涉及 2 个组合框中重复条目的错误。
感谢 Kwakkie 指出了由于本地化问题(我的懒惰)导致的年模式问题。此外,时间组合框未正确填充(同样是本地化问题),并且无法使用数字键盘输入数字字段。
  • 修正了 2 个组合框中重复条目的问题。
  • 修正了年模式中由于使用 ParseDateTime 而不是 SetDate 引起的问题。
  • 修正了由 ConvertVBFormatToCFormat 函数中不正确的功能导致的时间组合框问题。
  • 修正了数字字段不允许使用数字键盘输入的问题。
© . All rights reserved.