2011-11-10 13 views
7

बंद हो गया है, मैंने एक कस्टम wpf स्प्लैश-स्क्रीन कार्यान्वयन के साथ समस्या में भाग लिया है। समस्या यह है कि लोडिंग समाप्त होने के बाद और मेनविंडो को दिखाया जाना चाहिए, इसे कभी-कभी सामने नहीं लाया जाता है iee सक्रिय() कॉल विफल रहता है। यह शायद 1/10 बार होता है। एप्लिकेशन विंडोज 7/64 पर चलाया जाता है।स्प्लैश-स्क्रीन के बाद मुख्यविंडो को सामने लाएं

यहाँ implmentation (पूर्ण स्रोत sample)

public partial class App : Application 
{ 
    private Splash _splash; 
    private SplashVM _viewModel; 

    protected override void OnStartup(StartupEventArgs e) 
    { 
     base.OnStartup(e); 

     // starts splash in separate GUI thread 
     StartSplash(); 

     // continues on loading main application in main gui thread 
     LoadMainAppFakeSteps(1000, 3); 

     // tells splash screen to start shutting down 
     Stop(); 

     // Creates mainwindow for application 
     // The problem is that the mainwindow sometimes fails to activate, 
     // even when user has not touched mouse or keyboard (i.e has not given any other programs or components focus) 
     MainWindow = new Shell(); 
     MainWindow.Show(); 
     MainWindow.Activate(); 
    } 

    private void StartSplash() 
    { 
     _viewModel = new SplashVM(); 
     var thread = new Thread(SplashThread); 
     thread.SetApartmentState(ApartmentState.STA); 
     thread.IsBackground = true; 
     thread.Start(_viewModel); 
    } 

    private void SplashThread(object vm) 
    { 
     _splash = new Splash(); 
     _splash.DataContext = vm; 
     _splash.Show(); 

     System.Windows.Threading.Dispatcher.Run(); 

     _splash = null; 
     _viewModel = null; 
    } 

    private void LoadMainAppFakeSteps(int stepDelayMs, int numSteps) 
    { 
     for (int i = 1; i <= numSteps; i++) 
     { 
      _viewModel.Text = i.ToString(); 
      Thread.Sleep(stepDelayMs); 
     } 
    } 

    private void Stop() 
    { 
     if (_splash == null) throw new InvalidOperationException("Not showing splash screen"); 

     _splash.Dispatcher.BeginInvokeShutdown(DispatcherPriority.Normal); 
    } 
} 

मैं इस की कोशिश की है:

MainWindow = new Shell(); 
MainWindow.Topmost = true; 
MainWindow.Show(); 
MainWindow.Activate(); 
MainWindow.Topmost = false; 

और यह काम करने लगता है, धन्यवाद आपके सभी सुझावों

+1

इसे विंडोज एक्सपी पर 30 बार कोशिश की और मैंने कभी समस्या नहीं देखी। आपको इस समस्या का क्या ओएस है? –

+1

मैं समस्या को पुन: उत्पन्न नहीं कर सकता। मैं विंडोज 7 का उपयोग कर रहा हूं। –

+0

@Meleak Win7/64 – hkon

उत्तर

3
MainWindow = new Shell(); 
MainWindow.Topmost = true; 
MainWindow.Show(); 
MainWindow.Activate(); 
MainWindow.Topmost = false; 
+0

से एक्सई चलाते हैं तो यह वास्तव में इसे ठीक करने लगता है, संभवतः फोकस चोरी करने के लिए मजबूर होना। सक्रिय कॉल की भी आवश्यकता नहीं है। – stijn

4

विंडोज कुछ में बनाया गया है विंडोज़ को वर्तमान में सक्रिय थ्रेड से फोकस चोरी करने से रोकने के लिए सुरक्षा। इसका अर्थ यह है कि आप केवल Activate() किसी अन्य विंडो से एक फ़ॉर्म को वर्तमान में देने का ध्यान केंद्रित कर सकते हैं।

