[译]永久日历生成器...嗯...至少要到2099年!
By robot-v1.0
本文链接 https://www.kyfws.com/applications/a-perpetual-calendar-generator-well-at-least-until-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 12 分钟阅读 - 5877 个词 阅读量 0[译]永久日历生成器…嗯…至少要到2099年!
原文地址:https://www.codeproject.com/Articles/14411/A-Perpetual-Calendar-Generator-well-at-least-until
原文作者:Shaun Harrington
译文由本站 robot-v1.0 翻译
前言
Combines images from the ‘My Pictures’ folder with ‘on-the-fly’ generated calendar grids, and sets the desktop background to the resulting image.
将"我的图片"文件夹中的图像与"即时"生成的日历网格合并,并将桌面背景设置为生成的图像.
介绍(Introduction)
我厌倦了全天候在任务栏上获取日期.或更糟糕的是,双击它可以了解当前月份的情况.另外,我想以某种方式使用自己的图像,这些图像会自动用作我的桌面背景.我写了这个项目来减轻痛苦.(I am sick of floating over the clock on the taskbar to get the date. Or worse, double clicking on it to get a glimpse of what the current month looks like. Also, I want to use my own images in some way that they are automatically used as my desktop background. I wrote this project to ease my pain.)
那里有类似的项目,但是这一项目的独特之处在于它使用了ATL'(There are similar projects out there, but this one is unique in that it uses the ATL ‘) CImage
基于GDI +的对象,“我的图片"文件夹中的随机图像以及自制的(’ object based on GDI+, random images from the ‘My Pictures’ folder, and a home brewed)**永动的(perpetual)**日历生成器.此外,该项目是使用Visual Studio 2005生成的.(calendar generator. In addition, the project was generated using Visual Studio 2005.)
作为实用程序:PCalGen是一个(As a utility: PCalGen is a)**永动的(perpetual)**日历生成器(就我们的生活而言),每次您启动计算机,更改显示设置或更改日期时,都会使用"我的图片"文件夹中的随机图像自动生成日历网格.该图像用作日历网格下的水印.生成日历页面的文本时使用桌面颜色.(calendar generator (as far as our lives are concerned anyway) that uses random images from the ‘My Pictures’ folder to automatically generate a calendar grid each time you start your computer, change a display setting, or the date changes. The image is used as a watermark under the calendar grid. The desktop color is used when generating the text of the calendar page.)
例如:PCalGen项目演示了一些很酷的东西.该项目包含用于生成1901年到2099年之间任何给定日期的日历页面的代码.请参见名为”(As an example: The PCalGen project demonstrates several cool things. The project contains code used to generate a calendar page for any given date between the years 1901 and 2099. See the file named ‘)CalendarMaker.cpp(CalendarMaker.cpp)’ 更多细节.同一文件还包含演示如何使用(' for more details. The same file also contains code that demonstrates how to use the) AlphaBlend()
功能来创建类似水印的图像.该项目还包含演示如何哄骗Shell将新生成的日历图像用作桌面背景的代码.最后,该项目包含的代码演示了用于关闭隐藏窗口应用程序的机制的简单实现.看到(function to create a watermark-like image. The project also contains code that demonstrates how to coax the Shell to use the newly generated calendar image as the desktop background. Finally, the project contains code that demonstrates a simple implementation of a mechanism used to shut down a hidden window application. See) CcalgenApp::InitInstance()
在文件"(in the file ‘)**卡尔根(calgen.cpp)**有关此机制的更多信息.(’ for more information on this mechanism.)
最新发布(Latest Release)
使用本文顶部的"最新版本"链接以获取最新的(Use the “Latest Release” link at the top of this article to get the most recent)**发布(release)**版.下载内容包括(version. The download includes the)**功能齐全(fully featured)**带有安装和卸载(MSI)的产品.(product with install and uninstall (MSI).)
公历(The Gregorian Calendar)
日历生成器((The calendar generator ()CalendarMaker.h(CalendarMaker.h),(,).cpp(.cpp))代码写起来很有趣.我做了足够的研究才能使自己前进.这意味着我对收集来产生逻辑的信息的准确性进行一些假设.我相信我已经很好地完成了将所有相关因素隔离到此文件定义的对象中的工作.如果您要使用此代码,则只需要进行代码审查(在本文的消息部分中有注释).我将根据需要更新本文和相关的下载.() code was some what fun to write. I did just enough research to get myself going. This means I make some assumptions with respect to the accuracy of the information I gathered to produce the logic. I believe I have done a pretty good job of isolating all the relevant factors into the object defined by this file. A code review (with comments posted in the message section of this article) is all I ask for if you want to use this code. I’ll make updates to this article and the associated downloads, as required.)
兴趣点(Points of Interest)
首先,在(First, in)图1)(Figure (1)),我们来看一下(, we’ll look at the) CcalgenApp::InitInstance()
方法.这是我们执行关机处理的地方.关闭过程如下所示:查找现有的互斥对象,如果找到,则按类名查找现有的窗口.超出关闭处理范围的应用程序的任何实例均基于该类名称创建了一个窗口.如果找到了该窗口,并且具有关闭标志,则通过用户消息将其传达给该窗口,从而使该窗口强制退出拥有它的应用程序实例.如果互斥锁以前不存在,并且具有关闭标志,则当前实例退出.这使我们可以使用关闭标志,而不必先检查以前的实例.除此之外的代码将注册窗口类,并基于新注册的类创建窗口的实例,并将其分配为主框架,以便MFC起作用.(method. This is where we do the shutdown processing. The shutdown processing goes something like this: look for an existing mutex, and if found, look for an existing window by class name. Any instance of the application that is beyond the shutdown processing has created a window based on this class name. If the window is found and we have the shutdown flag, we communicate it to the window via a user message which, in turn, causes the window to force the instance of the application that owns it to exit. If the mutex does not previously exist and we have the shutdown flag, the current instance quits. This allows us to use the shutdown flag without having to first check for a previous instance. The code beyond that registers the window class, creates an instance of the window based on the newly registered class, and assigns it as the main frame so that MFC behaves.)
BOOL CcalgenApp::InitInstance() {
// Single instance stuff all mixed
// in with '-shutdown' command line processing.
// Used to enforce a single instance<
HANDLE hMutex = ::CreateMutex( NULL, false, s_lpszMutexGUID );
// If the mutex already existed then
// we can assume a previous instance exists.
if(hMutex && (ERROR_ALREADY_EXISTS == GetLastError())) {
// Let this instance's handle to the mutex go.
::CloseHandle(hMutex);
hMutex = NULL;
// Find the window in the previous instance and signal
// it to shutdown if '-shutdown' is on the command line.
HWND hWnd = FindPreExistingHWND();
if( hWnd ) {
if(m_lpCmdLine && !lstrcmp( TEXT("-shutdown"),
m_lpCmdLine) ) {
::PostMessage(hWnd, WM_USER_SHUTDOWN, 0, 0);
}
}
return FALSE; // Exist this instance.
}else {
// Still want to test for the shutdown flag...
// but not a second time so in this else here.
if(m_lpCmdLine && !lstrcmp( TEXT("-shutdown", m_lpCmdLine) ) {
}
}
// If we got here this is the first (primary) instance...
...
}
图1)(Figure (1))
文件 ‘(The file ‘)CalGenWnd.cpp(CalGenWnd.cpp)‘定义了MFC(’ defines the MFC) CWnd
称为"(derivation called ‘) CCalGenWnd
‘用作我们的主要框架.该对象处理:标准窗口开销;创建用于随机选择图像的图像文件列表;处理用于检查是否需要更新的计时器;通过关闭通知提示退出应用程序.我没有要特别强调的内容(’ which is used as our main frame. This object deals with: standard window overhead; creating the list of image files used in the random selection of an image; handling the timer used to check for the need for updates; quitting the application when signaled to do so via the shutdown notification. I don’t have anything particular that I want to highlight in ‘)CalGenWnd.cpp(CalGenWnd.cpp)',但是如果需要,您应该检查该文件.(’, but you should examine this file if you feel the need to.)
我要我们检查的下一个文件名为"(The next file that I want us to examine is named ‘)MakeCalander.cpp(MakeCalander.cpp)'.该文件是项目的内容.它包含用于根据2001年到2097年左右的任何日期生成日历网格的代码.(’. This file is the meat of the project. It contains the code to generate calendar grids based on any date from the year 2001 to the year 2097 or so.)
在(In)图(2)(Figure (2)),我们看到了用于确定leap年的方法.在五个步骤中概述了逻辑.该代码是我自己编写的逻辑代码,因此请随时进行改进.(, we see the method used to determine leap years. The logic is outlined in the five steps. The code is my own attempt to code the logic, so please feel free to improve on it.)
//1. If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5.
//2. If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.
//3. If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.
//4. The year is a leap year (it has 366 days).
//5. The year is not a leap year (it has 365 days).
/*static*/ bool CCalendarMaker::IsLeapYear(int nYear) {
if(nYear%4 == 0) { // step 1
if(nYear%100 == 0) { // step 2
if(nYear%400 == 0 ) { // step 3
return true; // step 4
}
} else
return true; // step 4
}
return false; // step 5
}
图(2)(Figure (2))
中的两个数组(The two arrays in)**图(3)(Figure (3))**是可以进行更好地研究以进行确认的东西.它们用于确定一年中第一天的名称.我做了一些测试,它们似乎起作用了….我只是没有数学证明.如果您喜欢这种事情,请随时提供任何证据,我将在这里详细介绍.(are something that could be researched better for confirmation. They are used to determine the name of the first day of the year. I did some testing, and they seem to work…. I just don’t have the mathematical proofs. Feel free to provide any proof if you are hip to that sort of thing, and I will detail them here.)
第一个数组是一个表格(二维),其中包含从2001年到2097年的年份,以4的递增增量排列,并在各列中指示年份的第一天所在的日期.请注意,日期不是正常的.第二个数组表示在第一个数组的标题中指定的日期顺序.数字代表一周中各天的正常顺序.(The first array is a table (two dimensional) that contains the years from 2001 to 2097, arranged in ascending increments of four, and in columns that indicate the name of they day the first of the year falls on. Note that the days are not in normal order. The second array represents the order of the days specified in the header of the first array. The numbers represent the normal order of the days of the week.)
要使用该表确定给定年份的第一天的名称,必须找到与所讨论的年份最接近的最大值,而不用对其进行遍历.请注意年份标题列中的日期,并算出任何其他天数,需要将每年的每一天添加到该列中的年份以达到所讨论的年份.(To use the table to determine the name of the first day of a given year, one must find the largest value that is nearest being equal to the year in question without going over it. Note the day in the column header for the year, and count off any additional days, one for each year needed to be added to the year in the column to reach the year in question.)
/*static*/ int CCalendarMaker::s_years2000[] = {
/* Mon Sat Thu Tue Sun Fri Wed */
2001, 2005, 2009, 2013, 2017, 2021, 2025,
2029, 2033, 2037, 2041, 2045, 2049, 2053,
2057, 2061, 2065, 2069, 2073, 2077, 2081,
2085, 2089, 2093, 2097
};
/*static*/ int CCalendarMaker::s_years1900[] = {
/* Tue Sun Fri Wed Mon Sat Thu */
1901, 1905, 1909, 1913, 1917, 1921, 1925,
1929, 1933, 1937, 1941, 1945, 1949, 1953,
1957, 1961, 1965, 1969, 1973, 1977, 1981,
1985, 1989, 1993, 1997
};
/*static*/ int CCalendarMaker::s_days2000[] = {
1,
6,
4,
2,
0,
5,
3
};
/*static*/ int CCalendarMaker::s_days1900[] = {
2,
0,
5,
3,
1,
6,
4
};
图(3)(Figure (3))
最后,在这里(Finally, here in)**图(4)(Figure (4))**是使用上述数组确定给定年份(1月1日)的第一天(通过数字引用)的名称的代码.(, is the code that uses the arrays described above to determine the name (via numeric reference) of the day the first of a given year (January 1) falls on.)
// 0=sun, 1=mon, 2=tue, 3=wed, 4=thu, 5=fri, 6=sat
/*static*/ int CCalendarMaker::GetStartDay(int nYear) {
if(nYear >= 1901 && nYear <= 2000) {
int nIndex = 0;
while( nYear >= s_years1900[nIndex] )
nIndex++;
int nDay = s_days1900[(nIndex-1)%];
nDay += (nYear - s_years1900[nIndex-1]);
if(nDay>6)
nDay -= 7;
return nDay;
} else if(nYear >= 2001 && nYear <= 3000) {
int nIndex = 0;
while( nYear >= s_years2000[nIndex] )
nIndex++;
int nDay = s_days2000[(nIndex-1)%];
nDay += (nYear - s_years2000[nIndex-1]);
if(nDay>6)
nDay -= 7;
return nDay;
}
return -1;
}
图(4)(Figure (4))
在(In)图(5)(Figure (5)),我们可以看到用于表示每个月中天数的值的数组.我们将看一下代码,看看在以后的leap年中如何处理.(, we can see the array of values used to represent the amount of days in each month. We will look at the code to see how we account for leap years later.)
/*static*/ int CCalendarMaker::s_daysPerMonth[] = {
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
};
图(5)(Figure (5))
其余代码详见(The rest of the code detailed in)**图(6)(Figure (6))**是个 ‘(is the ‘) CCalendarMaker::MakeCalendar()
' 方法.乍一看,这种方法似乎有点麻烦,但确实非常简单.(’ method. At first glance, this method appears to be a bit of a bear but is really pretty straightforward.)
首先,我们获取当前日期,并从中提取一些计算所需的数据.接下来,我们确定当月第一天的日期.现在,我们拥有制作日历网格所需的一切.(First, we get the current date, and extract some data from it that we need for our calculations. Next, we determine the name of the day that the first of the current month falls on. Now, we have everything we need to make a calendar grid.)
在下面的评论中,我包括了计划生成的网格的平面图.生成网格和混合图像的代码超出了此范围.您可以在这里找到使用(In the comments that follow, I have included a floor plan for the grid that I plan to generate. The code to generate the grid and the blended image are beyond that. This is where you will find examples of using the) CImage
对象和(object and the) AlphaBlend()
方法.(method.)
// Image file to use, output path... will be a jpg.
bool CCalendarMaker::MakeCalendar(LPCWSTR lpszInFilePathName,
LPCWSTR lpszOutFilePathName){
// Get the current time
// and stash it in one of these cool CTime objects.
SYSTEMTIME st = {0};
GetLocalTime(&st);
CTime timeNow(st);
// Use the time object to get some value
// we need for generating a calendar page.
int nCurrentYear = timeNow.GetYear();
int nCurrentMonth = timeNow.GetMonth();
int nCurrentDayOfMonth = timeNow.GetDay();
int nStartDayOfCurrentYear = GetStartDay(nCurrentYear);
// Get the month and year display strings ready.
CString strMonth = CCalendarMaker::s_months[nCurrentMonth-1];
CString strYear;
strYear.Format(L"%d", timeNow.GetYear());
int nFirstDayOfMonth = 0;
if(nCurrentMonth==1) {
nFirstDayOfMonth = nStartDayOfCurrentYear;
} else {
int nDayAccum = 0;
int nIndexMonth = 0;
while(nIndexMonth < (nCurrentMonth-1)) {
nDayAccum += s_daysPerMonth[nIndexMonth++];
}
nDayAccum += nCurrentDayOfMonth;
if(nCurrentMonth >= 3 && IsLeapYear(nCurrentYear))
nDayAccum += 1;
nFirstDayOfMonth =
(nDayAccum-(nCurrentDayOfMonth-nStartDayOfCurrentYear))%7;
}
// I think we have everything we need now.
// Generate the calendar image to using
// this floorprint... *today* should be in red.
// 0 1 2 3 4 5 6 Given: January 9th, 2006
// |---------------------------| |---------------------------|
// 0 | <MONTH> <YEAR> | | January 2006 |
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// 1 | S | M | T | W | T | F | S | | S | M | T | W | T | F | S |
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// 2 | | | | | | | | | | | | | | | 1 |
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// 3 | | | | | | | | | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// 4 | | | | | | | | |<9>| 10| 11| 12| 13| 14| 15|
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// 5 | | | | | | | | | 16| 17| 18| 19| 20| 21| 22|
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// 6 | | | | | | | | | 23| 24| 25| 26| 27| 28| 29|
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// 7 | | | | | | | | | 30| 31| | | | | |
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// 8 | copyright | | copyright |
// |---|---|---|---|---|---|---| |---|---|---|---|---|---|---|
// Get the screen dims.
int scX = GetSystemMetrics(SM_CXSCREEN);
int scY = GetSystemMetrics(SM_CYSCREEN);
scX = (scX - (scX/10));
scY = (scY - (scY/10));
// Make a bitmap 10% smaller in width and height
HWND hwndDesktop = GetDesktopWindow();
HDC hDCDeskTop = GetDC(hwndDesktop);
HDC hDC = CreateCompatibleDC(hDCDeskTop);
if(hDC) {
HBITMAP hBitmap = CreateCompatibleBitmap(hDCDeskTop, scX, scY);
CDC dc;
CBitmap bitmapCal;
bitmapCal.Attach(hBitmap);
dc.Attach(hDC);
dc.SelectObject(bitmapCal);
dc.SelectObject(GetStockObject(WHITE_BRUSH));
// Create the background
dc.Rectangle(0,0,scX, scY);
CImage imagePicture;
HRESULT hr = imagePicture.Load(lpszInFilePathName);
int nPicWidth = imagePicture.GetWidth();
int nPicHeight = imagePicture.GetHeight();
if(S_OK == hr) {
HDC hDCPic = CreateCompatibleDC(hDCDeskTop);
HBITMAP hBitmapPic =
CreateCompatibleBitmap(hDCDeskTop, scX, scY);
CBitmap bitmapPic;
bitmapPic.Attach(hBitmapPic);
CDC dcPic;
dcPic.Attach(hDCPic);
dcPic.SelectObject(hBitmapPic);
dcPic.SelectObject(GetStockObject(WHITE_BRUSH));
dcPic.Rectangle(0,0,scX, scY);
imagePicture.BitBlt(dcPic.GetSafeHdc(), 0, 0, SRCCOPY);
BITMAP bm;
bitmapPic.GetBitmap(&bm);
// dc.BitBlt(0,0,scX,scY,&dcPic,0,0,SRCCOPY);
// Normal draw code for debugging.
BLENDFUNCTION bf;
bf.AlphaFormat = 0;
bf.BlendFlags = 0;
bf.BlendOp = AC_SRC_OVER;
bf.SourceConstantAlpha = 64;
if(scX > nPicWidth) {
dc.AlphaBlend((scX/2)-(nPicWidth/2),(scY/2)-(nPicHeight/2),
nPicWidth,nPicHeight,&dcPic,0,0,nPicWidth,nPicHeight,bf);
// Watermark type drawing.
} else {
int nLeftPos = nPicWidth/2-(scX/2);
int nTopPos = nPicHeight/2-(scY/2);
if(nLeftPos<0)
nLeftPos=0;
if(nTopPos<0)
nTopPos=0;
dc.AlphaBlend(0,0,scX,scY,&dcPic,nLeftPos,nTopPos,
scX-nLeftPos,scY-nTopPos,bf); // Watermark type drawing.
}
}
dc.SetBkMode(TRANSPARENT);
int nRectWidth = scX/7;
int nRectHeight = scY/8;
if(m_fontTitle.GetSafeHandle()==0) {
MakeFonts(dc);
}
dc.SetTextColor(GetSysColor(COLOR_DESKTOP));
// Draw header (row 0)
dc.SelectObject(&m_fontTitle);
CString strOut = strMonth;
strOut += L" ";
strOut += strYear;
CRect rectHeader(0, 0, scX, nRectHeight/2);
dc.DrawText(strOut, strOut.GetLength(), rectHeader,
DT_CENTER|DT_VCENTER|DT_SINGLELINE);
// Draw days of the week (row 1)
dc.SelectObject(&m_fontDays);
CRect rectDay(0, nRectHeight/2, nRectWidth, nRectHeight*2);
for(int nIndexDayNames = 0; nIndexDayNames <= 6; nIndexDayNames++) {
dc.DrawText(s_dayNames[nIndexDayNames],
lstrlen(s_dayNames[nIndexDayNames]),
rectDay, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
rectDay.left += nRectWidth;
rectDay.right = rectDay.left + nRectWidth;
}
// Draw days of the month in each the grid (rows 2-7)
dc.SelectObject(&m_fontNumbers);
rectDay.left = nRectWidth * nFirstDayOfMonth;
rectDay.right = rectDay.left + nRectWidth;
rectDay.top = nRectHeight+nRectHeight/2;
rectDay.bottom = rectDay.top+nRectHeight;
int nNextRow = nFirstDayOfMonth;
int nLastDayInMonth = CCalendarMaker::s_daysPerMonth[nCurrentMonth-1];
if(nCurrentMonth==2 && IsLeapYear(nCurrentYear) )
nLastDayInMonth += 1;
for(int nIndexDayNumbers = 1; nIndexDayNumbers <= nLastDayInMonth;
nIndexDayNumbers++) {
CString strDayNumber;
strDayNumber.Format(L"%d", nIndexDayNumbers);
if(nIndexDayNumbers==nCurrentDayOfMonth) {
dc.SetTextColor(RGB(255,0,0));
}
dc.DrawText(strDayNumber, strDayNumber.GetLength(),
rectDay, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
if(nIndexDayNumbers==nCurrentDayOfMonth)
dc.SetTextColor(GetSysColor(COLOR_DESKTOP));
rectDay.left += nRectWidth;
rectDay.right = rectDay.left + nRectWidth;
nNextRow++;
if(nNextRow == 7) {
rectDay.left = 0;
rectDay.right = nRectWidth;
rectDay.top += nRectHeight;
rectDay.bottom = rectDay.top+nRectHeight;
nNextRow = 0;
}
}
//Draw footer (row 8)
dc.SelectObject(&m_fontTitle);
CRect rectFooter(0, nRectHeight*7, scX, nRectHeight*8);
rectFooter.bottom -= 10;
strOut.LoadStringW(IDS_WEBSITE);
dc.DrawText(strOut, strOut.GetLength(), rectFooter,
DT_CENTER|DT_VCENTER|DT_SINGLELINE);
dc.SelectObject(&m_fontDays);
strOut.LoadStringW(IDS_COPYRIGHT);
dc.DrawText(strOut, strOut.GetLength(), rectFooter,
DT_CENTER|DT_BOTTOM|DT_SINGLELINE);
// Store the image
CImage newImage;
newImage.Attach((HBITMAP)dc.GetCurrentBitmap()->GetSafeHandle());
newImage.Save(lpszOutFilePathName);
}
return true;
}
图(6)(Figure (6))
如果我遗漏了您认为应该在文章中提及的任何细节,请告诉我.(If I left out any details you think should be mentioned in the article, please let me know.)
如果您可以花一秒钟的时间对本文进行评分,甚至发表评论,我们将不胜感激.(If you could take one last second to rate this article or even leave a comment, it would be much appreciated.)
谢谢阅读!(Thanks for reading!)
历史:(History:)
-
1.04-2006年7月1日(1.04 - July 1, 2006)
- 修复了安装程序中的错误,该错误导致程序在重新启动后无法启动.(Fixed bug in installer that caused program to not launch after reboot.)
- Config对话框视图模式组合是一个下拉列表^无法再键入.(Config dialog view mode combo is a pull down list… can no longer type into it.)
-
1.03-2006年6月16日(1.03 - June 16, 2006)
- 修复了导致2007年和2008年开始日期的计算错误的错误.(Fixed bug that caused bogus calculation off the start day for years 2007 and 2008.)
-
1.02-2006年6月15日(1.02 - June 15, 2006)
- 表示某些假期(元旦,情人节,总统日,圣帕特里克节,复活节,阵亡将士纪念日,五月五日,母亲节,父亲节,独立日,劳动节,万圣节和圣诞节).(Indicates some holidays (New Year’s Day, Valentine’s Day, President’s Day, St. Patrick’s Day, Easter, Memorial Day, Cinco De Mayo, Mother’s Day, Father’s Day, Independence Day, Labor Day, Halloween, and Christmas).)
-
1.01-2006年6月14日(1.01 - June 14, 2006)
- 包括配置工具.(Includes configuration tool.)
- 用户选择的布局.(User selected layout.)
- 用户选择的颜色.(User selected colors.)
- 用户选择的Alpha混合值.(User selected alpha blend value.)
- 功能齐全的安装和卸载.(Fully featured install and uninstall.)
-
1.00-2006年6月10日(1.00 - June 10, 2006)
- 初始发行.(Initial release.)
学分:(Credits:)
- 卡伦的万年历页面(Karen’s Perpetual Calendar Page)
- 美国劳工部(US Department of Labor)
- 南澳大利亚天文学会(Astronomical Society of South Australia)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C++ VC8.0 WinXP Windows Win2K Visual-Studio GDI+ VS2005 Dev 新闻 翻译