2012-12-27 15 views
13

के साथ अजीब बग हमने हाल ही में वीएस 2012 में अपग्रेड किया है जिसके साथ .NET Framework 4.5 में अपग्रेड किया गया है। यह WinForms मेनूस्ट्रिप नियंत्रण के संबंध में एक अजीब और अजीब बग पेश करता है। 4.5 वें इंस्टॉलर के रूप में .NET Framework 4.0 को लक्षित करने वाले अनुप्रयोगों में वही बग भी होता है जो स्पष्ट रूप से 4.0 के हिस्सों को भी अपडेट करता है। इसलिए, फ्रेमवर्क अपग्रेड के कारण अब पूरी तरह से काम कर रहे कोड पैटर्न को तोड़ दिया गया है।.NET 4.0/4.5 WinForms मेनूस्ट्रिप स्टीलिंग फोकस

समस्या का वर्णन:
मैं एक MenuStrip के साथ एक Form1 है। ड्रॉप डाउन आइटमों में से एक के लिए, ईवेंट हैंडलर एक और फॉर्म 2 खोलता है (असफल रूप से एक बच्चा नहीं, सिर्फ एक और फॉर्म)। यदि उपयोगकर्ता नए फॉर्म 2 या उसके बाल नियंत्रण में से एक में राइट-क्लिक करता है और यह ContextMenuStrip का एक शो() ट्रिगर करता है, तो मूल फॉर्म 1 फिर से अग्रभूमि में पॉप हो जाता है।
यह फॉर्म 2 में पिछले सभी यूआई कार्यों से स्वतंत्र होता है। कोई भी आकार बदल सकता है, स्थानांतरित कर सकता है, छोटा कर सकता है, फॉर्म 2 को अधिकतम कर सकता है, नियंत्रणों के बीच स्विच कर सकता है, टेक्स्ट दर्ज कर सकता है। किसी भी तरह फॉर्म 1 के मेनूस्ट्रिप को याद रखना प्रतीत होता है कि यह फॉर्म 2 खोलने और पहले राइट-क्लिक पर फ्रेस फोकस करने का कारण बनता है।

मैं विभिन्न दृष्टिकोणों के साथ प्रयोग कर रहा था लेकिन अब तक कोई कामकाज नहीं ढूंढ पाया। नक्षत्र असामान्य नहीं है और आसपास के WinForms अनुप्रयोगों को प्रभावित कर सकता है। इसलिए मैंने इसे यहां पोस्ट करने का फैसला किया क्योंकि व्यवहार्य समाधान सामान्य रुचि का हो सकता है। अगर कोई कामकाज जानता है या कम से कम मेरे लिए कुछ सुराग है तो मुझे बहुत खुशी होगी।

मैं निम्नलिखित कोड में इसका सार वितरित करने में सक्षम था। इसे .NET 4.5 के साथ किसी भी मशीन पर पुन: उत्पन्न किया जाना चाहिए और यह 4.0 और 4.5 प्रत्येक को लक्षित करते समय होता है - लेकिन 3.5 या उससे कम नहीं।

using System; 
using System.Windows.Forms; 

namespace RightClickProblem { 
    static class Program { 
     [STAThread] 
     static void Main() { 
      // Construct a MenuStrip with one item "Menu" with one dropdown-item "Popup" 
      var mainMenu = new MenuStrip(); 
      var mainItem = new ToolStripMenuItem("Menu"); 
      mainItem.DropDownItems.Add(new ToolStripMenuItem("Popup", null, Popup)); 
      mainMenu.Items.Add(mainItem); 

      // Create form with MenuStrip and Show 
      var form1 = new Form(); 
      form1.Controls.Add(mainMenu); 
      Application.Run(form1); 
     } 

     private static void Popup(object sender, EventArgs e) { 
      // Create a form with a right click handler and show 
      var form2 = new Form(); 
      var contextMenu = new ContextMenuStrip(); 
      contextMenu.Items.Add("Just an item..."); 
      form2.ContextMenuStrip = contextMenu; 
      form2.Show(); 
      // Problem: contextMenu.Show() will give focus to form1 
     } 
    } 
} 

