DOBON.NET DOBON.NETプログラミング掲示板過去ログ

フォーム右上の閉じるボタン

分類:[.NET]

Form.Closingイベントでフォーム上の右上の閉じる(×)ボタンが押されたか否かを判断するにはどのようにすればよろしいのでしょうか?
ご教授ください。
よろしくお願いします。
こんばんは、てつ☆ミさん。ピラルクです。

[X]ボタンのイベントを直接捕らえるのは無理のようなので、
それ以外のForm.Closingを呼ぶ元となるイベントと協調して
Form.Closingで識別することはかろうじて可能のようです。
(開発環境の■ボタンは強制KillなのでClosingが来ない)

(補)このような識別が必要になるというような状態は、
    別のところに直すべき問題があると思われ、以下
    のようなトリッキーとも言える実装を試みること
    はおすすめしません。

'--------+---------+---------+---------*---------+---------+---------+----
'[X]ボタンでは閉じれないForm
'--------+---------+---------+---------*---------+---------+---------+----
Public Class Form1
  Inherits System.Windows.Forms.Form
  Implements IMessageFilter

...

  Private Const WM_CLOSE = &H10
  Private Const WM_NCLBUTTONDOWN = &HA1
  Private Const WM_NCMOUSEMOVE = &HA0
  Private Const WM_SYSCOMMAND = &H112
  Private Const SC_CLOSE = &HF060&

  Private m_Closable As Boolean = True

  Private Sub Form1_Load(ByVal sender As System.Object, _
                         ByVal e As System.EventArgs) Handles MyBase.Load
    Application.AddMessageFilter(Me)
  End Sub

  Private Sub Form1_Closing(ByVal sender As Object, _
    ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
    If Not m_Closable Then
      '[X]ボタンで閉じられかけている場合
      e.Cancel = True
    End If
  End Sub

  Private Sub btnClose_Click(ByVal sender As System.Object, _
              ByVal e As System.EventArgs) Handles btnClose.Click
    '閉じるボタンは常に閉じることが可能
    m_Closable = True
    Close()
  End Sub

  Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) _
                  As Boolean Implements IMessageFilter.PreFilterMessage
    If m.Msg = WM_NCLBUTTONDOWN Then
      '[X]の可能性あり
      m_Closable = False
    ElseIf m.Msg = WM_SYSCOMMAND And m.WParam.ToInt32 = SC_CLOSE Then
      'コントロールBOX(タスクバー含む)の[閉じる]あるいは"Alt+F4"
      m_Closable = True
    ElseIf m.Msg = WM_CLOSE Then
      'タスクマネージャでKillされる
      m_Closable = True
    End If
    Return False
  End Function
End Class

# なんか抜け道ありそう...
■No334に返信(てつ☆ミさんの記事)
> Form.Closingイベントでフォーム上の右上の閉じる(×)ボタンが押されたか否かを判断するにはどのようにすればよろしいのでしょうか?

私の発行しているメールマガジン「.NETプログラミング研究」の第13号で紹介していますので、こちらをご覧ください。

・メールマガジン 「.NETプログラミング研究」
http://dobon.net/vb/melma/index.html
PreFilterMessage では[X]ボタンで WM_SYSCOMMAND が来なかったので、
先のサンプルではFlagを使ってましたが、

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
ではちゃんと来るので、こちらを使う方がおすすめです。
(参).NETプログラミング研究 第13号
ピラルクさん、管理人さん、こんばんわ。
何とか解決できました。
ありがとうございました。

DOBON.NET | プログラミング道 | プログラミング掲示板