2012-09-19 7 views
7

एक Winform फीका करने के लिए कोड की खोज करते समय, मैं MSDN मंच पर इस page पर आया।बेहतर एल्गोरिदम एक Winform

for (double i = 0; i < 1; i+=0.01) 
{ 
    this.Opacity = i; 
    Application.DoEvents(); 
    System.Threading.Thread.Sleep(0); 
} 

for पाश एक गैर पूर्णांक वेतन वृद्धि होती है और जो पिछले एक सवाल मैंने पूछा से, कि नहीं एक अच्छा प्रोग्रामिंग तकनीक (सबसे दशमलव की अयथार्थ प्रतिनिधित्व के कारण) है।

मैं इस विकल्प के साथ आया था।

for (double i = 0; i < 100; ++i) 
{ 
    this.Opacity = i/100; 
    Application.DoEvents(); 
    System.Threading.Thread.Sleep(0); 
} 

इनमें से कौन सा अधिक कुशल है?

यदि किसी फॉर्म को लुप्त करने के लिए बेहतर एल्गोरिदम है, तो इसमें शामिल होने पर मुझे बहुत खुशी होगी।

धन्यवाद। चल बिन्दु डिवीजनों की संख्या के रूप में अधिक मशीन महंगा चल बिन्दु जोड़ (VM-झंडे को प्रभावित नहीं करते हैं) की तुलना कर रहे हैं

+0

@DarrenDavies 'स्लीप (0)' नियोजक को धागा के शेष समय वापस जाने के लिए अन्य धागा चलाने के लिए एक मौका देने के लिए किया गया था: आप यहाँ एक बार देख ले सकते हैं। शायद .NET पर यह वही है। [एमएसडीएन राज्य] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298 (v = vs.85) .aspx): "_ अगर आप 0 मिलीसेकंड निर्दिष्ट करते हैं, तो थ्रेड शेष को छोड़ देगा इसके समय का टुकड़ा लेकिन तैयार रहें ._ " –

+0

'int' को' double' में बदलने के बारे में कैसे? –

+0

एक vb.net सिंगल सी # में "फ्लोट" है, int नहीं। –

उत्तर

3
for (double i = 0; i < 1; i+=0.01) 
{ 
    this.Opacity = i; 
    Application.DoEvents(); 
    System.Threading.Thread.Sleep(0); 
} 

अधिक सक्षम है। उस ने कहा, आप 1/2 तक पुनरावृत्तियों की संख्या को कम कर सकते हैं (जो i + = 0.02 में परिवर्तन चरण है)। 1% अस्पष्टता में कमी मानव मस्तिष्क द्वारा ध्यान देने योग्य नहीं है और यह भी कम महंगी होगी, इसे लगभग 100% अधिक तेज कर देगा।

संपादित करें:

for(int i = 0; i < 50; i++){ 
    this.Opacity = i * 0.02; 
    Application.DoEvents(); 
    System.Threading.Thread.Sleep(0); 
} 
0

अतीत में, मैं AnimateWindow का उपयोग किया है एक उत्पन्न फार्म का है कि SystemColor.WindowColor में अपने पूरे आवेदन से अधिक कारतूस बाहर में/फीका करने के लिए।

यह साफ छोटी चाल इंटरफ़ेस जैसे विज़ार्ड में छिपाने/स्वैपिंग/स्क्रीन दिखाने का प्रभाव देती है। मैंने थोड़ी देर के लिए इस तरह की चीज नहीं की है, लेकिन मैंने वीबी में पी/इनवॉक का इस्तेमाल किया और एपीआई को अपने धागे में चलाया।

मुझे पता है कि आपका प्रश्न सी # में है, लेकिन यह लगभग समान है। यहां कुछ प्यारा वीबी है जिसे मैंने खोला है और 2006 से नहीं देखा है! जाहिर है, इसे अपने स्वयं के रूप में और बाहर फीका करने के लिए इसे अनुकूलित करना आसान होगा।

<DllImport("user32.dll")> _ 
Public Shared Function AnimateWindow(ByVal hwnd As IntPtr, ByVal dwTime As Integer, ByVal dwFlags As AnimateStyles) As Boolean 
End Function 

Public Enum AnimateStyles As Integer 
    Slide = 262144 
    Activate = 131072 
    Blend = 524288 
    Hide = 65536 
    Center = 16 
    HOR_Positive = 1 
    HOR_Negative = 2 
    VER_Positive = 4 
    VER_Negative = 8 
