Ну, это оказалось намного проще, чем ожидалось.У меня было впечатление, что уведомление MCN_VIEWCHANGE
отправляется в wndproc дочернего дескриптора.Вместо этого он отправляется в DateTimePicker wndproc, но с дескриптором окна дочернего элемента MonthCalender (вот почему я не уловил его в своих первых попытках).Таким образом, реализация подходящей обработки этого уведомления оказалась прямой.Вот моя реализация в Delphi, расширяющая встроенный класс TDateTimePicker
:
const
MCN_VIEWCHANGE = MCN_FIRST - 4; // -750
type
tagNMVIEWCHANGE = record
nmhdr: TNmHdr;
dwOldView: DWORD;
dwNewView: DWORD;
end;
PNMNMVIEWCHANGE = ^TNMNMVIEWCHANGE;
TNMNMVIEWCHANGE = tagNMVIEWCHANGE;
type
{$SCOPEDENUMS ON}
TViewKind = (Month, Year, Decade, Century);
{$SCOPEDENUMS OFF}
TViewChange = procedure(Sender: TObject; OldView, NewView: TViewKind) of object;
type
TDateTimePicker = class(Vcl.ComCtrls.TDateTimePicker)
private
FOnViewChange: TViewChange;
procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
protected
procedure ViewChange(OldView, NewView: TViewKind);
public
published
property OnViewChange: TViewChange read FOnViewChange write FOnViewChange;
end;
procedure TDateTimePicker.ViewChange(OldView, NewView: TViewKind);
begin
if Assigned(FOnViewChange) then FOnViewChange(Self, OldView, NewView);
end;
procedure TDateTimePicker.WMNotify(var Message: TWMNotify);
var
vwchg: PNMNMVIEWCHANGE;
begin
if Message.Msg = WM_NOTIFY then begin
vwchg := PNMNMVIEWCHANGE(Message.NMHdr);
if vwchg.nmhdr.code = MCN_VIEWCHANGE then begin
ViewChange(TViewKind(vwchg.dwOldView), TViewKind(vwchg.dwNewView));
end;
end;
inherited;
end;