कैसे पता करें कि उपयोगकर्ता ने "X" या "क्लोज़" बटन पर क्लिक किया है?


94

MSDN में मुझे CloseReason.UserClosingपता चला कि उपयोगकर्ता ने फॉर्म को बंद करने का फैसला किया था, लेकिन मुझे लगता है कि यह एक्स बटन पर क्लिक करने या क्लोज बटन पर क्लिक करने के लिए दोनों के लिए समान है। तो मैं अपने कोड में इन दोनों के बीच अंतर कैसे कर सकता हूं?

सबको शुक्रीया।


2
कौन से नज़दीकी बटन का मतलब है?
ब्रायन आर बॉडी

उदाहरण के लिए "ALT + F4" द्वारा बंद करना
Bohn


@ ओलिवर एक ही सवाल नहीं है।
Ctrl S

जवाबों:


95

आप WinForms के लिए पूछ रहे हैं, मान लें कि आप FormClosing () घटना का उपयोग कर सकते हैं । फॉर्म को बंद करने के लिए फॉर्म क्लोजिंग () किसी भी समय चालू हो जाता है।

यह पता लगाने के लिए कि उपयोगकर्ता ने X या आपके 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.
}

अन्यथा, मुझे कभी यह अंतर करने की आवश्यकता नहीं है कि क्या X या CloseButton को क्लिक किया गया था, क्योंकि मैं MDClontainerForm को बंद करने से पहले सभी MdiChildren को बंद करने, या बिना सहेजे गए परिवर्तनों की जाँच करने के लिए, FormClosing इवेंट पर कुछ विशिष्ट प्रदर्शन करना चाहता था। इन परिस्थितियों में, मुझे, मेरे अनुसार, दोनों बटन से अंतर करने की आवश्यकता नहीं है।

ALT+ F4से बंद होने से FormClosing () ईवेंट को भी ट्रिगर किया जाएगा, क्योंकि यह फॉर्म को एक संदेश भेजता है जो बंद करने के लिए कहता है। आप ईवेंट को सेट करके रद्द कर सकते हैं

FormClosingEventArgs.Cancel = true. 

हमारे उदाहरण में, यह अनुवाद होगा

e.Cancel = true.

FormClosing () और FormClosed () घटनाओं के बीच अंतर को नोटिस करें ।

फॉर्म क्लोजिंग तब होती है जब फॉर्म को बंद होने का संदेश प्राप्त होता है, और सत्यापित करें कि क्या बंद होने से पहले उसके पास कुछ करना है।

फॉर्म क्लोज्ड तब होता है जब फॉर्म वास्तव में बंद होता है, इसलिए इसे बंद करने के बाद।

क्या यह मदद करता है?


हां, "कास्ट" विचार के लिए धन्यवाद, डेल्फी 7 के साथ इस तकनीक का इस्तेमाल किया था, लेकिन C44 में वही करना भूल गया
Bohn

यह वास्तव में डेल्फी से .NET का पोर्ट है। =) मुझे खुशी है कि मैंने मदद की!
विल मार्कॉइलर

1
जब मैं इस कोड का उपयोग करता हूं तो मुझे 'ऑब्जेक्ट संदर्भ किसी ऑब्जेक्ट के उदाहरण पर सेट नहीं होता' मिलता है।
नैट एस।

33
ये गलत है। आप प्रेषक को बटन पर नहीं डाल सकते क्योंकि यह स्वयं प्रपत्र है। यह अपवाद फेंकता है।
Xtro

1
कृपया ध्यान दें कि यह एक जवाब है। कृपया इसे अपवित्र न करें।
नजीब

78

CloseReasonMSDN पर आपको मिलने वाली गणना केवल यह जांचने के उद्देश्य से है कि उपयोगकर्ता ने ऐप को बंद किया है, या यह किसी शटडाउन के कारण है, या कार्य प्रबंधक, आदि द्वारा बंद किया गया है ...

आप अलग-अलग कार्य कर सकते हैं, कारण के अनुसार, जैसे:

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
}

