DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DateTimePickerのカレンダークリック

環境/言語:[WindowsXP,VB.NET]
分類:[.NET]

いつも参考にさせて頂いています、よろしくお願いします。

DateTimePickerを使用しています。
コントロールの右端をクリックして表示されるカレンダー上の日付を選択(クリック)して閉じたのか、日付の選択なしで閉じたのか(他のコントロールをクリックした等)の情報がほしいのですがどのようにしたらよいのかわかりません。
最初ValueChangedイベントを使用しようと思ったのですが、カレンダーを開く前のValueと同じ日付をクリックした場合にValueChangedイベントが発生してくれません。
次にCloseUpイベントを使用してみましたが、この場合日付の選択をしなくても発生してしまいます。

もしよい方法がありましたらご教授よろしくお願いいたします。
> コントロールの右端をクリックして表示されるカレンダー上の日付を選択(クリック)して閉じたのか、日付の選択なしで閉じたのか(他のコントロールをクリックした等)の情報がほしいのですがどのようにしたらよいのかわかりません。
> 最初ValueChangedイベントを使用しようと思ったのですが、カレンダーを開く前のValueと同じ日付をクリックした場合にValueChangedイベントが発生してくれません。

 DTN_DATETIMECHANGE 通知メッセージを監視するというのはどうでしょうか? こちらは同じ日付を選択しても発生するようです。

 もしこの方法では問題があるようでしたら、 SPY++ で DateTimePicker コントロールがやり取りしているメッセージを把握することから始めることになるでしょうか。場合によっては、 DTM_GETMONTHCAL メッセージで Month Calendar のハンドルを取得→サブクラス化、ということまですることになるかも知れません。


 ところで、そもそも何故そのような判定が必要なのでしょうか? その仕様を見直すというのが一番現実的な対応のように感じます。
#余計なお世話でしょうけど(^_^;)
深山様、回答ありがとうございました。

>  ところで、そもそも何故そのような判定が必要なのでしょうか? その仕様を見直すというのが一番現実的な対応のように感じます。
> #余計なお世話でしょうけど(^_^;)

検索条件の入力用に使用していますが、日付を設定したい場合とそうでない場合があるため、
空白が入力できるようにする必要があり、苦し紛れに以下のようにしてみたのです。
(1)テキストボックス(txtDate)を配置
(2)その横にDateTimePickerを▼だけが見える幅にして更に配置
(3)▼をクリックしたらカレンダーが表示され日付を選択してValueChangedイベント発生したらDateTimePickerのValueをtxtDate.textに代入する

この方法ですと日付を設定したくない場合はtxtDateの日付をDeleteしてやればよいのですが、
その後▼クリックしてカレンダーを表示し同じ日付をクリックするとValueChangedイベントが発生せず、
txtDateに値を代入できないという問題が生じてしまったのです。

>  DTN_DATETIMECHANGE 通知メッセージを監視するというのはどうでしょうか? こちらは同じ日付を選択しても発生するようです。
>  もしこの方法では問題があるようでしたら、 SPY++ で DateTimePicker コントロールがやり取りしているメッセージを把握することから始めることになるでしょうか。場合によっては、 DTM_GETMONTHCAL メッセージで Month Calendar のハンドルを取得→サブクラス化、ということまですることになるかも知れません。

ネットで検索してみたのですが、DTN_DATETIMECHANGEの具体的な使用方法がわかりませんでした。
API関数を使用する、ということでしょうか?
同じ日付を選択しても発生するものでしたら解決しそうな気がします。
もし参考になるサイトなどございましたら教えていただけないでしょうか?
どうもすみません、よろしくお願いいたします。
> 検索条件の入力用に使用していますが、日付を設定したい場合とそうでない場合があるため、

ということでしたら、 ShowCheckBox / Checked プロパティを利用するだけで良いのでは‥‥?
#それともエンドユーザから別の形をという要望でもあったのでしょうか?


> API関数を使用する、ということでしょうか?

 いえ、前者の方法で良ければ API を使用する必要はありません。

