1

我的观点是我想让日历始终显示在月份视图中,如下所示:

预期的 TMonthCalendar 视图:

图片

这样当我单击一个月时,它不会显示该月的日期,而是停留在此屏幕上并调用该事件。

4

1 回答 1

2

在 Vista 之前,封装的底层Win32 MonthCal 控件TMonthCalendar根本没有视图的概念,因此您无法在 XP 和更早版本中执行您所要求的操作,除非您在那些 Windows 上找到支持您想要的内容的第 3 方日历版本。

但是,在 Vista 和更高版本中,底层的 MonthCal 控件是视图感知的(但TMonthCalendar它本身不是)。您可以手动向's发送MCM_SETCURRENTVIEW消息以将其初始视图设置为,并将其属性子类化以在用户更改活动视图时拦截消息(VCL 的包装器)以查找通知。您无法将控件锁定到特定视图,但您可以在用户将活动视图从“年”视图更改为“月”视图时做出反应,然后可以根据需要将日历重置回“年”视图。TMonthCalendarHWNDMCMV_YEARWindowProcCN_NOTIFYWM_NOTIFYMCN_VIEWCHANGE

例如:

class TMyForm : public TForm
{
__published:
    TMonthCalendar *MonthCalendar1;
    ...
private:
    TWndMethod PrevMonthCalWndProc;
    void __fastcall MonthCalWndProc(TMessage &Message);
    ...
public:
    __fastcall TMyForm(TComponent *Owner)
    ...
};

#include "MyForm.h"
#include <Commctrl.h>

#ifndef MCM_SETCURRENTVIEW

#define MCMV_MONTH      0
#define MCMV_YEAR       1

#define MCM_SETCURRENTVIEW (MCM_FIRST + 32)
#define MCN_VIEWCHANGE     (MCN_FIRST - 4) // -750

typedef struct tagNMVIEWCHANGE
{
    NMHDR           nmhdr;
    DWORD           dwOldView;
    DWORD           dwNewView;
} NMVIEWCHANGE, *LPNMVIEWCHANGE;

#endif

__fastcall TMyForm(TComponent *Owner)
    : TForm(Owner)
{
    if (Win32MajorVersion >= 6)
    {
        SendMessage(MonthCalendar1->Handle, MCM_SETCURRENTVIEW, 0, MCMV_YEAR);
        PrevMonthCalWndProc = MonthCalendar1->WindowProc;
        MonthCalendar1->WindowProc = MonthCalWndProc;
    }
}

void __fastcall TMyForm::MonthCalWndProc(TMessage &Message)
{
    PrevMonthCalWndProc(Message);
    if (Message.Msg == CN_NOTIFY)
    {
        if (reinterpret_cast<NMHDR*>(Message.LParam)->code == MCN_VIEWCHANGE)
        {
            LPNMVIEWCHANGE lpNMViewChange = static_cast<LPNMVIEWCHANGE>(Message.LParam);
            if ((lpNMViewChange->dwOldView == MCMV_YEAR) && (lpNMViewChange->dwNewView == MCMV_MONTH))
            {
                // do something ...
                SendMessage(MonthCalendar1->Handle, MCM_SETCURRENTVIEW, 0, MCMV_YEAR);
            }
        }
    }
}

如果您使用的是 C++Builder 10.1 Berlin 或更高版本,请查看更新的TCalendarView组件TCalendarPicker。它们都有一个DisplayMode您可以TDisplayMode::dmYear为当前视图设置的属性,以及一个On(Calendar)ChangeView对用户的视图更改做出反应的事件。

于 2019-03-19T18:24:07.167 回答