0

Program.cs で次のコードを使用して、メイン フォームの前に表示されるログイン フォームがあります。

static void Main()
{
    AppDomain.CurrentDomain.UnhandledException += Unhandled;
    frmLogin loginForm;
    using (loginForm = new frmLogin())
    {
        if (loginForm.ShowDialog() == DialogResult.OK)
        {
            NRBQConsts.userName = loginForm.UserName;
            NRBQConsts.pwd = loginForm.Password;
            NRBQConsts.currentSiteNum = loginForm.SiteNumber;
        }
        else
        {
            Application.Exit(); // klang!
        }
    }
    Application.Run(new frmMain());
}

static void Unhandled(object sender, UnhandledExceptionEventArgs exArgs)
{
    ExceptionLoggingService.Instance.WriteLog(String.Format("From 
application-wide exception handler: {0}", exArgs.ExceptionObject));
}

ユーザーが (ログインを試みるのではなく) [閉じる] ボタンを選択すると、ログイン フォームが閉じ、メイン フォームが表示されなくなり、アプリがシャットダウンされます。ユーザーが [OK] ボタンを選択すると、ログイン フォームが閉じ、メイン フォームが表示されます。

「閉じる」ボタンを選択すると、Gong Show 風の「クラッシュ」音でアプリがクラッシュします。ログ ファイルに次の例外メッセージがあります。

日付: 2009 年 4 月 9 日 8:57:51 PM メッセージ: frmLogin.buttonOK_Click に到達しました 日付: 2009 年 4 月 9 日 8:57:51 PM メッセージ: アプリケーション全体の例外ハンドラーから: System.NullReferenceException: NullReferenceException at NRBQ.frmLogin System.Windows.Forms.Button.OnClick(EventArgs e) で System.Windows.Forms.Control.OnClick(EventArgs e) で NRBQ.frmLogin.buttonOK_Click(オブジェクト送信者、EventArgs e) で .GetSiteNum()。 Forms.ButtonBase.WnProc(WM wm, Int32 wParam, Int32 lParam) で System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam) で Microsoft.AGL.Forms.EVL.EnterModalDialog(IntPtr hwnModal) でNRBQ.Program.Main() の System.Windows.Forms.Form.ShowDialog()

ログインフォームの関連コードは次のとおりです。

public partial class frmLogin : Form
{
    public string UserName { get { return textBoxUsername.Text; } }
    public string Password { get { return textBoxPwd.Text; } }
    public string SiteNumber { get { return GetSiteNum(); } }

    private string GetSiteNum()
    {
        String candidateSiteNum = 
    listBoxSitesWithFetchedData.SelectedItem.ToString();
        if (String.IsNullOrEmpty(candidateSiteNum))
        {
            candidateSiteNum = "42"; // TODO: Remove before deploying
        }
        return candidateSiteNum;
    }

    public frmLogin()
    {
        InitializeComponent();
    }

    private void buttonClose_Click(object sender, EventArgs e)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached 
    frmLogin.buttonClose_Click");
    }

    private void buttonOK_Click(object sender, EventArgs e)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached 
    frmLogin.buttonOK_Click");
        if (SanityCheck())
        {
            this.Close(); // closing this login form should make the main 
    form active/visible
        }
        else
        {
            MessageBox.Show("You have not yet provided some key data; be 
    sure to enter a username and a password");
        }
    }

    private bool SanityCheck()
    {
        // For now, anyway, no site has to be selected; if none, use "42" by 
    default
        return ((!(String.IsNullOrEmpty(textBoxUsername.Text.Trim())))
            && (!(String.IsNullOrEmpty(textBoxPwd.Text.Trim()))));
    }

注: 「OK」ボタンの DialogResult は「OK」に設定されています。「閉じる」ボタンの DialogResult は「キャンセル」に設定されています

Application.Exit() によってアプリがクラッシュするのはなぜですか? アプリを終了するためのより親切で穏やかな方法は何ですか?

また、[OK] ボタンを選択すると、その後メイン フォームが表示されないのはなぜですか? [OK] ボタンを選択しても (サニティ チェックに合格した場合)、ログイン フォーム閉じますが、それだけです... メイン フォームは表示されません。

アップデート

以下の回答に基づいてコードを修正したところ、キャンセルが正常に機能するようになりました (klang/crash なしでアプリを閉じます) が、ログイン フォームで [OK] ボタンを選択した後もメイン フォームが表示されません。ログインフォームコードでDialogResultをプログラムでOKに設定していますが。

以下の関連コード。

プログラム.CS

static void Main()
{
    AppDomain.CurrentDomain.UnhandledException += Unhandled;
    frmLogin loginForm;
    using (loginForm = new frmLogin())
    {
        if (loginForm.ShowDialog() == DialogResult.OK)
        {
            HHSConsts.userName = loginForm.UserName;
            HHSConsts.pwd = loginForm.Password;
            HHSConsts.currentSiteNum = loginForm.SiteNumber;
            // TODO: Verify that these vals are valid
            Application.Run(new frmMain());
        }
    }
}

FRMLOGIN.CS

private void buttonClose_Click(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached 
frmLogin.buttonClose_Click");
    this.DialogResult = DialogResult.Cancel; // <= necessary?
    this.Close();
}

private void buttonOK_Click(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached 
frmLogin.buttonOK_Click");
    this.DialogResult = DialogResult.OK; 
    if (SanityCheck())
    {
        this.Close();
    }
    else
    {
        MessageBox.Show("You have not yet provided some key data; be 
sure to enter a username and a password");
    }
}

これは私のログファイルに表示されるものです:

日付: 2009 年 4 月 9 日 9:56:47 PM メッセージ: frmLogin.buttonOK_Click に到達しました 日付: 2009 年 4 月 9 日 9:56:48 PM メッセージ: アプリケーション全体の例外ハンドラーから: System.NullReferenceException: NullReferenceException at HHS.frmLogin .GetSiteNum() HHS.frmLogin.get_SiteNumber() で HHS.Program.Main()

マール・ハガードが歌ったように、「だから今戻ってきた、再びコードルームに...

更新 2

GetSiteNum() にメッセージ ボックスを追加しました。

private string GetSiteNum()
{
    ExceptionLoggingService.Instance.WriteLog("Reached 
frmLogin.GetSiteNum()");
    String candidateSiteNum = 
listBoxSitesWithFetchedData.SelectedItem.ToString();
    // TODO: Remove after testing
    MessageBox.Show(String.Format("candidateSiteNum = {0}", 
candidateSiteNum));
    if (String.IsNullOrEmpty(candidateSiteNum))
    {
        candidateSiteNum = "03"; // TODO: Remove before deploying
    }
    return candidateSiteNum;
}

...そして、私はそれを見ないので、爆発しています:

String candidateSiteNum = listBoxSitesWithFetchedData.SelectedItem.ToString();

...このログイン フォームで [OK] ボタンを選択した直後。

4

3 に答える 3

3

Close()ログインフォームに対して呼び出さないでくださいDialogResult。以下のように設定してください。また、準備が整ったことをDialogResult.OK通知するまで設定しないことに注意してください。 SanityCheck()

    private void buttonClose_Click(object sender, EventArgs e)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached frmLogin.buttonClose_Click");
        this.DialogResult = DialogResult.Cancel; 
    }

    private void buttonOK_Click(object sender, EventArgs e)
    {
        ExceptionLoggingService.Instance.WriteLog("Reached frmLogin.buttonOK_Click");
        if (SanityCheck())
        {
            this.DialogResult = DialogResult.OK; 
        }
    }

SanityCheck()また、関数で ListBox 内の項目が選択されていることを確認する必要があります。

    private bool SanityCheck()
    {
        if (listBoxSitesWithFetchedData.SelectedIndex == -1)
        {
            MessageBox.Show("You must select a site first!");
            return false;
        }

        bool pass = ((!(String.IsNullOrEmpty(textBoxUsername.Text.Trim())))
            && (!(String.IsNullOrEmpty(textBoxPwd.Text.Trim()))));
        if (!pass)
        {
            MessageBox.Show("You have not yet provided some key data; be sure to enter a username and a password");
        }

        return pass;
    }
于 2015-01-20T21:11:30.507 に答える
2

これは、ドキュメントが言うことApplication.Exitです:

すべてのメッセージ ポンプに終了する必要があることを通知し、メッセージが処理された後にすべてのアプリケーション ウィンドウを閉じます。

これは、適切に制御されたシャットダウンを開始し、すぐに終了しないことを意味します。これにより、コードが続行されApplication.Run、明らかにクラッシュして燃焼します。

代わりに使用するオプションが 1 つありますがEnvironment.Exit、これはすぐに終了しますが、面倒な解決策です。別のオプションは のreturn直後にApplication.Exitあるため、 に到達することはありませんApplication.Run。しかし、それでも、あまり良くありません。

代わりに、次のことを試してください。

static void Main()
{
    AppDomain.CurrentDomain.UnhandledException += Unhandled;
    frmLogin loginForm;
    using (loginForm = new frmLogin())
    {
        if (loginForm.ShowDialog() == DialogResult.OK)
        {
            NRBQConsts.userName = loginForm.UserName;
            NRBQConsts.pwd = loginForm.Password;
            NRBQConsts.currentSiteNum = loginForm.SiteNumber;
            Application.Run(new frmMain());
        }
    }
}

から戻るMainとアプリケーションも終了するため、他に何も必要ありません。

編集:どうやらこれはあなたが抱えていた問題ではなかったようですが、とにかく、これはタイトルの質問に答えます.

于 2015-01-20T19:34:00.070 に答える
1

[OK] ボタンにダイアログの結果を設定したことがないようです。

ダイアログの結果を次のように設定します。

this.DialogResult = DialogResult.OK;

this.Close()エラーはNull refffによるものであるため、サニティチェックの後、問題を解決する直前に。

また、フォームが返す他の場所でキャンセルされた結果を設定する必要があります (または、私がよく行うように、フォームの読み込み時に、成功して戻ることがわかるまで失敗を想定します)。

于 2015-01-20T19:34:42.360 に答える