लेकिन जैसे आपने अनुमान लगाया, एक्स बटन पर क्लिक करने, या टास्कबार को राइट-क्लिक करने और 'पास', या दबाने Alt F4आदि के बीच कोई अंतर नहीं है , यह सब एक CloseReason.UserClosingकारण में समाप्त होता है।


11
मानक बंद का उपयोग करना (); मेरे लिए CloseReason.UserClosing ट्रिगर करने के लिए लगता है। यकीन नहीं है कि क्यों।
दान डब्ल्यू

मुझे यह उपयोगी तब लगा जब प्रपत्र पर उपयोगकर्ता कार्रवाई द्वारा एमडीआई बच्चे के फॉर्म को बंद करने की कोशिश कर रहा था, लेकिन तब नहीं जब माता-पिता बंद हो रहे हों।
स्टीव पेटीफ़र

1
यह सवाल का जवाब नहीं देता है, केवल इस मुद्दे को आगे बढ़ाता है।
राबर्ट कॉर्नके

आप घटना को विधि से कैसे बांधेंगे?
user2924019

43

"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;
            }
        }
    }

1
मेरे मामले में यह स्वीकृत उत्तर की तुलना में अधिक उपयोगी है। चूंकि 'X' को DialogResult.Cancel सौंपा गया है, इसलिए रद्द बटन को कुछ अन्य मान देकर आसानी से उन्हें अलग करना और उचित तरीके से चीजों को संभालना है।
मिकीफैगैन_बाहरExitOfSO

3
यह मेरे मामले में काम नहीं करता है। जब 'X' दबाते हैं, तो DialogResultरहता है None। क्या समस्या हो सकती है?
भास्कर

1
@ भास्कर, जब आप अपने डायलॉग को इंस्टाल करते हैं, तो अपने डायलॉग के प्रत्येक बटन पर उपयुक्त DialogResult सेट करना सुनिश्चित करें। मैंने ऊपर एक उदाहरण प्रदान किया था, लेकिन डायलॉग घोषणा दिखाने के लिए एक कोड ब्लॉक नहीं बनाया था।
एलेक्सप्रेस

@Bhaskar: दबाने Xबनाता है DialogResultशामिल Cancel, नहीं NoneNoneआपके बटन को असाइन करना उसी तरह है जैसे इसकी .DialogResultप्रॉपर्टी को सेट नहीं करना , और यदि आप form.Close()अपने बटन के ईवेंट हैंडलर से कॉल करते हैं, form.DialogResultतो इसमें शामिल होगा Cancel। केवल Noneया Cancelआपके सभी फॉर्म-क्लोजिंग बटन के अलावा एक मान असाइन करना आपको वांछित अंतर बनाने की अनुमति देगा।
mklement0

9

एक्स बटन पर क्लिक करके या Close()कोड में कॉल करके फॉर्म का पता कैसे लगाया जाए ?

आप फॉर्म क्लोजिंग ईवेंट आर्ग के करीबी कारण पर भरोसा नहीं कर सकते हैं, क्योंकि यदि उपयोगकर्ता टाइटल बार पर एक्स बटन पर क्लिक करता है या फॉर्म को बंद करने के लिए Alt + F4 का उपयोग करके फॉर्म को बंद करता है या सिस्टम मेनू का उपयोग करता है, या कॉलिंग Close()विधि द्वारा बंद हो जाता है , सभी उपरोक्त मामलों में, नज़दीकी कारण उपयोगकर्ता द्वारा बंद किया जाएगा जो वांछित परिणाम नहीं है।

यह पहचानने के लिए कि क्या फॉर्म एक्स बटन या 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 - स्टैकट्रेस की जाँच

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");
}

1
अच्छी तरह से किया। आप पार्टी के लिए बहुत बुरे थे - पुराने से मुकाबला करने के लिए कड़ी मेहनत, पहले से ही अत्यधिक मतदान के जवाब।
mklement0