> ネットで検索してみたのですが、DTN_DATETIMECHANGEの具体的な使用方法がわかりませんでした。
> もし参考になるサイトなどございましたら教えていただけないでしょうか?

 えっと、『DTN_DATETIMECHANGE』をキーワードに Google で(ウェブ全体から)検索したとき
最初にヒットする『猫でもわかるプログラミング』、そして二番目にヒットする『MSDN Library』が
参考になると思うのですけど‥‥厳しいでしょうか?(^_^;)
#『WM_NOTIFY』をキーワードに過去ログ検索すると他の通知メッセージを扱ったものが‥‥
#って、それでもやっぱりキツイですよね(汗)


 簡単なサンプルを下記します。参考になれば幸いです。
#フォーム上に直接 DateTimePicker1 配置してください。

    Private Structure NMHDR
        Public hwndFrom As IntPtr
        Public idFrom As Integer
        Public code As Integer
    End Structure

    Private Structure NMDATETIMECHANGE
        Public nmhdr As NMHDR
        Public dwFlags As Integer
        Public st As SYSTEMTIME
    End Structure

    Private Structure SYSTEMTIME
        Public wYear As Short
        Public wMonth As Short
        Public wDayOfWeek As Short
        Public wDay As Short
        Public wHour As Short
        Public wMinute As Short
        Public wSecond As Short
        Public wMilliseconds As Short
    End Structure

    Private Const WM_NOTIFY As Integer = &H4E
    Private Const DTN_FIRST As Integer = (0 - 760)
    Private Const DTN_DATETIMECHANGE As Integer = (DTN_FIRST + 1)

    Protected Overrides Sub WndProc(ByRef m As Message)
        If m.Msg = WM_NOTIFY AndAlso m.WParam.Equals(Me.DateTimePicker1.Handle) Then
            Dim nmh As NMHDR = CType(m.GetLParam(nmh.GetType()), NMHDR)
            If nmh.code = DTN_DATETIMECHANGE Then
                Dim nmdate As NMDATETIMECHANGE = _
                    CType(m.GetLParam(nmdate.GetType()), NMDATETIMECHANGE)
                Console.WriteLine("{0}/{1}/{2}", _
                    nmdate.st.wYear, nmdate.st.wMonth, nmdate.st.wDay)
            End If
        End If
        MyBase.WndProc(m)
    End Sub
深山様

お返事どうもありがとうございました。
サンプルまでご教授いただき、とても感謝です。

> えっと、『DTN_DATETIMECHANGE』をキーワードに Google で(ウェブ全体から)検索したとき
>最初にヒットする『猫でもわかるプログラミング』、そして二番目にヒットする『MSDN Library』が
> 参考になると思うのですけど‥‥厳しいでしょうか?(^_^;)

申し訳ありません、厳しかったです(泣)
なので、サンプルはとてもうれしかったです。

> ということでしたら、 ShowCheckBox / Checked プロパティを利用するだけで良いのでは‥‥?
> #それともエンドユーザから別の形をという要望でもあったのでしょうか?

日付のでる、直接入力可能なコンボボックスのようなものを希望されていまして、
それで今回のような方法でやってみました。
自己都合で申し訳ありませんが、現在他のトラブルで急ぎ修正をしていまして
ご教授いただいた方法を後日やってみて改めて結果報告させていただきます。
(ShowCheckBox / Checked プロパティも存在を知らなかったので一度試してみます。)
本来すぐに結果報告しなければいけないですが、まずはお礼まで・・・。
申し訳ありません、お許しください。
深山様

検証遅くなってしまってすみませんでした。
深山様のサンプルのConsole.WriteLineの部分を
TextBox.Text=DateTimePicker.Value.ToShortTimeString
に置換えてみましたところ、問題解決しました!

頂いたサンプルを読んでみたのですが、
WndProcというのはWidowsからのメッセージを取得する関数で
これにOverRideで機能を追加している、ということで合っていますでしょうか?
すみません、この辺りまだまだ勉強不足です、これからもっと勉強していこうと
思います。

ShowCheckBox / Checked プロパティも試してみましたが、
これも使えますね
(今回は客先の要望から外れてしまって使えなかったですが)
次回からこの方法も選択肢にしたいと思います。

本当にどうもありがとうございました。
今後ともよろしくお願いいたします。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板