Используйте TMonthCalendar только на месяцы и годы - PullRequest
0 голосов
/ 19 марта 2019

Суть в том, что я хочу, чтобы календарь всегда отображался в месяцах, например:

Ожидаемое представление TMonthCalendar:

image

чтобы при нажатии на месяц вместо отображения дней месяца он оставался на этом экране и вызывал событие.

1 Ответ

2 голосов
/ 19 марта 2019

До Vista базовый элемент управления Win32 MonthCal , который TMonthCalendar, не имеет вообще никаких представлений, поэтому вы не можете делать то, о чем просите в XP и ранее, если вы не найдете сторонний календарь, который поддерживает то, что вы хотите в этих версиях Windows.

Однако в Vista и более поздних версиях базовый элемент управления MonthCal учитывает представление (но само по себе TMonthCalendar нет). Вы можете вручную отправить сообщение MCM_SETCURRENTVIEW на TMonthCalendar HWND, чтобы установить его начальное представление на MCMV_YEAR, и создать подкласс для его свойства WindowProc для перехвата CN_NOTIFY сообщений ( Оболочка VCL для WM_NOTIFY) ищет уведомление MCN_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, чтобы реагировать на просмотр изменений пользователем.

...