- PR -

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

投稿者投稿内容
reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-04 10:38
いつもお世話になります。
自作で日付入力コントロールを作成しています。
MaskedTextBox、その右に小さい正方形のボタン、
MaskedTextBoxの下に、MonthCalendarを配置しました。
デフォルトではカレンダーは非表示にしています。

そこで質問が2点あります・・・。

*----*----*----*----*----*----*----*----*----*----*

<1>
ボタンが押下されるとカレンダーの非表示/表示が切り替わるようにしましたが、
カレンダー表示中に、フォームとか、カレンダーに関係ないところがクリックされた時にも
表示されているカレンダーを非表示にしたいのですが、その方法がわからず困っています。

「ユーザコントロール 親フォーム」で検索し、
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=22416&forum=7&start=0
などを見つけたのですが、どうもわたしには良くわかりませんでした(泣)

ユーザコントロールでフォームのイベントを取得する事は可能でしょうか?


<2>
初期表示時カレンダーは非表示ですので、ユーザコントロールの大きさがカレンダーを含めた大きさだと使いづらい気がしましたので、MaskedTextBoxとボタンの大きさにしました。
ですがユーザコントロールが上記の大きさだと、カレンダーのVisibleをTrueにしてもカレンダーが見えません。

苦肉の策で以下のように、表示/非表示が切り替わる際に
コントロールの大きさを変更するようにしました。

Private Sub Btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Btn.Click
Calendar.Visible = Not Calendar.Visible
If Calendar.Visible = True Then
Me.Height = 166
Me.Width = 140
Else
Me.Height = 21
Me.Width = 98
End If
Me.BringToFront()
End Sub

一応これで希望の処理は出来ていますが、カレンダーコントロールの表示/非表示がボタンで変化するというのは良くある動作の気がするので、もっと良い方法があるのかもしれないな、と思っています。

*----*----*----*----*----*----*----*----*----*----*

・・・質問は以上です。

どちらか片方のみでもご回答頂けたら嬉しいです。
何卒ご教授よろしくお願い致します。


じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-07-04 12:17
引用:

reikoさんの書き込み (2007-07-04 10:38) より:

<1>
ボタンが押下されるとカレンダーの非表示/表示が切り替わるようにしましたが、カレンダー表示中に、フォームとか、カレンダーに関係ないところがクリックされた時にも表示されているカレンダーを非表示にしたいのですが、その方法がわからず困っています。


Calendar が表示される時に Calendar にフォーカスを合わせておき、フォーカス アウトしたら非表示にするという発想に変えてみてはいかがでしょうか?

引用:

<2>
苦肉の策で以下のように、表示/非表示が切り替わる際にコントロールの大きさを変更するようにしました。


これはあまり良くない実装だと思います。コントロールの大きさというのは環境依存です。また、UserControl コンテナが大きくなるということは周囲に配置されている Form のコントロールを汚らしく覆い隠す可能性があります。(汚らしく == Button の表面の色でベタ塗りされた状態) コンテナ自体を透明にすれば見た目の問題はありませんが。

大雑把な話をすれば、UserControl のコンテナ内に配置しなければ、UserControl の大きさは変えなくて済みますね。(今度は Form 上での表示位置の問題が出てきますが)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-04 13:18
じゃんぬねっとさん、いつもありがとうございます。
お世話になっております。

引用:

Calendar が表示される時に Calendar にフォーカスを合わせておき、フォーカス アウトしたら非表示にするという発想に変えてみてはいかがでしょうか?



実はそれも試してみたのですが、自作コントロールを配置したフォームの背景(?コントロールが配置されていないグレーの部分です)をクリックしても、ユーザコントロールのLostFocusイベントもCalendarのLostFocusイベントも発生してくれなかったのです(泣)
例えばタブ移動などで別のコントロールに移動した時などはそれで消えてくれるのですが・・・。

引用:

大雑把な話をすれば、UserControl のコンテナ内に配置しなければ、UserControl の大きさは変えなくて済みますね。(今度は Form 上での表示位置の問題が出てきますが)



なるほど・・・。大きさを変えると良くない理由、とても勉強になりました。

頂いたアドバイスは、ユーザコントロールにカレンダーを配置するのではなく、ユーザコントロールを使用するフォームにカレンダーを配置するという意味であってますか?だとしたら今回は無理なのです・・・。これから大規模プロジェクトの開発を行うにあたり、プログラマーさん達がその辺の意識をしないでPGできるようにする為のコントロール作成なので・・・。
「市販のツールを買ったほうが良いよ」って私は思うのですが^^;そうはいかないみたいです(泣)。




