MSDN CloseReason.UserClosing
で、ユーザーがフォームを閉じることにしたことがわかりましたが、Xボタンをクリックする場合も閉じるボタンをクリックする場合も同じです。では、コードでこれら2つをどのように区別できますか?
皆さんありがとう。
回答:
WinFormsを要求していると想定すると、FormClosing()イベントを使用できます。イベントFormClosing()は、フォームが閉じられるときにトリガーされます。
ユーザーがXまたはCloseButtonをクリックしたかどうかを検出するには、送信者オブジェクトを介してそれを取得できます。たとえば、senderをButtonコントロールとしてキャストし、その名前が「CloseButton」などであることを確認してください。
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
if (string.Equals((sender as Button).Name, @"CloseButton"))
// Do something proper to CloseButton.
else
// Then assume that X has been clicked and act accordingly.
}
それ以外の場合は、MDIContainerFormを閉じる前にすべてのMdiChildrenを閉じる、または保存されていない変更のイベントチェックなど、FormClosingイベントに固有の何かを実行したかったため、XまたはCloseButtonがクリックされたかどうかを区別する必要はありませんでした。私によると、これらの状況下では、どちらのボタンとも区別する必要はありません。
ALT+で閉じるF4と、FormClosing()イベントがトリガーされます。フォームに閉じるようにメッセージが送信されるためです。イベントをキャンセルするには、
FormClosingEventArgs.Cancel = true.
この例では、これは次のように変換されます。
e.Cancel = true.
FormClosing()イベントとFormClosed()イベントの違いに注意してください。
FormClosingは、フォームが閉じるメッセージを受信したときに発生し、閉じる前に何かする必要があるかどうかを確認します。
FormClosedは、フォームが実際に閉じたときに発生するため、閉じた後に発生します。
これは役に立ちますか?
CloseReason
あなたはMSDNで見つけ列挙は、単にユーザーがアプリを閉じた、またはそれがシャットダウンによるものであったか、など、タスクマネージャによって閉じられているかどうかをチェックするためのものであり...
理由に応じて、次のようなさまざまなアクションを実行できます。
void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if(e.CloseReason == CloseReason.UserClosing)
// Prompt user to save his data
if(e.CloseReason == CloseReason.WindowsShutDown)
// Autosave and clear up ressources
}
しかし、ご想像のとおり、xボタンをクリックするか、タスクバーを右クリックして[閉じる]をクリックするか、を押すAlt F4などの違いはありません。すべて、CloseReason.UserClosing
何らかの理由で終了します。
「X」ボタンDialogResult.Cancel
は別のオプションとして登録されるため、DialogResult
。
フォームに複数のボタンがある場合は、おそらくすでに異なる DialogResult
それぞれにているため、各ボタンの違いを確認する手段が提供されます。
(例:btnSubmit.DialogResult = DialogResult.OK
、btnClose.DialogResult = Dialogresult.Abort
)
public Form1()
{
InitializeComponent();
this.FormClosing += Form1_FormClosing;
}
/// <summary>
/// Override the Close Form event
/// Do something
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
//In case windows is trying to shut down, don't hold the process up
if (e.CloseReason == CloseReason.WindowsShutDown) return;
if (this.DialogResult == DialogResult.Cancel)
{
// Assume that X has been clicked and act accordingly.
// Confirm user wants to close
switch (MessageBox.Show(this, "Are you sure?", "Do you still want ... ?", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
//Stay on this form
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
}
DialogResult
残りNone
ます。何が問題でしょうか?
X
とDialogResult
、Cancel
ではなくが含まれますNone
。None
ボタンへの割り当ては、その.DialogResult
プロパティをまったく設定しないことと同じであり、form.Close()
ボタンのイベントハンドラーから呼び出すと、form.DialogResult
が含まれますCancel
。フォームを閉じるボタン以外の値None
またはCancel
すべてのボタンに値を割り当てるだけで、目的の区別が可能になります。
Close()
か、コードを呼び出すことによってフォームが閉じられたかどうかを検出するにはどうすればよいですか?ユーザーがタイトルバーのXボタンをクリックするか、Alt + F4を使用してフォームを閉じるか、システムメニューを使用してフォームを閉じるか、Close()
メソッドを呼び出すことによってフォームが閉じられるため、フォームを閉じるイベント引数の閉じる理由に依存することはできません。上記の場合、クローズ理由はユーザーによってクローズされますこれは望ましい結果ではありません。
フォームがXボタンまたはClose
メソッドのどちらで閉じられたかを区別するには、次のオプションのいずれかを使用できます。
WM_SYSCOMMAND
と確認SC_CLOSE
フラグ、設定します。StackTrace
て、フレームにClose
メソッド呼び出しが含まれているかどうかを確認してください。例1-ハンドル WM_SYSCOMMAND
public bool ClosedByXButtonOrAltF4 {get; private set;}
private const int SC_CLOSE = 0xF060;
private const int WM_SYSCOMMAND = 0x0112;
protected override void WndProc(ref Message msg)
{
if (msg.Msg == WM_SYSCOMMAND && msg.WParam.ToInt32() == SC_CLOSE)
ClosedByXButtonOrAltF4 = true;
base.WndProc(ref msg);
}
protected override void OnShown(EventArgs e)
{
ClosedByXButtonOrAltF4 = false;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (ClosedByXButtonOrAltF4)
MessageBox.Show("Closed by X or Alt+F4");
else
MessageBox.Show("Closed by calling Close()");
}
例2-StackTraceの確認
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (new StackTrace().GetFrames().Any(x => x.GetMethod().Name == "Close"))
MessageBox.Show("Closed by calling Close()");
else
MessageBox.Show("Closed by X or Alt+F4");
}
私のアプリケーションでは常に、フォームのCloseメソッドを使用しています。このメソッドは、exitボタンからのalt + x、alt + f4、または別のフォームの終了イベントが開始されたことをキャッチします。mstrClsTitle = "grmRexcel"
この場合、すべてのクラスのクラス名はプライベート文字列として定義されています。このメソッドは、フォームのクローズメソッドとフォームのクローズメソッドを呼び出すExitメソッドです。フォームのクローズ方法-についての声明もありthis.FormClosing = My Form Closing Form Closing method name
ます。
このためのコード:
namespace Rexcel_II
{
public partial class frmRexcel : Form
{
private string mstrClsTitle = "frmRexcel";
public frmRexcel()
{
InitializeComponent();
this.FormClosing += frmRexcel_FormClosing;
}
/// <summary>
/// Handles the Button Exit Event executed by the Exit Button Click
/// or Alt + x
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
/// <summary>
/// Handles the Form Closing event
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void frmRexcel_FormClosing(object sender, FormClosingEventArgs e)
{
// ---- If windows is shutting down,
// ---- I don't want to hold up the process
if (e.CloseReason == CloseReason.WindowsShutDown) return;
{
// ---- Ok, Windows is not shutting down so
// ---- either btnExit or Alt + x or Alt + f4 has been clicked or
// ---- another form closing event was intiated
// *) Confirm user wants to close the application
switch (MessageBox.Show(this,
"Are you sure you want to close the Application?",
mstrClsTitle + ".frmRexcel_FormClosing",
MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
// ---- *) if No keep the application alive
//---- *) else close the application
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
}
}
}
次のようなデザインからイベントハンドラーを追加してみてください。デザインビューでフォームを開く、プロパティウィンドウを開く、またはF4キーを押し、イベントツールバーボタンをクリックしてFormオブジェクトのイベントを表示し、[動作]グループでFormClosingイベントを見つけてダブルクリックします。リファレンス:https : //social.msdn.microsoft.com/Forums/vstudio/en-US/9bdee708-db4b-4e46-a99c-99726fa25cfb/how-do-i-add-formclosing-event?forum=csharpgeneral
namespace Test
{
public partial class Member : Form
{
public Member()
{
InitializeComponent();
}
private bool xClicked = true;
private void btnClose_Click(object sender, EventArgs e)
{
xClicked = false;
Close();
}
private void Member_FormClosing(object sender, FormClosingEventArgs e)
{
if (xClicked)
{
// user click the X
}
else
{
// user click the close button
}
}
}
}
私はDialogResult
-Solutionをより単純なものとして同意します。
ただし、VB.NETでは、CloseReason
-Property を取得するには型キャストが必要です。
Private Sub MyForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
Dim eCast As System.Windows.Forms.FormClosingEventArgs
eCast = TryCast(e, System.Windows.Forms.FormClosingEventArgs)
If eCast.CloseReason = Windows.Forms.CloseReason.None Then
MsgBox("Button Pressed")
Else
MsgBox("ALT+F4 or [x] or other reason")
End If
End Sub
また、フォームの「InitializeComponent()」メソッド内にクロージング関数を登録する必要がありました。
private void InitializeComponent() {
// ...
this.FormClosing += FrmMain_FormClosing;
// ...
}
私の "FormClosing"関数は与えられた答え(https://stackoverflow.com/a/2683846/3323790)に似ています:
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e) {
if (e.CloseReason == CloseReason.UserClosing){
MessageBox.Show("Closed by User", "UserClosing");
}
if (e.CloseReason == CloseReason.WindowsShutDown){
MessageBox.Show("Closed by Windows shutdown", "WindowsShutDown");
}
}
もう1つ言及する必要があります。「FormClosing」の後に発生する「FormClosed」関数もあります。この機能を使用するには、以下のように登録してください。
this.FormClosed += MainPage_FormClosed;
private void MainPage_FormClosing(object sender, FormClosingEventArgs e)
{
// your code after the form is closed
}