如何从TDateTimePicker的MonthCalendar子项接收MCN_VIEWCHANGE通知?

时间:2018-12-03 16:31:20

标签: windows delphi datetimepicker

Windows中的 DateTimePicker 控件在下拉期间创建 MonthCalendar 子控件,该控件在关闭时将释放。可以使用 DateTime_GetMonthCal 检索该子控件的句柄。

是否可以从该子控件获取MCN_VIEWCHANGE通知(如果可以,如何)?

Date and Time Picker

Month Calendar Control Reference

1 个答案:

答案 0 :(得分:1)

嗯,事实证明这比预期的要容易得多。我的印象是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;