2011-10-28 20 views
14

मुझे आपको पृष्ठभूमि देने दें।संदेशबॉक्स को प्रोग्रामेटिक रूप से बंद करने के लिए बल

हम एक आवेदन (मध्यम आकार के) कि विभिन्न स्थानों पर MessageBox.Show (....) उपयोग कर रहा है (सैकड़ों में) है।

ये संदेश बॉक्स worklfow का हिस्सा हैं और, को सूचित करने की चेतावनी या एक उपयोगकर्ता से इनपुट लेने के लिए इस्तेमाल किया जा रहा। यदि कोई गतिविधि नहीं है तो आवेदन निश्चित समय के बाद स्वचालित रूप से लॉग ऑफ होना चाहिए। हमारे पास एक आवश्यकता है कि एप्लिकेशन को लॉग आउट करते समय, सत्र डेटा को साफ करने के लिए, दृश्यों को साफ़ करने और स्वयं को छिपाने के लिए, ताकि अगले लॉन्च में, स्टार्टअप प्रक्रिया को निष्पादित नहीं करना पड़ेगा जो कि समय के अनुसार महंगा है।

सब कुछ ठीक है, लेकिन एक परिदृश्य में काम कर रहा है जब वहाँ स्क्रीन पर कुछ संदेश बॉक्स है और उपयोगकर्ता कोई गतिविधि के कारण संदेश बॉक्स का जवाब देने और उसके बाद लॉग आउट करने के आवेदन करने के लिए बिना मशीन छोड़ दिया है। समस्या संदेश बॉक्स गायब नहीं होगा।

आवेदन छुपाते समय मैं खोला गया संदेशबॉक्स, यदि कोई हो, तो कैसे बंद कर सकता हूं?

धन्यवाद। एक धारणा है कि आप कोड है कि MessageBox.Show() विधि कॉल कर रहा है संपादित कर सकते हैं के रूप में

+0

यह कॉल हो सकता है कि कुंजी दर्ज करें या esc भेजें? :) – Reniuz

+0

मैंने सोचा कि 'MessageBox.Show (...)' मोडल है, तो प्रोग्राम एक कुंजी कैसे भेज सकता है? क्या आप धागे/कार्यों का उपयोग कर रहे हैं? – Fischermaen

+0

उत्तर के लिए धन्यवाद। अनुकूलित संदेश बॉक्स का उपयोग करके स्पष्ट करने के लिए बस एक विकल्प नहीं है क्योंकि पुनर्विक्रय काफी बड़ा है। ईएससी कुंजी भेजना भी सही नहीं है क्योंकि केवल सक्रिय एप्लिकेशन को कमांड प्राप्त होगा। मैं FINDWindow दृष्टिकोण का उपयोग कर रहा हूं जहां मुझे आईडी और संदेश बॉक्स कैप्शन पास करके Msgbox हैंडल मिल रहा है। हैंडलर प्राप्त करने के बाद मैं निम्नलिखित Win32 API का उपयोग कर बंद कर रहा हूं उदा। SendMessage (नया हैंडलरफ (शून्य, msgbxc हैंडलर), WM_CLOSE, IntPtr.Zero, IntPtr.Zero); SendMessage (नया हैंडलरफ (शून्य, msgbxc हैंडलर), WM_NCDESTROY, IntPtr.Zero, IntPtr.Zero); अभी तक यह ठीक काम कर रहा है। – NYK

उत्तर

1

ले रहा है, मैं MessageBox का उपयोग नहीं की सिफारिश करेंगे। इसके बजाय, संदेश बॉक्स श्रेणी के समान ही मूल रूप से करने के लिए, बस ShowDialog() पर कॉल करके अपने स्वयं के कस्टम फॉर्म का उपयोग करें। फिर, आप में फॉर्म का उदाहरण स्वयं है, और आप Close() पर उदाहरण को बंद करने के लिए कॉल कर सकते हैं।

एक अच्छा उदाहरण here है।

+0

ओच। और जब हम संदेश बॉक्स को पुन: कार्यान्वित करते हैं तो हम कई बार कितना भयानक देखते हैं। 'msg' दिखाता है कि आपके पास एक वास्तविक संदेश बॉक्स हो सकता है और देरी के बाद इसे बंद कर सकता है ... – Joey

+0