संपादित करें: मैं कुछ समय बिताया .नेट फ्रेमवर्क स्रोत कोड के माध्यम से कदम और मूल कारण पाया System.Windows.Forms.ToolStripManager में बहुत संभव है किया जाना है। वहां, माइक्रोसॉफ्ट विंडो सक्रियण को ट्रैक करने के लिए एक संदेश फ़िल्टर का उपयोग कर रहा है जिसे मेनूस्ट्रिप के लिए गलत तरीके से कार्यान्वित किया गया है।
इसी दौरान मैंने यह भी पाया कि माइक्रोसॉफ्ट ने पहले से ही इस समस्या को हॉटफिक्स में संबोधित किया है (http://support.microsoft.com/kb/2769674 देखें) और उम्मीद है कि यह .NET Framework 4.5 के भविष्य के अपडेट में अपना रास्ता खोजेगा।

दुर्भाग्य से सभी क्लाइंट मशीनों पर इस हॉटफिक्स को लागू करना मुश्किल है। इसलिए एक व्यावहारिक कामकाज अभी भी बहुत सराहना की जाएगी। मैं अपने आप को अब तक असमर्थ एक व्यावहारिक समाधान खोजने के लिए किया गया है ...

संपादित करें # 2: मूल KB संख्या Win8 के लिए है, लेकिन KB 2756203. तहत Win7 & Vista के लिए समान Hotfix किसी के लिए इसका इस्तेमाल कर सकते हैं है , यहां डाउनलोड करने के लिए हॉटफिक्स मिला: http://thehotfixshare.net/board/index.php?autocom=downloads&showfile=15569। हमने इसका परीक्षण किया और यह वास्तव में समस्या को हल करता है। अगर हमें जल्द ही कोई कामकाज नहीं मिल रहा है, तो हम हॉटफिक्स के साथ जाएंगे।

संपादित # 3: spajce
जाहिर शो को फोन करके प्रस्तावित स्वीकार किए जाते हैं समाधान के लिए टिप्पणियां() पर किसी भी ContextMenu फोकस पर अपना दावा के बारे में भूल करने के लिए मूल MenuStrip को समझाने होगा। यह एक तरह से किया जा सकता है ताकि डमी ContextMenu स्क्रीन पर भी नहीं दिखाया जा सकता है।

public partial class Form1 : Form { 
    public Form1() { 
     InitializeComponent(); 

     using (var dummyMenu = new ContextMenuStrip()) { 
      dummyMenu.Items.Add(new ToolStripMenuItem()); 
      dummyMenu.Show(Point.Empty); 
     } 
    } 
} 

इसलिए हर फार्म खुलती ToolStripMenu प्रणाली के भ्रष्ट राज्य को साफ: मैं सबसे छोटी और ज्यादा लागू करने के लिए आसान तरीका किसी भी फार्म के निर्माता में निम्न स्निपेट डाल पाया। कोई भी इस कोड को फॉर्महेल्पर जैसी स्थैतिक विधि में रख सकता है।FixToolStripState() या इसे टेम्पलेट के ऑनक्रेट कंट्रोल (...) में डाल दें और उस से सभी फॉर्मों का वारिस करें (वैसे भी हम क्या सौभाग्य से करते हैं)।

+3

बहुत अच्छा repro। मुझे गंभीरता से संदेह है कि आपको एक जवाब मिलेगा, टूलस्ट्रिप कक्षाएं एक प्रमुख दर्द हैं। मैं इसे माइक्रोसॉफ्ट सपोर्ट में ले जाऊंगा। –

+0

हॉटफिक्स विवरण को देखते हुए, यह बिल्कुल विपरीत समस्या है। यह संदेश फ़िल्टर को पर्याप्त तेज़ी से नहीं हटाता है। समस्या देखने के लिए बस फॉर्म पर बायाँ-क्लिक करें। टूलस्ट्रिप मैनेजर में कोड है जो फ़िल्टर को हटाने के लिए माना जाता है जब दूसरी विंडो सक्रिय होती है, ऐसा नहीं हो रहा है। उम्मीद है कि यह हॉटफिक्स इसे जल्द ही एक अद्यतन में लाता है, यह एक बहुत ही सकल बग है। –

+0

मूल कारणों से निपटना मुश्किल है क्योंकि विभिन्न योगदान भागों को स्रोत कोड में बहुत वितरित किया जाता है। चूंकि मैंने फ्रेमवर्क कोड को ठीक करने का कोई तरीका नहीं देखा है, इसलिए मैंने कुछ बिंदु पर रुक दिया। मुझे आश्चर्य हुआ कि अंतर्निहित कार्यान्वयन गंदा है (मेरी राय में) लेकिन मुझे आश्चर्य नहीं है कि यह कोड ऐसी बगों के लिए बहुत प्रवण है। – markus987

उत्तर

1

यह मेरा समाधान :)