End Enum 

Private m_CoverUp As Form 

Private Sub StartFade() 
    m_CoverUp = New Form() 
    With m_CoverUp 
     .Location = Me.PointToScreen(Me.pnlMain.Location) 
     .Size = Me.pnlMain.Size 
     .FormBorderStyle = System.Windows.Forms.FormBorderStyle.None 
     .BackColor = Drawing.SystemColors.Control 
     .Visible = False 
     .ShowInTaskbar = False 
     .StartPosition = System.Windows.Forms.FormStartPosition.Manual 
    End With 
    AnimateWindow(m_CoverUp.Handle, 100, AnimateStyles.Blend) 'Blocks 
    Invoke(New MethodInvoker(AddressOf ShowPage)) 
End Sub 

Private Sub EndFade() 
    AnimateWindow(m_CoverUp.Handle, 100, AnimateStyles.Blend Or AnimateStyles.Hide) 
    m_CoverUp.Close() 
    m_CoverUp = Nothing 
End Sub 
+0

यह विजुअल बेसिक है। – carefulnow1

+0

प्रश्न सी # –

12

तो, सबसे पहले, application.DoEvents should be avoided जब तक आप वास्तव में पता है कि तुम क्या कर रहे हैं और यह सुनिश्चित करें कि यह दोनों इसके बारे में एक उचित इस्तेमाल होता है, और आप इसे सही ढंग से उपयोग कर रहे हैं कि। मैं काफी हद तक निश्चित हूं कि यहां कोई मामला नहीं है।

अगला, आप लुप्तप्राय की गति को कैसे नियंत्रित कर रहे हैं? आप मूल रूप से कंप्यूटर को उतनी जल्दी फीका कर सकते हैं जितना जल्दी हो सकता है और संचालन (और पृष्ठभूमि प्रक्रियाओं) के अंतर्निहित ओवरहेड पर निर्भर करता है ताकि इसे अधिक समय लगे। यह वास्तव में बहुत अच्छा डिजाइन नहीं है। आप यह निर्धारित करने से बेहतर हैं कि शुरुआत से फीका कब तक लेना चाहिए ताकि यह मशीनों के बीच सुसंगत रहे। उचित सेट अंतराल पर कोड निष्पादित करने के लिए आप Timer का उपयोग कर सकते हैं और यह सुनिश्चित कर सकते हैं कि यूआई थ्रेड फीका की अवधि के लिए अवरुद्ध नहीं है (DoEvents का उपयोग किए बिना)।

बस duration को फेड लेता है, यह बदलने के लिए नीचे steps संशोधित करने के लिए duration संशोधित करें और यह निर्धारित करने के लिए कि "चटनी" कैसे है। मैंने इसे 100 पर सेट किया है क्योंकि यह प्रभावी ढंग से आपका कोड क्या कर रहा था। हकीकत में, आपको शायद उन लोगों की आवश्यकता नहीं है और आप चपटे होने लगने से ठीक पहले ही कम कर सकते हैं। (जितना बेहतर होगा उतना ही बेहतर होगा।)

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

private void button1_Click(object sender, EventArgs e) 
{ 
    int duration = 1000;//in milliseconds 
    int steps = 100; 
    Timer timer = new Timer(); 
    timer.Interval = duration/steps; 

    int currentStep = 0; 
    timer.Tick += (arg1, arg2) => 
    { 
     Opacity = ((double)currentStep)/steps; 
     currentStep++; 

     if (currentStep >= steps) 
     { 
      timer.Stop(); 
      timer.Dispose(); 
     } 
    }; 

    timer.Start(); 
} 
+1

में था यह एक समझदार टिप्पणी है, और मैं विशेष रूप से इस तथ्य की तरह हूं कि आप जोर दे रहे हैं कि "DoEvents से बचा जाना चाहिए" ... वास्तव में यह होना चाहिए। मैं कुछ भी बहुत समान करता हूं, लेकिन आप कुछ महत्वपूर्ण याद कर रहे हैं: आपको टाइमर को किसी बिंदु पर रोकना चाहिए !!! टिक हैंडलर के भीतर, चेक 'if (अस्पष्टता> = 1.0) {timer.Stop(); timer.Dispose(); } ' – fernandoespinosa

+0

@ khovanskiiªn धन्यवाद, मैं टाइमर को रोकने के लिए पूरी तरह से भूल गया; संपादित किया गया – Servy

15