@ जॉय: हाँ, आप सही हैं ... यह सिर्फ एक विचार था, शायद सबसे अच्छा नहीं। आप कहते हैं कि _msg दिखाता है कि आपके पास एक वास्तविक संदेश बॉक्स हो सकता है और देरी_ के बाद इसे बंद कर सकता है ... "msg" क्या है या कौन है? क्षमा करें, मुझे समझ में नहीं आ रहा है, मैं पॉइंट 3 के लिए क्षमा चाहता हूं – Marco

3

पहले एक प्रश्न: संदेशों बक्से कार्यप्रवाह के भाग के रूप में इस्तेमाल कर रहे हैं, प्रोग्राम के द्वारा बंद करने नहीं संदेश बॉक्स प्रवाह को बदलने के लिए कारण होगा/जारी रखें?

मुझे लगता है कि आपके पास तीन विकल्प

  1. messagebox वर्ग एक संवाद खिड़की है कि अतिरिक्त कार्यक्षमता के साथ एक messagebox की तरह लग रहा है, तो यह समय की अवधि के बाद अपने आप बंद खुलती के अपने स्वयं के संस्करण बनाने की है।

  2. programtically संदेश बॉक्स बंद करने के लिए सी # में कुछ इस तरह लागू करें। http://www.codeproject.com/KB/dialog/AutoCloseMessageBox.aspx

  3. वर्कफ़्लो को इंटरप्ट करने से संदेश बॉक्स से छुटकारा पाएं। यह शायद सबसे अच्छा समाधान है क्योंकि संदेश बॉक्स को बंद करने की आवाज से प्रोग्रामेटिक रूप से वर्कफ़्लो जारी/बदलना होगा, और संभवतः एक और संदेशबॉक्स भी दिखाना होगा जो वांछित नहीं हो सकता है। लेकिन स्पष्ट रूप से रूट समस्या को ठीक करना सबसे अच्छा हो सकता है, लेकिन हमेशा सबसे आसान नहीं होता है। ताकि आप messagebox अवरुद्ध हो जाएगा दिखा के रूप में है कि के निहितार्थ के बारे में सोचने की जरूरत होगी

1 और 2, एक अलग थ्रेड से किया जा करने की आवश्यकता होगी।

+0

+1। मैं भी, मुझे किसी खुले संदेश बॉक्स को "पुष्टि" करने की अच्छी भावना नहीं होगी, यह जानने के बिना कि उपयोगकर्ता ने इसे देखा है ... – MartinStettner

1

मुझे लगता है कि स्पष्ट तरीका की तरह

class MyMessageBox : Form { 
    private MyMessageBox currentForm; // The currently active message box 

    public static Show(....) { // same as MessageBox.Show 
    // ... 
    } 

    public static Show(...) { // define additional overloads 
    } 

    public static CloseCurrent() { 
    if (currentForm != null) 
     currentForm.Close(); 
    } 

    // ... 
} 

मेरी बड़ी परियोजनाओं में से कुछ में आप खुद संदेश बॉक्स प्रपत्र लागू करने के लिए हो सकता है, मैं अन्य प्रयोजनों (जैसे त्रुटि संदेशों में से स्वत: प्रवेश के रूप में के लिए भी इस दृष्टिकोण उपयोगी पाया इत्यादि)

दूसरा विचार है कि आपके पास आपके आवेदन की वर्तमान शीर्ष-स्तरीय विंडो प्राप्त करने के लिए GetTopWindow() (या शायद कुछ अन्य WIN32 फ़ंक्शन) का उपयोग करना होगा और WM_CLOSE संदेश भेजें।

+0

क्या होगा यदि उपयोगकर्ता वांछित संदेश बॉक्स के ऊपर दिखाए गए Alt टैब या अन्य संदेश बॉक्स को दबाए । उस परिदृश्य में मुझे लगता है कि यह अवांछित बंद कर देगा। – Vivekh

0

इसके लिए अपना स्वयं का नियंत्रण बनाएं और उस व्यवहार को लागू करें जिसे आप वहां रखना चाहते हैं। एक विकल्प के रूप में इस संदेश बॉक्स को बंद करने के लिए एक टाइमर हो सकता है।

2

यहाँ SendKeys के साथ अपने उदाहरण - परीक्षण किया है और काम कर रहे:

की सुविधा देता है कहते हैं कि हम के रूप में BackgroundWorker और बटन होता है। बटन क्लिक करने के बाद - कार्यकर्ता शुरू करें और संदेश बॉक्स दिखाएं। श्रमिकों में DoWork घटना 5s के लिए सोती है और फिर एंटर कुंजी भेजती है - मैसेज बॉक्स बंद हो जाता है।

private void button1_Click(object sender, EventArgs e) 
{ 
    backgroundWorker1.RunWorkerAsync(); 
    MessageBox.Show("Close this message!"); 
} 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Thread.Sleep(5000); 
    SendKeys.SendWait("{Enter}");//or Esc 
} 
+1

मैं बस यह इंगित करना चाहता हूं कि समाधान के लिए यह जांचना बहुत महत्वपूर्ण है कि वास्तव में एक संदेश बॉक्स खुला है या नहीं: उपयोगकर्ता इंटरफ़ेस के किसी भी अन्य भाग में भेजी गई एक प्रविष्टि कुंजी के अनचाहे परिणाम हो सकते हैं ... – MartinStettner

+0

हाँ आपका बिंदु अच्छा है। इसका त्वरित कामकाज इसलिए कुंजी दर्ज करना स्पष्ट रूप से अच्छी कुंजी नहीं है, ईएससी का उपयोग करने के लिए बेहतर - यूआई में इसे रद्द करने का प्रतिनिधित्व करना चाहिए। – Reniuz

+1

यह समाधान केवल तभी काम करता है जब उपयोगकर्ता किसी अन्य ऐप पर फ़ोकस नहीं बदलता है। आप यह सुनिश्चित नहीं कर सकते कि ऐप अभी भी फोकस कर रहा है। और विंडोज ऐप को अन्य ऐप से प्रोग्रामेटिक रूप से फोकस करने से रोकता है। – Alex

6

यह link MSDN मंचों पर पता चलता FindWindow का उपयोग कर और एक WM_CLOSE संदेश भेज कर संदेश बॉक्स को बंद करने के लिए कैसे। हालांकि सवाल .NET/WindowsCE के लिए पूछा गया था, यह आपकी समस्या को हल कर सकता है, इसकी कीमत

+2

मुझे लगता है कि लिंक्ड पेज किसी समस्या को हल कर सकता है (केवल नंगे लिंक पोस्ट करने के बजाय) को कम से कम एक बहुत ही कम जानकारी जोड़ने के लिए अच्छा अभ्यास माना जाता है। मुझे उम्मीद है कि आपको कोई फर्क नहीं पड़ता कि मैंने एक संक्षिप्त विवरण जोड़ा है। वैसे भी +1, यह एक सहायक संसाधन हो सकता है। – MartinStettner

+0

अच्छी तरह से मार्टिन, आप बिल्कुल सही हैं। समय जटिलता के कारण मैं इस जानकारी को जोड़ने में सक्षम नहीं था। हालांकि संपादन के लिए धन्यवाद। :) – Bravo

7

यहां UIAutomation (एक ठंडा लेकिन अभी भी बहुत उपयोग नहीं किया गया एपीआई) के आधार पर कोड का एक टुकड़ा है जो सभी मोडल को बंद करने का प्रयास करता है खिड़कियों मौजूदा प्रक्रिया के (MessageBox के साथ खोला एक सहित):

/// <summary> 
    /// Attempt to close modal windows if there are any. 
    /// </summary> 
    public static void CloseModalWindows() 
    { 
     // get the main window 
     AutomationElement root = AutomationElement.FromHandle(Process.GetCurrentProcess().MainWindowHandle); 
     if (root == null) 
      return; 

     // it should implement the Window pattern 
     object pattern; 
     if (!root.TryGetCurrentPattern(WindowPattern.Pattern, out pattern)) 
      return; 

     WindowPattern window = (WindowPattern)pattern; 
     if (window.Current.WindowInteractionState != WindowInteractionState.ReadyForUserInteraction) 
     { 
      // get sub windows 
      foreach (AutomationElement element in root.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window))) 
      { 
       // hmmm... is it really a window? 
       if (element.TryGetCurrentPattern(WindowPattern.Pattern, out pattern)) 
       { 
        // if it's ready, try to close it 
        WindowPattern childWindow = (WindowPattern)pattern; 
        if (childWindow.Current.WindowInteractionState == WindowInteractionState.ReadyForUserInteraction) 
        { 
         childWindow.Close(); 
        } 
       } 
      } 
     } 
    } 