उदाहरण के लिए यदि आपका मुख्य एप्लिकेशन विंडो एक संवाद दिखाता है, खिड़कियों यह ध्यान केंद्रित किया है क्योंकि मुख्य अनुप्रयोग सिर्फ एक ही धागे में ध्यान केंद्रित करती थी और कर सकते हैं तो इसके पास होते हैं, जो करने के लिए खुश है।

स्पलैश स्क्रीन के मामले में आपका मुख्य रूप कई कारणों से केंद्रित विंडो नहीं हो सकता है। या तो क्योंकि आपकी स्प्लैश स्क्रीन पर ध्यान केंद्रित किया गया है या क्योंकि अंतिम उपयोगकर्ता ने आपके ऐप को लोड करना शुरू कर दिया है और फिर कुछ और करना शुरू कर दिया है (शायद उनके ईमेल या ब्राउज़र के साथ खेलना) जिसका अर्थ है कि आपके ऐप पर बिल्कुल ध्यान नहीं दिया गया है। पहले मामले में (आप टास्कबार में खिड़की फ़्लैश ध्यान केंद्रित करने की कोशिश कर देख सकते हैं?)

, आप अपने स्प्लैश स्क्रीन मुख्य रूप से सक्रिय करने के लिए और फिर बंद करना चाहते हैं। (जैसा कि स्प्लैश स्क्रीन को बंद करने के लिए पहले और फिर मुख्य रूप को सक्रिय करने का प्रयास किया गया था)। यदि थ्रेड के साथ आपकी गड़बड़ी है, तो आप खिड़की हैंडल के साथ SetForegroundWindow() पर कॉल करने के लिए कुछ Win32 पिनवोक का उपयोग करने पर भी वापस आ सकते हैं। आप थ्रेड के चारों ओर खिड़की हैंडल पास कर सकते हैं। इससे यह सुनिश्चित होगा कि विंडोज फोकस के लिए आपके अनुरोध के लिए उपयुक्त है क्योंकि वर्तमान में केंद्रित फॉर्म अनुरोध कर रहा है।

एक ही तरीका है Windows 2000 और Windows XP आप सामने करने के लिए अपने आवेदन की खिड़की लाने देता है, तो धागा यह पर चल रहा है है:

यहाँ चोरी फोकस के विषय पर एक स्वच्छ लेख है उस समय अग्रभूमि खिड़की का धागा। तो, आपको अपने आवेदन के थ्रेड को अग्रभूमि विंडो के थ्रेड पर संलग्न करना है और फिर अपने एप्लिकेशन की विंडो को सामने लाएं। के बाद आपको अपने धागे को अलग करने की आवश्यकता है (यह सब तब होता है जब उपयोगकर्ता में अग्रभूमि सक्रिय विंडो के रूप में एक और एप्लिकेशन की विंडो हो)। स्रोत:Force Window to Front

किसी के लिए इस लेख के कोड परिवर्तित सी यह अन्य StackOverflow पोस्ट में अधिक #: Steal Focus in C# on StackOverflow (PInvoke कॉल के लिए कुछ परिभाषाओं की तरह याद कर रहे हैं लगता है, लेकिन आप के साथ "PInvoke" गूगल पर आसानी से इन पा सकते हैं और Win32 एपीआई आप चाहते हैं उसका नाम।)

1

इसके अलावा hkon करने के अगर आपके स्प्लैश स्क्रीन सर्वोच्च = सच के माध्यम से ध्यान केंद्रित चोरी करने से पहले वर्तमान अग्रभूमि खिड़की है आप की जाँच करनी चाहिए जवाब।

[DllImport("user32.dll")] 
    private static extern IntPtr GetForegroundWindow(); 

    public static bool IsForeground(this Window window) 
    { 
     var windowHandle = new WindowInteropHelper(window).Handle; 
     var foregroundWindow = GetForegroundWindow(); 
     return windowHandle == foregroundWindow; 
    } 
+0

हाँ यह करने के लिए विनम्र बात होगी =) – hkon

संबंधित मुद्दे