टाइमर भूल जाएं (इच्छित इरादा)।

विजुअल स्टूडियो 4.5 या उच्चतम के साथ, आप केवल await देरी से कार्य कर सकते हैं। इस विधि का एक लाभ यह है कि यह Sleep या DoEvents लूप के विपरीत असीमित है, जो फीका के दौरान एप्लिकेशन को अवरुद्ध करता है (और अन्य उपर्युक्त DoEvents समस्याएं)।

private async void FadeIn(Form o, int interval = 80) 
{ 
    //Object is not fully invisible. Fade it in 
    while (o.Opacity < 1.0) 
    { 
     await Task.Delay(interval); 
     o.Opacity += 0.05; 
    } 
    o.Opacity = 1; //make fully visible  
} 

private async void FadeOut(Form o, int interval = 80) 
{ 
    //Object is fully visible. Fade it out 
    while (o.Opacity > 0.0) 
    { 
     await Task.Delay(interval); 
     o.Opacity -= 0.05; 
    } 
    o.Opacity = 0; //make fully invisible  
} 

उपयोग:

private void button1_Click(object sender, EventArgs e) 
{ 
    FadeOut(this, 100); 
} 

अगर वस्तु इससे पहले कि आप के लिए किसी भी पारदर्शिता लागू निपटान किया जाता है आप जाँच करनी चाहिए। मैंने ऑब्जेक्ट के रूप में एक फॉर्म का उपयोग किया था, लेकिन आप किसी ऑब्जेक्ट को पारित कर सकते हैं जो पारदर्शिता का समर्थन करता है जब तक कि यह ठीक से डाला जाता है।

+0

जब मैं पृष्ठभूमि कार्यकर्ता से फ़ेडइन को कॉल करता हूं, तो 'प्रतीक्षा' रेखा एक डेडलॉक का कारण बनती है। इससे कैसे बचा जा सकता है? –

+1

@NineTails ने इस में फेडइन विधि को लपेटने का प्रयास किया है। बेगिन इनवोक (नई क्रिया (() => फ़ेडइन (...)))? – drake7707

+1

@ drake7707 धन्यवाद। हालांकि मैंने पहले 'सिंक्रनाइज़ेशन कॉन्टेक्स्ट.सेट सिंक्रनाइज़ेशन कॉन्टेक्स्ट (नया विंडोजफॉर्म सिंक्रनाइज़ेशन कॉन्टेक्स्ट()) के साथ अपना मुद्दा हल किया;' –

1

मैंने विक्टर स्टोडार्ड के दृष्टिकोण को स्प्लैशस्क्रीन पर लागू किया। मैंने इसे फॉर्म_लोड ईवेंट में फीडइन और फॉर्मक्लोसिंग इवेंट में फीडऑट पर इस्तेमाल किया। नोट: fadeIn विधि को कॉल करने से पहले मुझे फॉर्म की अस्पष्टता 0 पर सेट करनी थी।

यहाँ आप एक WinForm (जीवन चक्र) द्वारा rised घटनाओं के क्रम देख सकते हैं: https://msdn.microsoft.com/en-us/library/86faxx0d(v=vs.110).aspx

private void Splash_Load(object sender, EventArgs e) 
{ 
    this.Opacity = 0.0; 
    FadeIn(this, 70); 
} 


private void Splash_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    FadeOut(this, 30); 
} 

private async void FadeIn(Form o, int interval = 80) 
{ 
    //Object is not fully invisible. Fade it in 
    while (o.Opacity < 1.0) 
    { 
     await Task.Delay(interval); 
     o.Opacity += 0.05; 
    } 
    o.Opacity = 1; //make fully visible  
} 

private async void FadeOut(Form o, int interval = 80) 
{ 
    //Object is fully visible. Fade it out 
    while (o.Opacity > 0.0) 
    { 
     await Task.Delay(interval); 
     o.Opacity -= 0.05; 
    } 
    o.Opacity = 0; //make fully invisible  
} 
0

मैं विशेष रूप में करते हैं और प्रपत्र fading के लिए एक वर्ग के लिए लिखा था। यह ShowDialog और डायलॉग रिसेट्स का भी समर्थन करता है।

मैंने इस पर विस्तार किया है क्योंकि मुझे नई सुविधाओं की आवश्यकता है, और सुझावों के लिए खुला हूं। Win32, IIRC, पर

https://gist.github.com/nathan-fiscaletti/3c0514862fe88b5664b10444e1098778