उदाहरण के लिए, यदि आप एक WinForms अनुप्रयोग है कि एक संदेशबॉक्स पॉप अप होता है जब आप कुछ Button1 दबाते हैं, तो आप अभी भी ऐप्स को बंद करने में सक्षम हो जाएगा विंडोज़ "बंद विंडो" मेनू का उपयोग करके (टास्क बार में राइट क्लिक करें):

private void button1_Click(object sender, EventArgs e) 
    { 
     MessageBox.Show("Don't click me. I want to be closed automatically!"); 
    } 

    protected override void WndProc(ref System.Windows.Forms.Message m) 
    { 
     const int WM_SYSCOMMAND = 0x0112; 
     const int SC_CLOSE = 0xF060; 

     if (m.Msg == WM_SYSCOMMAND) // this is sent even if a modal MessageBox is shown 
     { 
      if ((int)m.WParam == SC_CLOSE) 
      { 
       CloseModalWindows(); 
       Close(); 
      } 
     } 
     base.WndProc(ref m); 
    } 

आप अपने कोड में कहीं और CloseModalWindows का उपयोग कर सकते हैं, यह सिर्फ एक नमूना है।

+0

WPF के लिए UIAutomation नहीं है? सवाल WinForms –

+0

@ErikFunkenbusch के लिए था - यह नहीं पता कि "WPF के लिए" का क्या अर्थ है। UIAutomation किसी भी प्रकार के आवेदन का समर्थन करता है। –

+0

System.Windows.Automation नेमस्पेस का कहना है कि यह WPF के लिए है। http://msdn.microsoft.com/en-us/library/ms747327(v=vs.110).aspx "माइक्रोसॉफ्ट यूआई ऑटोमेशन माइक्रोसॉफ्ट विंडोज के लिए नया एक्सेसिबिलिटी फ्रेमवर्क है, जो विंडोज प्रेजेंटेशन फाउंडेशन का समर्थन करने वाले सभी ऑपरेटिंग सिस्टम पर उपलब्ध है (WPF)। " –

1

मैंने उसी चाल के साथ .NET 2 और दो दृष्टिकोणों का उपयोग किया।

ओपन MessageBox.Show(this,"message")

साथ ठूंठ-फार्म से MessageBox जब प्रपत्र दिखाई नहीं देता है या वास्तव में यूआई है नहीं करता है।

  1. प्रपत्र हैंडलर रखें और साथ इसे बंद:

    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); 
    

    या

  2. वर्ग पैरामीटर के रूप में रूप धारण और FormX.Close() का उपयोग कर।

चूंकि फॉर्म संदेशबॉक्स का मालिक है, बंद होने से यह संदेशबॉक्स बंद हो जाएगा।

1

using System.Runtime.InteropServices; 
using System.Threading; 
using System.Windows.Forms; 

    public class AutoClosingMessageBox 
    { 
     System.Threading.Timer _timeoutTimer; 
     string _caption; 
     AutoClosingMessageBox(string text, string caption, int timeout) 
     { 
      _caption = caption; 
      _timeoutTimer = new System.Threading.Timer(OnTimerElapsed, 
       null, timeout, System.Threading.Timeout.Infinite); 
      MessageBox.Show(text, caption); 
     } 
     public static void Show(string text, string caption, int timeout) 
     { 
      new AutoClosingMessageBox(text, caption, timeout); 
     } 
     void OnTimerElapsed(object state) 
     { 
      IntPtr mbWnd = FindWindow(null, _caption); 
      if (mbWnd != IntPtr.Zero) 
       SendMessage(mbWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); 
      _timeoutTimer.Dispose(); 
     } 
     const int WM_CLOSE = 0x0010; 
     [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
     static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 
     [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)] 
     static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); 
    } 

तक पहुँचने के समय समाप्ति के बाद DmitryG post in "Close a MessageBox after several seconds"

स्वत: बंद संदेशबॉक्स के संदर्भ लें और के माध्यम से

AutoClosingMessageBox.Show("Content", "Title", TimeOut); 
संबंधित मुद्दे