0

I have a window.xaml which has components with different kind of styling( border color red, opacity changed and so on). In one moment I want to create a screenshot and save to folder. But before that the window background should be transparent and someCanvas should be hidden.

How do I know when the styling method finished so I can take a screenshot?

public void SomeMethod()
{
    ChangeWindowControlStyles();

    //TODO: waint till 'ChangeWindowControlStyles' finished

    TageScreenshotAndSave();
}

public void ChangeWindowControlStyles()
{
     this.Background.Opacity = 0;

     this.someCanvas.Visibility = Visibility.Collapsed;

     //Some other stuff related to window content styling
}

public void TakeScreenshotAndSave()
{
    //No multithreading happening here

    //Just taking screenshot and saving to folder
}

EDIT

The window itself is transparent WindowStyle="None", that means it has no borders. In the start the window's Background.Opacity is set to 0.1 and all controls are visible (there are other controls than someCanvas that should always be visible).

Before screenshot is taken someCanvas is hidden and the Background.Opacity is set to 0.

Window.xaml

<Window
    WindowStartupLocation="CenterScreen" 
    ResizeMode="NoResize" 
    WindowState="Maximized"
    WindowStyle="None" 
    AllowsTransparency="True" >

   <Window.Background>
        <SolidColorBrush Opacity="0.1" Color="White"/>
    </Window.Background>

        <Grid Name="mainGrid" Background="Transparent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0">

            <!--Main canvas, function holder-->
            <Canvas Name="canvasAlwaysVisible" Margin="0" Panel.ZIndex="5">
                <!-- Controls that are always visible -->
            </Canvas>

            <Canvas x:Name="someCanvas" Margin="0" Background="Transparent" Visibility="Visibility">
                <!-- Controls with styling -->
            </Canvas>

        </Grid>
</Window>

EDIT 2

Another thing to mention is that inside TakeScreenshotAndSave there is also System.IO operations like - get all folders in directory, creation new directory and so on. Maybe .NET sees that and it is ran asynchronously.

Mr. Blond
  • 1,113
  • 2
  • 18
  • 41
  • As long as you don't call `ChangeWindowControlStyles` asynchronously, it will be complete when the next line runs. You don't have to "wait" for a method to return, its finished as soon as the line is done executing and goes to the next one. Depending on how `SomeMethod` is called, you may need to invoke on the `Dispatcher` though. – Ron Beyer Jul 19 '15 at 21:28
  • Are you trying to take a screenshot of the screen without all your program windows or a screenshot without only the window that triggers it but you still have other windows? – SaintJob 2.0 Jul 19 '15 at 21:29
  • I would like to hide one of the canvas in that window, also to change window.Background Opacity to 0. So, I want to hide specific controls only not all window. I will edit my post, add some additional info. @SaintJob2.0 – Mr. Blond Jul 19 '15 at 21:42
  • And btw, what happens when you take the screenshot? The styles are not applied yet? – SaintJob 2.0 Jul 19 '15 at 21:55
  • Yes. That saved screenshot contains styles that should be removed. @SaintJob2.0 – Mr. Blond Jul 19 '15 at 22:06
  • As far as I know, there is a Control.StyleChanged event, but I never looked if it is triggered after the change or wen the change starts. You could try it. – SaintJob 2.0 Jul 19 '15 at 22:10
  • I got your code and added button. On click I hide it and make screenshot of window as here: http://stackoverflow.com/questions/24466482/how-to-take-a-screenshot-of-a-wpf-control. It worked for me. Need more code to reproduce your error. – keymusicman Jul 19 '15 at 22:23
  • After Edit 2 I changed code and it still works. As about folders reading, .NET cannot perform synch operation asynchrously. – keymusicman Jul 19 '15 at 22:47
  • By using `Application.Current.Dispatcher` it worked! – Mr. Blond Jul 19 '15 at 23:19

1 Answers1

0

Looks like I found the solution. I don't know why it works, will need to investigate more. That TakeScreenshotAndSave method that I mentioned in code sample was somehow running on different thread. When wrap that method inside Application.Current.Dispatcher it worked!

public void SomeMethod()
{
    ChangeWindowControlStyles();

    var m_dispatcher = Application.Current.Dispatcher;

    m_dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.ApplicationIdle,
    new System.Threading.ThreadStart(delegate
    {

        TakeScreenshotAndSave(); //Now running on UI thread

    }));
}
Mr. Blond
  • 1,113
  • 2
  • 18
  • 41
  • 2
    It works, because the view is not repainted immediately. After each change there is a notification, that a repaint has to be done and it will be done when the application enters the idle state. So you are doing the right thing, wait for idle and take the screenshot – Sir Rufo Jul 19 '15 at 23:57