MonthCalendarで日付が選択されたかどうかを知るには?


やまだ  2014-11-05 01:45:47  No: 46858  IP: [192.*.*.*]

こんにちは。

いつもお世話になっております。

開発環境は、delphiXE3 enterprise(update2適用済)、win7(sp1)です。

MonthCalendarを使ってDateTimePickerを自作しようと思っています。

同系の質問をしているのですが、質問内容が違うので、投稿することにしました。

monthcalendarで日付が選択されたかどうかを確認する方法は無いでしょうか?

適当なイベントがなかったので、clickイベントに以下のコードを書いたのですが、カレンダーの年月(2014年11月)が表示されているタイトル部をクリックしても閉じてしまいます。

procedure TForm2.MonthCalendar1Click(Sender: TObject);
begin
  form1.maskedit1.Text:=datetostr(MonthCalendar1.Date);
  modalresult:=mrok;
end;

clickイベントなので当然と言えば当然なのですが。

日付がクリックされたときのみ、form2の画面を閉じたいです。

clickイベント以外のイベントがあれば、教えてほしいです。

どなたか教えてください。

よろしくお願いします。

編集    削除
Mr.XRAY  2014-11-05 15:35:20  No: 46859  IP: [192.*.*.*]

TMonthCalendar の OnClick イベントで,
カレンダーのどの部分をクリックしたかを検出するサンプルです.
Form1 から Form2 を表示します.
Form2 には TMonthCalendar を配置しておきます.

動作確認は,Windows 7 U64(SP1) + Delphi XE5(UP2) Pro です.


--------------------- Form1 のコード ---------------------------------

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Left := Self.Left + 100;
  Form2.Top  := Self.Top + 200;
  Form2.ShowModal;
  Panel1.Caption := DateToStr(Form2.FDataTime);
end;


--------------------- Form2 のコード ---------------------------------

type
  TForm2 = class(TForm)
    MonthCalendar1: TMonthCalendar;
    procedure MonthCalendar1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
  public
    { Public 宣言 }
    FDataTime : TDateTime; //この値をForm1で取得する
  end;

var
  Form2: TForm2;

implementation

uses CommCtrl;

{$R *.dfm}

{ TForm2 }

//-----------------------------------------------------------------------------
//  TMonthCalendarのOnClickイベント処理
//  クリックしたマウスの位置を取得し
//  どんな通知メッセージでOnClickが発生したかを調べる
//  WM_NOTIFYメッセージで調べる方法もある(WMNotifyメソッド使用)
//
//  usesにCommCtrlが必要
//  (コモンコントロールの定数値やレコード型の定義等が書かれているユニット)
//-----------------------------------------------------------------------------
procedure TForm2.MonthCalendar1Click(Sender: TObject);
var
  MousePos : TPoint;
  HitInfo  : TMCHitTestInfo;
begin
  GetCursorPos(MousePos);
  MousePos       := MonthCalendar1.ScreenToClient(MousePos);
  HitInfo.cbSize := SizeOf(HitInfo);
  HitInfo.pt     := MousePos;

  //MonthCal_HitTestマクロを使用
  //Delphi XE以前では以下のメッセージを使用
  //SendMessage(MonthCalendar1.Handle, MCM_HITTEST, 0, Longint(@HitInfo));
  MonthCal_HitTest(MonthCalendar1.Handle, HitInfo);

  //クリックした場所が日付関係だったらこのフォームを閉じる
  if HitInfo.uHit and MCHT_CALENDARDAY <> 0 then begin
    FDataTime := MonthCalendar1.Date;
    ModalResult := mrOk;
  end;
end;

--------------------- Form2 のコード 終り ---------------------------------


MCHT_CALENDARDAY については以下を参照.
こういうメッセージ関係は,日本語はほとんどないので,
[このページを訳す] をクリックしてみることになります.

https://www.google.co.jp/search?num=50&site=webhp&source=hp&q=MCHT_CALENDARDAY+site%3Ahttp%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2F&oq=MCHT_CALENDARDAY+site%3Ahttp%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2F&gs_l=hp.12...0.0.2.41.0.0.0.0.0.0.0.0..0.0....0...1c..58.hp..14.0.0.80xrR1ghXVg

コントロールの通知メッセージについては,以下を参照.
MonthCalendar, DateTimePicker は,Windows (マイクロソフト) が提供しているコントロールです.
こういうコントロールを一般的に「コモンコントロール」と言っています.
コモンコントロール類を Delphi から利用するためのコードが ComCtrls ユニットにあります.
ComCtrls, CommCtrl は,Common Control(s) の略でしょう.多分.

[2−4 WM_NOTIFY での通知メッセージ]
http://mrxray.on.coocan.jp/Halbow/VCL02.html#VChap2-4

編集    削除
au  2014-11-05 18:06:42  No: 46860  IP: [192.*.*.*]

通知メッセージを利用する方法
usesにComCtrls, CommCtrlを追加
MonthCalendarを使ってるformの定義の前に以下の定義を追加
  TMonthCalendar = class(ComCtrls.TMonthCalendar)
  private
    FOnDaySelect: TNotifyEvent;
    procedure SetOnDaySelect(const Value: TNotifyEvent);
  protected
    procedure CNNotify(var Message: TWMNotifyMC); message CN_NOTIFY;
  public
    property OnDaySelect: TNotifyEvent read FOnDaySelect write SetOnDaySelect;
  end;

implementationの下に以下を追加
procedure TMonthCalendar.CNNotify(var Message: TWMNotifyMC);
begin
  inherited;
  with Message, NMHdr{$IFNDEF CLR}^{$ENDIF} do
  begin
    case code of
      MCN_SELECT:
        if Assigned(FOnDaySelect) then
          FOnDaySelect(Self);
    end;
  end;
end;

使う場合はFormのOnCreateででも以下の感じでイベントをセットしたら良いかと。
MonthCalendar1.OnDaySelect := OnDaySelect;

これでユーザーが日付を選択した場合のみイベントが走ります。

編集    削除
山本隆  2014-11-05 20:13:29  No: 46861  IP: [192.*.*.*]

蛇足ですが、JVCLのTJvMonthCalendar2では、日付が選択されるとOnSelectイベントが発生するようになっています。
ソースコードも参考になるかもしれません。

編集    削除