static class Program 
    { 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     static void Main() 
     { 
      // Construct a MenuStrip with one item "Menu" with one dropdown-item "Popup" 
      var mainMenu = new MenuStrip(); 
      var mainItem = new ToolStripMenuItem("Menu"); 
      mainItem.DropDownItems.Add(new ToolStripMenuItem("Popup", null, Popup)); 
      mainMenu.Items.Add(mainItem); 

      // Create form with MenuStrip and Show 
      var form1 = new Form(); 
      form1.Controls.Add(mainMenu); 
      Application.Run(form1); 
     } 

     private static void Popup(object sender, EventArgs e) 
     { 
      // Create a form with a right click handler and show 
      var form2 = new Form(); 
      var contextMenu = new ContextMenuStrip(); 
      contextMenu.Items.Add("Just an item..."); 
      var loc = form2.Location; //<---- get the location 
      var p2 = new Point(loc.X, loc.Y); //<---- get the point of form 
      form2.ContextMenuStrip = contextMenu; 
      form2.ContextMenuStrip.Show(form2, p2); //<---- just add this code. 
      form2.Show(); 
      // Problem: contextMenu.Show() will give focus to form1 
     } 
    } 
+0

आश्चर्यजनक रूप से पर्याप्त, यह वास्तव में चाल करता है! मैंने इसे अधिक सामान्यता देने के लिए ऊपर अपना प्रश्न अपडेट किया है (हमें अपना जवाब सीधे संपादित करना चाहिए?)। सिर्फ एक मामूली टिप्पणी: चूंकि प्वाइंट एक संरचना है, वैसे भी इसकी प्रतिलिपि बनाई गई है इसलिए स्थानीय/पी 2 की कोई आवश्यकता नहीं है। – markus987

+0

मैं स्वीकार करता हूं कि मैं केवल एक नौसिखिया हूं, इसलिए मैंने जो चाल दी है, वह सिर्फ कुछ सुझाव है जो हमने पाया है कि कुछ मामूली बग को हल करने के लिए मेरा सुझाव है, इसलिए मेरा मुद्दा प्रोग्रामिंग में है, समस्या को हल करने और गंदी को हल करने के लिए हमेशा साफ कोड होते हैं रास्ता हमारा आखिरी हथियार है 'मैंने आपका अद्यतन प्रश्न पढ़ा है और यह बढ़िया है, यह बेहतर तरीका हो सकता है :) – spajce

+0

ईमानदार होने के लिए, मुझे पहले स्थान पर विश्वास नहीं था कि आपका समाधान प्रभावी होगा। मैंने शो() के अतिरिक्त कॉल के साथ प्रयोग किया और पाया कि कॉलिंग() लगातार दो बार समस्या को हल करता है लेकिन मुझे नहीं पता कि यह कैसे व्यावहारिक हो सकता है, इस पर विचार करते हुए कि हमारे पास सैकड़ों मेनू के साथ एक बड़ा कोडबेस है और संदर्भमेन। आपके प्रस्तावित समाधान ने मुझे सही दिशा दी। – markus987

0

मैं इस समस्या को भी हो रही थी है। मैं कोड बदलना नहीं चाहता था, क्योंकि मुझे लगा कि मेरा कार्यक्रम सही कर रहा था। मैं माइक्रोसॉफ्ट के वेबसाइट पर यहाँ ठीक पाया:

http://support.microsoft.com/kb/2750147

यह एक फर्क पड़ता है और हम बस आज सुबह 2 उपयोगकर्ता कंप्यूटर पर स्थापित। हमारा आईटी लड़का आज सभी कंप्यूटरों पर इसे स्थापित कर रहा है कि इसका परीक्षण किया गया है और काम पर दिखाया गया है।