1
@ mklement0 मुझे आशा है कि भविष्य के उपयोगकर्ता इसे उपयोगी पाएंगे। मैंने उत्तर पोस्ट किया क्योंकि गैर जवाब में से कोई भी समस्या को सही ढंग से हल कर सकता है और यह एक सवाल है कि इस संख्या के विचारों और अत्यधिक मतदान (गैर-काम करने वाले) उत्तरों के लिए यह बहुत अजीब है!
रेजा अघाई

6

यह निर्धारित करता है कि यदि कोई फ़ॉर्म बंद है (यदि आपका आवेदन किसी विशिष्ट फ़ॉर्म से संलग्न नहीं है) तो आवेदन को बंद करना है।

    private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
    {
        if (Application.OpenForms.Count == 0) Application.Exit();
    }

5

मैं हमेशा अपने अनुप्रयोगों में एक फॉर्म क्लोज विधि का उपयोग करता हूं जो मेरे एग्जिट बटन से alt + x पकड़ता है, alt + f4 या किसी अन्य फॉर्म क्लोजिंग इवेंट को शुरू किया गया था। मेरी सभी कक्षाओं mstrClsTitle = "grmRexcel"में इस मामले में निजी नाम के रूप में परिभाषित कक्षा का नाम है , एक निकास विधि जो फॉर्म क्लोजिंग विधि और एक फॉर्म क्लोजिंग विधि कहती है। - मैं भी फार्म समापन विधि के लिए एक बयान है 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;
                }
            }
        }
    }
}

2

आप इस तरह से डिजाइन से इवेंट हैंडलर जोड़ने की कोशिश कर सकते हैं: फॉर्म व्यू में ओपन फॉर्म, प्रॉपर्टीज विंडो खोलें या F4 दबाएं, फॉर्म ऑब्जेक्ट पर इवेंट देखने के लिए इवेंट टूलबार बटन पर क्लिक करें, बिहेवियर ग्रुप में फॉर्म क्लोजिंग इवेंट ढूंढें, और इसे डबल क्लिक करें। संदर्भ: https://social.msdn.microsoft.com/Forums/vstudio/en-US/9bdee708-db4b-4e46-a99c-99726fa25cfb/how-do-adad-formclosing-event?forum=csharpgeneral


1
if (this.DialogResult == DialogResult.Cancel)
        {

        }
        else
        {
            switch (e.CloseReason)
            {
                case CloseReason.UserClosing:
                    e.Cancel = true;
                    break;
            }
        }

यदि उपयोगकर्ता प्रपत्र पर 'X' या क्लोज़ बटन पर क्लिक करता है तो स्थिति निष्पादित होगी। उपयोगकर्ता द्वारा किसी अन्य उद्देश्य के लिए Alt + f4 पर क्लिक करने पर इसका उपयोग किया जा सकता है


1
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
            }
        }
    }
}

1

मैं सहमत हूँ 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

0

मुझे फॉर्म के "InitializeComponent ()" विधि के अंदर समापन समारोह को पंजीकृत करना था:

private void InitializeComponent() {
// ...
this.FormClosing += FrmMain_FormClosing;
// ...
}

मेरा "फ़ॉर्म क्लोज़िंग" फ़ंक्शन दिए गए उत्तर ( https://stackoverflow.com/a/2683846/332890 ) के समान दिखता है :

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");
    }
}

उल्लेख करने के लिए एक और बात: एक "FormClosed" फ़ंक्शन भी है जो "FormClosing" के बाद होता है। इस फ़ंक्शन का उपयोग करने के लिए, इसे नीचे दिखाए अनुसार पंजीकृत करें:

this.FormClosed += MainPage_FormClosed;

private void MainPage_FormClosing(object sender, FormClosingEventArgs e)
{
// your code after the form is closed
}

0

मैंने कुछ ऐसा किया है।

private void Form_FormClosing(object sender, FormClosingEventArgs e)
    {
        if ((sender as Form).ActiveControl is Button)
        {
            //CloseButton
        }
        else
        {
            //The X has been clicked
        }
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.