- PR -

MDI子フォームで自分自身をアクティブにしたい

投稿者投稿内容
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2007-06-22 16:25
下記にて確認。

新規プロジェクト
MDIParent:Form1(Button1)
MDIChild:Form2,Form3

コード:

Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim f2 As New Form2
f2.MdiParent = Me
f2.Show()
Dim f3 As New Form3
f3.MdiParent = Me
f3.Show()
End Sub
End Class
Public Class Form3
Private Sub Form3_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles Me.Validating
e.Cancel = True
End Sub
End Class


あ、終われないのでデバッグ自体を終了してください。

[ メッセージ編集済み 編集者: まどか 編集日時 2007-06-22 16:28 ]
pine
会議室デビュー日: 2004/11/10
投稿数: 10
投稿日時: 2007-06-22 17:01
おお!確かにCancelが利いていますね。で、どうもMessageBoxが原因のようだと
わかりました。MessageBoxの表示が変なことだとは思いもしませんでした。

コード:
    Private Sub Form3_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles Me.Validating
        If MessageBox.Show("フォーカスを移しますか?", "", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.No Then
            e.Cancel = True
        End If
    End Sub



のような感じの処理にしてるんです。こうするとNoと答えるとMessageBoxが
2回表示されます。
MessageBoxが一旦Focusを奪ってしまうために、2回入ってしまうみたいですね。

原因はわかりましたが、う〜んどうすればいいんでしょうか? MessageBoxでの
問いかけはしたいのですよね。Noと答えたときだけ、Cancelしたい。

何か良いアイデア無いですか?
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2007-06-22 17:22
引用:

どうもMessageBoxが原因のようだとわかりました。MessageBoxの表示が変なことだとは思いもしませんでした。
(略)
のような感じの処理にしてるんです。こうするとNoと答えるとMessageBoxが
2回表示されます。
MessageBoxが一旦Focusを奪ってしまうために、2回入ってしまうみたいですね。


イベントの連鎖を前提にした仕組みでの典型的な不具合パターンです。

以降のイベントがキャンセルされるのはe.Cancel=True+End Subの直後です。
したがってそれ以前にどんな処理を入れても無駄だと思います。

どうしてもというなら、フォーカスに絡む全イベントにConsole.WriteLine等を書き
あらゆるパターンでのイベントの発生順序を調べてください。
そして法則を見つけてください。
その法則がわかれば「このタイミングでは処理は不要だな」と各イベントハンドラで判断できるはずです。※必ずではありません。
ただし、条件判断および状態保持変数のオンパレードになるのは間違いありません。
したがってお勧めしません。

個人的には、そこまでして注意を促すのであればそのフォームでOK,Cancelを必ず選択させるようにすべきと考えます。
pine
会議室デビュー日: 2004/11/10
投稿数: 10
投稿日時: 2007-06-22 19:23
色々とありがとうございました。

諦めがつきました。ValidatingではMessageBoxは出さないこととし、
Formのどこかにフォーカスが移らない理由を表示することにしました。

ただ、どうも不可解な動きがありさらに調べてみました。非アクティブにしたい
フォームにはDataGridViewが貼り付けてあるのですが、DataGridViewがあると
FormのVaidatingでCancel=Trueにしても、フォーカスが移ってしまうのです。
(まどかさんのサンプルで確認しました。)
で、親フォームを閉じようとしても、まどかさんのサンプルだと当然親は
終了できないのですが、それをやるとフォームに貼り付けてある別のコントロール
たとえばボタンなどのイベントがまったく飛んでこなくなるのです。

DataGridViewは貼り付けて、適当にカラムのコレクションを加えてあるだけです。
イベント処理も何もしていません。

DataGridViewを貼り付けると、Cancelがおかしくなる?なぜなんでしょうか?
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-06-23 00:28
ValidatingでMessageBoxを表示しちゃったのですか…。
それはダメですね。
やるならせめてLostFocusでないと。
それなら多少怪しいですが、動きますね。

>DataGridViewを貼り付けると、Cancelがおかしくなる?なぜなんでしょうか?

確かにおかしくなりますね。
バグですね。そんな話もあったような気がします。

.NetのForm実装はFocusやMDI周りにバグが多いです。
変わったことをやるとすぐにおかしくなります。
バグが頻発したり、やりたいことができない場合は
デザインを見直したほうがいいです。

MDIはドキュメントを切り替えて使えるというのが利点なので、
FOCUS固定ならMDIの意味がありません。

pine
会議室デビュー日: 2004/11/10
投稿数: 10
投稿日時: 2007-06-25 09:11
引用:

確かにおかしくなりますね。
バグですね。そんな話もあったような気がします。



バグですか…。根本的に仕様を見直したほうがよさそうですね。
いつもながらMicrosoftにはバグ回避を使用者側で行わないといけないので
大変です。

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