- PR -

カレンダーを使用した日付入力コントロールを自作したい

投稿者投稿内容
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-05 18:14

まぁうまく動けばなんでもいいんですが。

ばらばらに
frm.Width = xx
frm.Height = xx
と設定すると内部でレイアウトエンジンが2回呼ばれてしまいます。
Paintイベントで毎回呼ぶのはちょっと無駄が多いですね。

Loadイベントでサイズを設定してもいいですが、
Loadではレイアウトエンジンがまだ呼ばれてないので
カレンダーコントロールが動的に大きさを変えない保証はないです。
実際には変えませんが。

カレンダー以外を使う場合、他のコントロールを複数配置する場合など、
いろいろな場合できちんと動く方法を考えると、
コードの流用ができるので楽です。

私は今回のようにコントロールをポップアップする場合は
AutoSizeを使っています。
コーディングも0ですし
レイアウトエンジンもトータルで1回しか呼ばれませんし、
いろんな意味で最も効率いいかなと。

reikoさんの問題、右側に余白ができてしまうという件ですが、
marginプロパティの問題ではないですか?
コントロールをフォームの左端において
marginを0にすれば解決すると思いますよ。



reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-05 18:32
イシバシさん、れいさん、ありがとうございます。
本当に何から何までお世話になりっぱなしで、大変恐縮です。
無知とは恐ろしいものです・・・(T.T)

もちろんいつもだってそうなのですが、
今回は特に「皆さんに育てていただいているなあ」って、かなりそう思います。

実はもう退社しまして、今は自宅から投稿しているので、明日また報告させて頂きます。
本当は家で試せればベストなのですが、今日はちょっと多忙で・・・(私事ですみません;)

本当に有り難うございます。
reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-06 09:31
皆様、おはようございます。この度はお世話になっております。
早速アドバイス頂いた事を実行しました。
1つだけ問題が残りましたが、以下の件が解決しました。
残った件は最後に質問させていただきます。

まず、カレンダーフォームのサイズの件ですが、
れいさんのアドバイスどおり、marginプロパティをゼロに設定する事で、
デザイン時に設定したフォームのプロパティ

AutoSize = True
AutoSizeMode = GrowAndShrink

が思い通りに動いてくれるようになりました。
(余白なしで表示されるようになりました。)
プログラムでのサイズ指定が不要になりました。



次にカレンダーフォームからユーザコントロールに値を設定する件ですが、
イシバシさんのご指摘の通り New していた事が大きな原因でした。(すみませんっ;)
(おっしゃるとおり、EdDateはユーザコントロール名でした。説明不足で申し訳ありません。)

正確にはそれ以外も修正を加えました。報告としてソースを添付します。

<カレンダー呼び出し側(ユーザコントロール側)ボタン押下時処理>
fCalendar = New frmCalendar(Me)
fCalendar.Location = New System.Drawing.Point(MskDt.PointToScreen(p).X, MskDt.PointToScreen(p).Y + MskDt.Height)
fCalendar.Show()


※今までは、Showの時にMeを渡そうとしてたのですが、コンストラクタで渡すように変更しました。

<カレンダーフォームの処理>

Private ParentCtrl As EdDate

'*** コンストラクタ ***
Public Sub New(ByVal uc As EdDate)

InitializeComponent()

Me.ParentCtrl = uc


End Sub

