Vadim Ovchinnikov
Vadim Ovchinnikov

Reputation: 14022

Showing invisible window

I have a window with some process and visualization but I want this window to be hidden on startup but still performing it's work. I've managed to achieve this using simple code

SomeWindow.Show();
SomeWindow.Hide();

But the issue is this code causing startup flickering. I can't fight this neither in Windows Forms, nor in WPF. Is there more elegant way to show hidden/invisible window?

UPDATE

I want the window to show in TaskBar but only when it's visible. Window is performing task that relies on rendering that will be performing in time regardless of visibility and user should be able to see it's state like it was open all the time.

Upvotes: 1

Views: 2983

Answers (5)

Markus Nißl
Markus Nißl

Reputation: 381

Vadim Ovchinnikov's answer for WPF was a great start, but didn't work for me eventually for two reasons: Show() and Hide() are synchronous methods which is a problem when you want to have that window precreated while no other window is open (for there is no Dispatcher executing these requests); furthermore restoring the original values had to be performed later, otherwise a quick flicker was still noticeable. Then again, I had to restore the value of ShowInTaskbar asynchronously; otherwise the taskbar entry was missing, but curiously only when running in the Visual Studio debugger.

The following helper class does the job for me:

public class InitiallyInvisibleWindow
{
  private readonly Window _window;
  private bool _origShowActivated;
  private bool _origShowInTaskbar;
  private WindowState _origWindowState;

  public InitiallyInvisibleWindow(Window window)
  {
    _window = window;
  }

  public void ShowInvisible()
  {
    _origShowActivated = _window.ShowActivated;
    _origShowInTaskbar = _window.ShowInTaskbar;
    _origWindowState = _window.WindowState;

    _window.ShowActivated = false;
    _window.ShowInTaskbar = false;
    _window.WindowState = WindowState.Minimized;

    _window.Visibility = Visibility.Visible;
    _window.Visibility = Visibility.Hidden;
  }

  public void RestoreVisible()
  {
    _window.ShowActivated = _origShowActivated;
    _window.Visibility = Visibility.Visible;

    Dispatcher.CurrentDispatcher.InvokeAsync(() =>
      {
        _window.ShowInTaskbar = _origShowInTaskbar;
        _window.WindowState = _origWindowState;
      });
  }
}

Upvotes: 1

Vadim Ovchinnikov
Vadim Ovchinnikov

Reputation: 14022

Based on Logman's answer I've created extension method to show invisible window

For Windows Forms:

public static class FormHelper
{
    public static void ShowInvisible(this Form form)
    {
        // saving original settings
        bool needToShowInTaskbar = form.ShowInTaskbar;
        FormWindowState initialWindowState = form.WindowState;

        // making form invisible
        form.ShowInTaskbar = false;
        form.WindowState = FormWindowState.Minimized;

        // showing and hiding form
        form.Show();
        form.Hide();

        // restoring original settings
        form.ShowInTaskbar = needToShowInTaskbar;
        form.WindowState = initialWindowState;
    }
} 

or for WPF:

public static class WindowHelper
{
    public static void ShowInvisible(this Window window)
    {
        // saving original settings
        bool needToShowInTaskbar = window.ShowInTaskbar;
        WindowState initialWindowState = window.WindowState;

        // making window invisible
        window.ShowInTaskbar = false;
        window.WindowState = WindowState.Minimized;

        // showing and hiding window
        window.Show();
        window.Hide();

        // restoring original settings
        window.ShowInTaskbar = needToShowInTaskbar;
        window.WindowState = initialWindowState;
    }
}

Upvotes: 1

Logman
Logman

Reputation: 4189

Try this:

SomeWindow.ShowInTaskbar = false; // not shown on taskbar set to true if you want to show form on taskbar
SomeWindow.WindowState = FormWindowState.Minimized; // set window state as minimized
SomeWindow.Show(); 

You don't even need to hide it.

This is winforms version I did not test it in WPF.

Update:

If Hide() is not done after Show() window is on opened windows list (Alt+Tab). To prevent this do:

SomeWindow.Hide(); 

Upvotes: 3

C Perkins
C Perkins

Reputation: 3882

This works on my machine without "flicker". As Ed mentioned, the Taskbar button behaves as you would expect without addition settings or code.

//Assuming SomeWindow is System.Windows.Form object
SomeWindow.Opacity = 0.0;
SomeWindow.Show();
SomeWindow.Hide();

//Elsewhere in code when you want to display the window
SomeWindow.Opacity = 1.0;
SomeWindow.Visible = true;

Upvotes: 0

Kelly
Kelly

Reputation: 7183

Why use a window for this task? Why not just start up a class on another thread and have it do the work?

If a window is really needed just have the window when opened request data from that custom task.

var myClass = new MyClass();

Task.Run(()=>myClass.Start());

Upvotes: 0

Related Questions