Linked Questions

Popular Questions

I am writing WPF/C# code where I need to loop through all my views (windows) in my application. For each iteration, I open the window, do a screen capture of the window, then close the window.

The first issue I had was the fact that the screen capture was being executed before the window was fully painted on the screen. But this post helped me fix this issue. The problem I have is that it works fine when I just open one window. But because I now start a loop, to process each window, the screen freezes.

If you look at my code below, you will see that I use DispatcherPriority.ApplicationIdle for my DispatcherTimer. This works fine for one window because eventually the application will become idle after it opens the one window. But obviously, application idle never happens when I begin my loop. Which I am sure explains why the screen freezes when I try to process all my windows in a loop. How can I process each of my windows independently? Or find a way to call the screen capture code after each window opens?

    private void StartCapturing(object sender, EventArgs e)
    {
        // When opening one view using the next three lines, it works fine, the screen capture occurs when the window is fully painted.
        // i = 0;
        // m_view = SystemConfigurationComponent.GetView(@"gtcs\gcs\mmc_alarmlist");
        // CaptureView(m_view);

        // But when I loop all my views, screen freezes.
        var allViews = SystemConfigurationComponent.GetAllViews();
        foreach (var view in allViews)
        {
            i++;
            m_view = view;
            CaptureView(view);
        }
    }

    private void CaptureView(View view)
    {
        // Call UiLoaded method when UI is loaded and rendered
        m_dispatchTimer = new DispatcherTimer(TimeSpan.Zero, DispatcherPriority.ApplicationIdle, UiLoaded, Application.Current.Dispatcher);

        // Invoke OpenMimic with highest priority.
        Application.Current.Dispatcher.Invoke(new Action(() =>
        {
            ViewsIntegrationService.OpenMimic(m_view.Uri, string.Empty, string.Empty, 2, null, null);

        }), DispatcherPriority.Send, null);
    }

    /// <summary>
    /// Method called when DispatcherTimer when application is idle.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void UiLoaded(object sender, EventArgs e)
    {
        Application.Current.Dispatcher.BeginInvoke(
            DispatcherPriority.ApplicationIdle,
            new Action(() =>
            {
                // UI thread sometimes does not finish painting the window completely, so we delay the print screen slightly.
                Thread.Sleep(3000);
                //Dispatcher.Yield(DispatcherPriority.ApplicationIdle);

                // Generate print screen and save as Jpeg image file.
                using (Bitmap bitmap = new Bitmap(m_view.DefaultWidth, m_view.DefaultHeight + 35))
                {
                    using (Graphics g = Graphics.FromImage(bitmap))
                    {
                        g.CopyFromScreen(new Point(m_view.DefaultLeft, m_view.DefaultTop + 130), Point.Empty,
                            new Size() { Width = m_view.DefaultWidth, Height = m_view.DefaultHeight + 35 });
                    }
                    bitmap.Save(@"C:\\temp\\GTCS_PrintScreens\\test" + i++ + ".jpg", ImageFormat.Jpeg);
                    //bitmap.Save(view.WindowTitle.Replace(" ", string.Empty).Replace("'", string.Empty) + ".jpg", ImageFormat.Jpeg);

                    // Stop dispatcher timer, otherwise it will generate a lot of print screens.
                    m_dispatchTimer.Stop();

                    // Close mimic.
                    m_alsMimic = m_mimicsManager.Mimics.SingleOrDefault(m => m.Path == m_view.Uri);
                    ViewsIntegrationService.CloseView(new AlstomGuiMimicImpl(m_mimicsManager, m_alsMimic));
                }
            }));
    }

Related Questions