'*** フォームを閉じる処理 ***
Private Sub frmCalendar_Deactivate(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Deactivate

Me.Close()

End Sub

'*** 日付を選択された時の処理 ***
Private Sub MonthCalendar1_DateChanged(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DateRangeEventArgs) Handles MonthCalendar1.DateChanged

ParentCtrl.TextString = MonthCalendar1.SelectionStart.ToString("yyyy/MM/dd")
Me.Close()★

End Sub


・・・これで、カレンダーをキレイに表示させて、
カレンダーがアクティブでなくなった時には非表示にすることが出来て、
日付選択時に値を渡すことが出来るようになりました。

そして、「残った問題」というのは、前回も少し触れさせていただきました、
日付選択時の「Me.Close()」なんです。(上記★印部分)

やはり、この記述があることで、 MonthCalendar1_DateChanged イベントの
End Sub でエラーになってしまいます。エラー内容をもう一度記載します。

=========================================================================================
System.ObjectDisposedException はハンドルされませんでした。
Message="破棄されたオブジェクトにアクセスできません。\\\\r\\\\nオブジェクト名 'MonthCalendar' です。"
Source="System.Windows.Forms"
ObjectName="MonthCalendar"
StackTrace:
場所 System.Windows.Forms.Control.CreateHandle()
場所 System.Windows.Forms.MonthCalendar.CreateHandle()
場所 System.Windows.Forms.Control.get_Handle()
場所 System.Windows.Forms.Control.set_CaptureInternal(Boolean value)
場所 System.Windows.Forms.Control.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)
場所 System.Windows.Forms.Control.WndProc(Message& m)
場所 System.Windows.Forms.MonthCalendar.WndProc(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
場所 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
場所 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
場所 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
場所 System.Windows.Forms.Application.Run(ApplicationContext context)
場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
場所 Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
場所 Test.My.MyApplication.Main(String[] Args) 場所 (一応省略).vb:行 81
場所 System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
場所 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
場所 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
場所 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
場所 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
場所 System.Threading.ThreadHelper.ThreadStart()
=========================================================================================

・・・長いですが、一応全部貼り付けました;

あと、本当にこれだけなんです(泣)
皆様、本当にお世話になります!!もう少しお付き合いいただけないでしょうか。
何卒よろしくお願いいたします。

※情報を追加します。
Me.Close()の部分が
Me.Visible = Falseでも、Me.Hide() でもエラー内容は変わらないです。

※再度情報を追加します。
Me.Hide
Me.Visivle = False

の場合、MonthCalendar1_DateChanged宣言部分にブレークポイントを置いて、
シングルステップで実行する分にはエラーが発生しません。
上記ロジックを通った後、フォームのDeactivateが発生し、クローズされて終わります。
ですが、シングルステップでない場合はやはりエラーになってしまいます。



何卒よろしくお願い致します。

[ メッセージ編集済み 編集者: reiko 編集日時 2007-07-06 10:05 ]

[ メッセージ編集済み 編集者: reiko 編集日時 2007-07-06 11:11 ]
reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-06 14:48
皆様、この度は本当にお世話になりました。
どうしても解決する事が出来なかったので、無理やり解決することにしました。

前回の投稿後、試しにカレンダーを配置しているフォームにボタンを貼り付け、
ボタンのクリックイベントで Me.Close() を行ってみたところ、
エラーにはならなかったんです。
なんか、そうなるとカレンダーコントロールの問題。。。というか、どうしようもない問題に思えてきてしまって。

方法としては、カレンダー表示を別フォームにするのをやめ、
カレンダー以外の部分がクリックされた時にカレンダーを非表示にする処理だけ
プログラマーがフォームのイベントで書くようにする事にしました。
MaskedTextBoxのLostFocusで非表示にするところはユーザコントロールで書きました。

コントロールのデザインでカレンダーを配置するのではなく、
シュリさんにアドバイスしていただいた、プログラムでカレンダー表示をする方法をとりました。
「投稿日時:2007-07-04 15:47」の方法です。

相談の結果こうなりましたが、もし何か有力な情報がありましたら、今後の勉強の為教えてください。

皆様、今回は、本当に、本当にお世話になりました。
また何か質問するかもしれませんが、今後ともよろしくお願いします。
私も早く回答出来る側に回れるよう頑張ります。


[ メッセージ編集済み 編集者: reiko 編集日時 2007-07-06 14:50 ]
シュリ
会議室デビュー日: 2007/01/29
投稿数: 15
投稿日時: 2007-07-06 16:23
reikoさんこんにちは。
私は答えを持ち合わせていなかったので、いまさら出てきてしまったのですが・・・。

返事が遅い上に仕様との折り合いもありますが、DateChangedではなく、DateSelectedイベントを使うのではいけなかったのかなと。
ヘルプをご覧の上、却下されたかもしれませんが・・・。
マウスでの選択時にしか発生しないイベントですが、そのままだととても使いにくいコントロールになってしまうと思います。
reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-06 16:40
引用:

シュリさんの書き込み (2007-07-06 16:23) より:
reikoさんこんにちは。
私は答えを持ち合わせていなかったので、いまさら出てきてしまったのですが・・・。

返事が遅い上に仕様との折り合いもありますが、DateChangedではなく、DateSelectedイベントを使うのではいけなかったのかなと。
ヘルプをご覧の上、却下されたかもしれませんが・・・。
マウスでの選択時にしか発生しないイベントですが、そのままだととても使いにくいコントロールになってしまうと思います。



シュリさん、こんにちは。ご指摘ありがとうございます。
実は、前回投稿の方法に変更してから、
DateChangedからDateSelectedに変更しました。
DateChangedだと、月を変えただけでイベントが発生するのですね。気づかなかったのです。
ヘルプをみて決めた、とかでなく、単に知らなかったと言いますか・・・(恥)
カレンダーをダブルクリックして出てくるイベントがDateChangedだったので、
そのまま使っていました^^;

まったくお恥ずかしい限りです。
・・・もしかして、DateSelectedイベントならMe.Close()出来ちゃいますか?(汗)

今から早速試してみます。


===========
シュリさん、ありがとうございます!
出来ました!DateSelectedなら問題なくClose出来ました!(泣)

・・・本当にありがとうございます〜〜!!
これで、プログラマーがカレンダーを閉じる処理を記述することなく
コントロールを使えます!
本当にありがとうございました!とても助かりました!

今後ともよろしくお願い致します。





[ メッセージ編集済み 編集者: reiko 編集日時 2007-07-06 16:46 ]
イシバシ
常連さん
会議室デビュー日: 2007/02/06
投稿数: 20
お住まい・勤務地: 浦安の隣
投稿日時: 2007-07-06 16:49
確かに、DateChangedイベントだと同様の現象が起こりますね。

#送ったソースはDateSelectedになっていたと思いますが、そこまで気が回らない程テンパってたって事でしょう。お疲れ様でした。

#と思ったら、投稿したレスはDateChangedになってました・・・orz
誠に申し訳ありませんでした。

[ メッセージ編集済み 編集者: イシバシ 編集日時 2007-07-06 16:51 ]
reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-06 17:29
イシバシさん、この度は本当にお世話になりました。
先ほどメッセージ送らせていただきました。
ほんと、めっちゃテンパってました;お恥ずかしい限りです。
ロジックばっかり目が言っちゃって、宣言部分まで確認するのを怠りました。
本当に申し訳ありません。

ソースまで送っていただき、本当にありがとうございました。
あれがなかったら、たぶんまだ値を渡すところで悩んでたと思います;

皆さん、今回は本当にお世話になりました。
今回の事で少し.NETがわかってきた気がします。

またお世話になる事があるかもしれませんが、何卒よろしくお願い致します。



[ メッセージ編集済み 編集者: reiko 編集日時 2007-07-06 17:31 ]

スキルアップ/キャリアアップ(JOB@IT)