[ メッセージ編集済み 編集者: reiko 編集日時 2007-07-04 13:22 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-07-04 14:02
引用:

reikoさんの書き込み (2007-07-04 13:18) より:

実はそれも試してみたのですが、自作コントロールを配置したフォームの背景(?コントロールが配置されていないグレーの部分です)をクリックしても、ユーザコントロールのLostFocusイベントもCalendarのLostFocusイベントも発生してくれなかったのです(泣)
例えばタブ移動などで別のコントロールに移動した時などはそれで消えてくれるのですが・・・。


説明が難しいので安易な方法を書きますが、その MonthCalendar コントロールの Parent を追ってそれら (system.Windows.Forms.Control) のインスタンスから Parent_Click イベントを実装してそこで ActiveControl を null (Nothing) にしてはいかがでしょう。

引用:

頂いたアドバイスは、ユーザコントロールにカレンダーを配置するのではなく、ユーザコントロールを使用するフォームにカレンダーを配置するという意味であってますか?


配置する場所は Form で良いのですが、

引用:

だとしたら今回は無理なのです・・・。これから大規模プロジェクトの開発を行うにあたり、プログラマーさん達がその辺の意識をしないでPGできるようにする為のコントロール作成なので・・・。


UserControl 内で動的な解決を図れば良いので、このようなことにはなりません。面倒そうな方法をご想像していないでしょうか?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-04 14:48
じゃんぬねっとさん、ありがとうございます。
引用:

じゃんぬねっとさんの書き込み (2007-07-04 14:02) より:

説明が難しいので安易な方法を書きますが、その MonthCalendar コントロールの Parent を追ってそれら (system.Windows.Forms.Control) のインスタンスから Parent_Click イベントを実装してそこで ActiveControl を null (Nothing) にしてはいかがでしょう。



なるほど。どういう事をすればよいかのイメージはわきました。
ですが、イベントを自作した経験がなく、どのようにすれば良いのかわかりません。。。

http://dobon.net/vb/dotnet/beginner/eventhandle.html

このようなページを見つけ、コントロールの[Designer.vb]の所で

Friend WithEvents PForm As System.Windows.Forms.Form = Me.Parent

と記述した後
Private Sub PForm_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles PForm.Click

End Sub
を記述し、
Private Sub PForm_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles PForm.Click

の部分にブレークポイントを置いて動かしてみたのですが、止ってくれませんでした。

引用:

UserControl 内で動的な解決を図れば良いので、このようなことにはなりません。面倒そうな方法をご想像していないでしょうか?



すみません。たぶんお察しのとおりだと思います。
「UserControl 内で動的な解決を図る」とはどのような作業になるのでしょうか。

フォーム作成者がフォームにカレンダーを配置するけど、そのカレンダーの名前を統一するなどしてユーザコントロール側で何か処理を行う・・・とイメージしたのですが、間違ってそうですね(汗)
こちらはイメージも出来ていない状態でお恥ずかしい限りです・・・。

お手数をおかけして大変申し訳ないのですが、何卒ご教授よろしくお願い致します。
イシバシ
常連さん
会議室デビュー日: 2007/02/06
投稿数: 20
お住まい・勤務地: 浦安の隣
投稿日時: 2007-07-04 15:28
ためしに、こんなものを作ってみました。

・テキストボックスと、小さいボタンを持つユーザーコントロール
・上記ユーザーコントロールのプロジェクトにフォームを一つ追加。
・上記フォームにMonthCalendarを配置
・上記フォームのタイトルバーを消去。ついでにボーダーも消去。
・さらにMonthCalendarと同じサイズにし、リサイズ不可にする。
・ユーザーコントロール上のボタンクリックで、上記フォームをShow
・上記フォームDeactivateイベントで、自分をClose。

自作ユーザーコントロールを配置する(使用する)フォームの外観も変化する事なくMonthCalendarが表示され、かつMonthCalendar以外をクリックすると非表示になりました。
こういうことではないでしょうか?


うーん、でもDatetimePikkerのほうが使いやすい気がするんだけど、何か自作しないといけない理由があるんでしょうかね。

[ メッセージ編集済み 編集者: イシバシ 編集日時 2007-07-04 15:31 ]
reiko
ベテラン
会議室デビュー日: 2004/11/19
投稿数: 84
投稿日時: 2007-07-04 15:41
まず最初に、自作イベントの発生方法、自己解決しました。大変失礼しました。
[Designer.vb]ではMe.ParentはNothingでした。

そこでカレンダーを表示する為のボタンのクリックイベントで
PrtForm = Me.Parent
AddHandler PrtForm.Click, AddressOf PrtForm_Click
を記述する事により、親フォームのクリックイベントを拾う事が出来るようになりました。
大変失礼しました。


そして、イシバシさん。ご回答ありがとうございます。
なるほど、とても参考になりました。同一プロジェクト内にフォームを作成するという意味だったのですね。
納得です。ありがとうございます。早速今から試してみます。

引用:

うーん、でもDatetimePikkerのほうが使いやすい気がするんだけど、何か自作しないといけない理由があるんでしょうかね。


ですよね!!やっぱりそう思いますよね
当チームのメンバーは.NET歴が浅く、私もDatetimePikkerを使ったことがないのでもしかしたら間違いかも知れないんですけど、DatetimePikkerだと、年月日を数字キーを続けて打つだけじゃ入力できないですよね?年を打ったあと、月に移動するには→キーを押さないと移動できない事ありませんか?
勘違いだったらすみません・・・。それだけの理由で自作を命じられております;

シュリ
会議室デビュー日: 2007/01/29
投稿数: 15
投稿日時: 2007-07-04 15:47
reikoさん、こんにちは。

実は、ひそかにじゃんぬさんの答えを待っていたりしたのですが、私も書いてみることにしました。
NGな事をしているかもしれませんが・・・。

コード:

Private MonthCalendar1 As MonthCalendar

Private Sub UserControl1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MonthCalendar1 = New MonthCalendar
MonthCalendar1.Location = New System.Drawing.Point(Me.Location.X, Me.Location.Y + Me.Height)
Me.Parent.Controls.Add(MonthCalendar1)
MonthCalendar1.Visible = False

AddHandler MonthCalendar1.Leave, AddressOf MonthCalendar1_Leave
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MonthCalendar1.Visible = True
MonthCalendar1.Focus()
End Sub

Private Sub MonthCalendar1_Leave(ByVal sender As Object, ByVal e As System.EventArgs)
MonthCalendar1.Visible = False
End Sub



#New がふたつあったり、Privateじゃなかったりを修正。

[ メッセージ編集済み 編集者: シュリ 編集日時 2007-07-04 16:01 ]

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