C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: 子画面から親画面のタイマー制御


(過去ログ 178 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■102057 / inTopicNo.1)  子画面から親画面のタイマー制御
  
□投稿者/ Yuta (1回)-(2023/06/15(Thu) 11:23:21)

分類:[VB.NET/VB2005 以降] 

Windows10 VS2017(VB.net)でWindowsフォームのアプリケーションを作成しています。

やり方がわからないので教えてください。
よろしくお願いします。

親画面に時間表示とタイマーコントロール、子画面に開始/終了ボタンを作成しています。

親画面から子画面を呼び出し、子画面の開始ボタンを押すと
子画面はそのまま表示させた状態で親画面のタイマーを開始させたいです。

目的としては子画面を閉じたときには、子画面の開始ボタン押した瞬間からの経過時間を表示させることです。

サンプル等あれば助かります。
引用返信 編集キー/
■102058 / inTopicNo.2)  Re[1]: 子画面から親画面のタイマー制御
□投稿者/ 魔界の仮面弁士 (3654回)-(2023/06/15(Thu) 11:32:13)
No102057 (Yuta さん) に返信
> 親画面から子画面を呼び出し、子画面の開始ボタンを押すと
> 子画面はそのまま表示させた状態で親画面のタイマーを開始させたいです。

子画面側に、「開始ボタンが押されたときに発生するイベント」を定義し、
それを RaiseEvent するようにしてみてください。


そのうえで、親画面側では
 Private WithEvents child As 子フォーム
のようにしておき、
 Sub child_開始ボタンクリック(〜) Handles child.〜
  Me.Timer1.Start()
 End Sub
のように、親にて自身のタイマーを動作させます。
引用返信 編集キー/
■102059 / inTopicNo.3)  Re[1]: 子画面から親画面のタイマー制御
□投稿者/ 魔界の仮面弁士 (3655回)-(2023/06/15(Thu) 11:57:00)
No102057 (Yuta さん) に返信
> サンプル等あれば助かります。

掲示板に直書きですが、ソースのイメージ的にはこんな感じ。

ここでは子画面をモードレス(Show)にしていますが、
モーダル(ShowDialog)でも基本方針は同じです。

イベントを WithEvents で受ける代わりに、AddHandler で割り当てても良いでしょう。


'子画面
Public NotInheritable Class ChildForm
 Inherits Form
 Public Event StartButtonClicked As EventHandler
 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  RaiseEvent StartButtonClicked(Me, EventArgs.Empty)
 End Sub
End Class


'親画面
Public Class Form1
 Inherits Form
 Private beginTime As Date?
 Private WithEvents childForm As ChildForm
 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  Button1.Enabled = False
  childForm = New ChildForm()
  childForm.Show(Me)
 End Sub
 Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
  Text = (Now - beginTime)?.ToString()
 End Sub
 Private Sub childForm_StartButtonClicked(sender As Object, e As EventArgs) Handles childForm.StartButtonClicked
  beginTime = Now
  Timer1.Start()
 End Sub
 Private Sub childForm_FormClosed(sender As Object, e As FormClosedEventArgs) Handles childForm.FormClosed
  Timer1.Stop()
  childForm = Nothing
  Button1.Enabled = True
 End Sub
End Class


イベントで通知する以外の別案としては、
MethodInvoker や Action といったコールバック用の Delegate インスタンスを
子画面のコンストラクタに渡して、子画面側でそれを実行するという手もあるかも。
これなら、「Sub() Timer1.Start()」などのラムダ式でも渡せるので、
WithEvents 変数を用意する必要がなくなります。
引用返信 編集キー/
■102060 / inTopicNo.4)  Re[2]: 子画面から親画面のタイマー制御
□投稿者/ Yuta (3回)-(2023/06/15(Thu) 12:41:29)
No102059 (魔界の仮面弁士 さん) に返信
ご丁寧にありがとうございます。

サンプルを参考に作成してみます。
引用返信 編集キー/
■102061 / inTopicNo.5)  Re[3]: 子画面から親画面のタイマー制御
□投稿者/ Yuta (4回)-(2023/06/15(Thu) 15:35:09)
教えて頂いたサンプルをベースに作ってみました。
とりあえず、子画面でRaiseEventして親画面でデバッグ文を出そうとしているのですが、
どうしても親画面のForm2.Startのイベントが発生しません。

いろいろ調べたのですが、解決方法がわからず、おかしなところ等あればご指摘お願いします。


<親画面>
Public Class Form1
Private WithEvents Form2 As Form2

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim frm As New Form2
frm.ShowDialog()
End Sub

Private Sub Form2_Start(sender As Object, e As EventArgs) Handles Form2.Start
Debug.Print("TEST")
End Sub
End Class

<子画面>
Public Class Form2
Public Event Start As EventHandler

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
RaiseEvent Start(Me, EventArgs.Empty)
End Sub
End Class
引用返信 編集キー/
■102062 / inTopicNo.6)  Re[4]: 子画面から親画面のタイマー制御
□投稿者/ 魔界の仮面弁士 (3656回)-(2023/06/15(Thu) 17:56:17)
No102061 (Yuta さん) に返信
> frm.ShowDialog()
ShowDialog を呼び出した後は、呼び出し元は必ず Dispose を呼び出さねばなりません。
(一般的には Using ブロックが使われます)

Using frm As New Form2()
 frm.ShowDialog()
End Using



> Private WithEvents Form2 As Form2
この変数にフォームを代入すると、

> Private Sub Form2_Start(sender As Object, e As EventArgs) Handles Form2.Start
> Debug.Print("TEST")
> End Sub
このイベントハンドラで受信できるのですが、


> Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
> Dim frm As New Form2
> frm.ShowDialog()
> End Sub
この処理では、ローカル変数 frm をセットしただけで、
フィールド変数 Me.Form2 が Nothing のままなので、
イベントを捉えられていないのです。

たとえば
 Me.Form2 = frm
 frm.ShowDialog()
のようにすればイベントを捉えれます。


とはいえ、モーダルならばフォーム変数はローカル変数で充分なので、
WithEvents なフィールド変数を使うのは冗長です。その場合は
WithEvents 変数は使わずに AddHandler の方が楽でしょう。


'Handles 句は使いません。WithEvents 変数も削除しておきます。
Private Sub Form2_Start(sender As Object, e As EventArgs)
 Debug.Print("TEST")
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
 'ShowDialog を呼ぶ場合は、使用後に Using すべきです。
 '(閉じた後、New しなおさずに再表示したい場合は、Using を使わないこともあります)
 Using frm As New Form2()
  'AddHandler を使ってイベントハンドラーを割り当てます。AddressOf の代わりにラムダ式でも構いません。
  AddHandler frm.Start, AddressOf Form2_Start
  frm.ShowDialog()
 End Using
End Sub
引用返信 編集キー/
■102063 / inTopicNo.7)  Re[5]: 子画面から親画面のタイマー制御
□投稿者/ Yuta (5回)-(2023/06/15(Thu) 19:00:47)
No102062 (魔界の仮面弁士 さん) に返信
希望通りの動作ができるようになりました。
ありがとうございました。

非常に助かりました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -