フォームから別アプリのプロセス起動中のイベントについて

解決


himizu  2012-04-13 22:13:52  No: 147552

VB.netで作成したフォームから別のアプリを起動した際に
起動元フォームのボタン操作ができてしまいます。
以下の様に処理しているのですが、
ビューワーアプリ起動中にビューワーアプリ画面を少しずらすと
フォーム画面が現れます。そこでボタン1を押すとその時は何も起こらないのですが
ビューワーアプリを終了すると、先程押したボタン操作が実行されてしまいます。。

Dim viewerProcess As System.Diagnostics.Process = 
 System.Diagnostics.Process.Start(VIEWER_EXEFOLDER, prevfilepath)

'//呼び出し元を操作できないように画面制御する
Me.Enabled = False

'//終了するまで待機
viewerProcess.WaitForExit()

'//不要になった時点で破棄
viewerProcess.Close()
viewerProcess.Dispose()

ビューワーのアプリ起動中のフォーム画面へのイベントをキャンセルする方法など
ありますでしょうか。
宜しくお願い致します。


ポポン  2012-04-13 22:51:12  No: 147553

Process.Startの前にMe.Enabled = False(または対象ボタンのEnabled = False)にするとどうですか?


himizu  2012-04-14 20:15:43  No: 147554

ポポン様

ご提案有難うございますmm

場所を変えてもダメでした。
フォームアプリに制御が戻った時に
別アプリ起動中に発生したイベントが発生してしまいます。。


魔界の仮面弁士  2012-04-15 00:59:08  No: 147555

> 先程押したボタン操作が実行されてしまいます。。

アプリがビジー状態(イベント処理など)の最中に行われた
ユーザー操作(マウスやキーボード入力)というものは、
メッセージキューとして溜められていき、順番待ちになっています。

そしてこのメッセージキューは、アプリケーションがアイドル状態に戻った時
(つまり、ビジー状態ではなくなったとき)に、後追いで処理されます。

このような理由から、Enabled = False の間に行われたボタン操作が、
後から実行されるという事態になります。

対応策としては、たとえばこういった方法が考えられます。

(案1) 別アプリの終了待ちが終わった後に発生する Idle イベントをとらえ、
  そのタイミングで Enabled プロパティの値を True に戻す。

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Me.Enabled = False
        AddHandler Application.Idle, AddressOf Application_Idle
        Using p As Process = Process.Start("notepad.exe", "C:\temp\newFile.txt")
            p.WaitForExit()
            p.Close()
        End Using
    End Sub

    Private Sub Application_Idle(sender As Object, e As EventArgs)
        RemoveHandler Application.Idle, AddressOf Application_Idle
        Me.Enabled = True
    End Sub
End Class

(案2) ビジー状態になっていたアプリケーションが、アイドル状態に
  戻ったかどうかを Idle イベント+フラグ変数で管理しておき、
  そのフラグ変数を見ることで、ビジー状態のときに発生した処理を無視する。

Public Class Form1
    Private isBusy As Boolean = False
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        AddHandler Application.Idle, AddressOf Application_Idle
    End Sub
    Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
        RemoveHandler Application.Idle, AddressOf Application_Idle
    End Sub
    Private Sub Application_Idle(ByVal sender As Object, ByVal e As EventArgs)
        isBusy = False
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If isBusy Then Return

        Me.Enabled = False
        isBusy = True
        Using p As Process = Process.Start("notepad.exe", "C:\temp\newFile.txt")
            p.WaitForExit()
            p.Close()
        End Using
        Me.Enabled = True
    End Sub
End Class


himizu  2012-04-16 21:51:10  No: 147556

魔界の仮面弁士様

ご返信有難う御座います。

案1にて想定する動作となりました。有難うございます。

アイドル中に発生したイベントを管理し、
フォームアプリに制御が戻った時点で破棄して
その後フォームアプリ制御を解除するという方向で対応しようと思います。

案2についてもまた試してみようと思います。

解決済みとさせて頂きます。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加