Files
minigui-docs/programming-guide-zh/MiniGUIProgGuidePart6Chapter15-zh.md
lisimeng123 12ea4e47e4 update
2022-11-18 00:00:48 +08:00

260 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 月历控件
月历控件monthcalendar提供一个类似日历的用户界面使用户可以方便的选择和设置日期。应用程序可以通过向月历控件发送消息来获取和设置日期。
你可以通过调用`CreateWindow`函数,使用控件类名称 `CTRL_MONTHCALENDAR`,来创建一个月历控件。
## 1.1 月历控件风格
月历控件可以用中文或英文等多种格式显示星期和月份等日期信息,这可以通过指定控件的风格为 `MCS_CHN``MCS_ENG_L``MCS_ENG_S` 来完成。如果月历控件风格中包括 `MCS_CHN` 的话,控件以中文显示日期信息;如果包括 `MCS_ENG_L`,以英文显示日期信息;如果包括 `MCS_ENG_S` 的话,将以简写的英文格式显示。
如果风格中包括 `MCS_NOTIFY` 的话,月历控件将在响应用户操作时等情况下产生相应的通知消息。
## 1.2 月历控件消息
### 1.2.1 获取日期
`MCM_GETCURDAY` 消息用来获取当前选择的日期中是当月中的第几天:
```c
int day;
day = SendMessage (hwndMonthcal, MCM_GETCURDAY, 0, 0) ;
```
`SendMessage` 函数返回值就是当前的天数。
`MCM_GETCURMONTH` 消息用来获取当前选择的日期中的月份值:
```c
int month;
month = SendMessage (hwndMonthcal, MCM_GETCURMONTH, 0, 0) ;
```
`SendMessage` 函数返回值就是当前的月份。
`MCM_GETCURYEAR` 消息用来获取当前选择日期中的年份:
```c
int year;
year = SendMessage (hwndMonthcal, MCM_GETCURYEAR, 0, 0) ;
```
`SendMessage` 函数返回值就是当前的年份。
`MCM_GETCURMONLEN` 消息用来获取当前月份的长度(该月有几天):
```c
int monthlen;
monthlen = SendMessage (hwndMonthcal, MCM_GETCURMONLEN, 0, 0) ;
```
`SendMessage` 函数返回值就是当前月份的长度。
`MCM_GETFIRSTWEEKDAY` 消息用来确定当前月份中的第一天是星期几:
```c
int weekday;
weekday = SendMessage (hwndMonthcal, MCM_GETFIRSTWEEKDAY, 0, 0) ;
```
`SendMessage` 函数返回值就是当前月份第一天的星期号,从 0 到 60 表示星期天。
`MCM_GETCURDATE` 消息获取月历控件中当前选择的日期:
```c
SYSTEMTIME systime;
SendMessage (hwndMonthcal, MCM_GETCURDATE, 0, (LPARAM)&systime) ;
```
`systime` 是一个 `SYSTEMTIME` 类型的结构,存放获取的年、月、日和星期几等日期信息。该结构还用于 `MCM_GETTODAY` 等消息,其结构定义如下:
```c
typedef struct _SYSTEMTIME
{
/* 年 */
int year;
/* 月 */
int month;
/* 日 */
int day;
/* 星期几 */
int weekday;
} SYSTEMTIME;
typedef SYSTEMTIME *PSYSTEMTIME;
```
`MCM_GETTODAY` 消息获取“今天”的日期:
```c
SYSTEMTIME systime;
SendMessage (hwndMonthcal, MCM_GETTODAY, 0, (LPARAM)&systime) ;
```
`systime` 也是一个 `SYSTEMTIME` 类型的结构。
### 1.2.2 设置日期
需要注意的是,在 Linux 系统中,设置日期可能需要特殊用户身份(如 root
`MCM_SETCURDAY` 消息设置当前选择的“天”,`MCM_SETCURMONTH` 消息设置当前的月,`MCM_SETCURYEAR` 消息设置当前的年:
```c
int day;
int month;
int year;
SendMessage (hwndMonthcal, MCM_SETCURDAY, day, 0) ;
SendMessage (hwndMonthcal, MCM_SETCURMONTH, month, 0) ;
SendMessage (hwndMonthcal, MCM_SETCURYEAR, year, 0) ;
```
`day``month``year` 分别指定新的天、月和年,如果这些值在合理的值范围之外,控件将采用最接近的一天、月或年。
`MCM_SETCURDATE` 消息设置当前选择的日期:
```c
SYSTEMTIME systime;
SendMessage (hwndMonthcal, MCM_SETCURDATE, 0, (LPARAM)&systime) ;
```
`MCM_SETTODAY` 把“今天”设为当前选择的日期:
```c
SendMessage (hwndMonthcal, MCM_SETTODAY, 0, 0) ;
```
### 1.2.3 调整颜色
应用程序可以通过 `MCM_GETCOLOR``MCM_SETCOLOR` 消息来获取和改变月历控件中各部分的颜色设置:
```c
MCCOLORINFO color;
SendMessage (hwndMonthcal, MCM_GETCOLOR, 0, (LPARAM)&color) ;
SendMessage (hwndMonthcal, MCM_SETCOLOR, 0, (LPARAM)&color) ;
```
`color` 是一个 `MCCOLORINFO` 类型的结构,用于保存颜色信息。
```c
typedef struct _MCCOLORINFO
{
/* 标题的背景色 */
int clr_titlebk;
/* 标题的文字颜色 */
int clr_titletext;
/* 年和月箭头的颜色 */
int clr_arrow;
/* 箭头高亮时背景色 */
int clr_arrowHibk;
/* 星期标题背景色 */
int clr_weekcaptbk;
/* 星期标题文字颜色 */
int clr_weekcapttext;
/* 天数部分背景色 */
int clr_daybk;
/* 天数部分高亮时背景色 */
int clr_dayHibk;
/* 天数部分文字颜色 */
int clr_daytext;
/* 非当前月部分天数文字颜色 */
int clr_trailingtext;
/* 高亮的文字颜色 */
int clr_dayHitext;
} MCCOLORINFO;
```
### 1.2.4 控件大小
为了能够正常显示其中的内容,月历控件有一个窗口最小限制值,`MCM_GETMINREQRECTW` 消息和 `MCM_GETMINREQRECTH` 消息分别用来获取最小宽度和最小高度值:
```c
int minw, minh;
minw = SendMessage (hwndMonthcal, MCM_GETMINREQRECTW, 0, 0) ;
minh = SendMessage (hwndMonthcal, MCM_GETMINREQRECTH, 0, 0) ;
```
`SendMessage` 函数的返回值就是最小宽度和高度值。
## 1.3 月历控件通知码
当用户点击月历控件并造成当前日期发生改变时,控件将产生 `MCN_DATECHANGE` 通知码。
## 1.4 编程实例
__清单 1.1__ 中的代码演示了月历控件的使用。该程序的完整源代码可见本指南示例程序包 `mg-samples` 中的 `monthcal.c` 程序。
__清单 1.1__ 月历控件示例程序
```c
#define IDC_MC 100
#define IDC_OK 200
/* 对话框模板:只有两个控件:月历控件和“确定”按钮 */
static CTRLDATA CtrlTime[]=
{
{
"monthcalendar",
WS_CHILD | WS_VISIBLE | MCS_NOTIFY | MCS_CHN,
10, 10, 240, 180,
IDC_MC,
"",
0
},
{
"button",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
260, 180, 50, 22,
IDC_OK,
"确定",
0
}
};
static DLGTEMPLATE DlgTime =
{
WS_VISIBLE | WS_CAPTION | WS_BORDER,
WS_EX_NONE,
0, 0, 320, 240,
"约会时间",
0, 0,
2, CtrlTime,
0
};
static int TimeWinProc(HWND hDlg, int message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case MSG_INITDIALOG:
break;
case MSG_COMMAND:
{
int id = LOWORD(wParam);
if (id == IDC_OK) {
char info[100];
SYSTEMTIME date;
/* 获取月历控件中的当前日期 */
SendMessage (GetDlgItem(hDlg, IDC_MC), MCM_GETCURDATE, 0, (LPARAM)&date);
sprintf (info, "你定于%d年%d月%d日会见总统!",
date.year, date.month, date.day);
MessageBox (hDlg, info, "约会", MB_OK | MB_ICONINFORMATION);
EndDialog (hDlg, 0);
}
}
break;
case MSG_CLOSE:
{
EndDialog (hDlg, 0);
}
return 0;
}
return DefaultDialogProc (hDlg, message, wParam, lParam);
}
```
![月历控件的使用](figures/Part4Chapter15-1.1.jpeg)
__图 1.1__ 月历控件的使用