Showing invisible window - c#

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.

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();

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;
}
}

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;
});
}
}

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());

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;

Related

WPF UI resize after minimize and restore

I have a WPF Application. I need to minimize and restore the main window after instantiate it to obtain focus. I am using something like the following class but it is not making what I want because when the window is restored it has an invalid size. I've tried to modify the width and height but it is not working.
public class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ConfigureWindow();
}
public void Show()
{
base.Show();
UpdateWindowPositionAndSize();
base.WindowState = WindowState.Normal;
base.Show();
}
private void ConfigureWindow()
{
base.ShowActivated = true;
this.Focusable = true;
if (base.IsActive == false)
{
base.Activate();
}
if (base.IsFocused == false)
{
base.Focus();
}
base.WindowState = WindowState.Minimized;
}
private void UpdateWindowPositionAndSize()
{
this.Top = (SystemParameters.WorkArea.Height - this.Height) / 2;
this.Left = (SystemParameters.WorkArea.Width - this.Width) / 2;
}
}
What I am doing wrong? There is another way to obtain the focus? Sorry if the question is too newby.
UPDATED:
What is the specific need?
I need that my WPF Application appears on focus and active after launch it.
why?
Since it will be launched by a Windows (7, 8.1 and 10) User after explicitly click on a submenu from a file context menu (meaning a Shell Extension). This is 'why' my client wants that appears on front of the screen and focused.
when?
After instantiate the window.
how?
Well, I made some research and I found several ways to do this. One of the methods that I've tried is minimize the window and the restore it. There where others like using the functions SwitchToThisWindow or setforegroundwindow, but I would like to know if there are better options.
What happen when I've tried minimize and restore the window? (correct size)
Well, this way gives me focus on the main window, but it change the width and heigh. By default I define them on 300 (w) and 300 (h), but after changing the windows state to normal these values change to 400 (w) and 350 (h).
If I dont do anything, it has the focus right away?
... No ...
UPDATE2:
I choose the method used in the next link:
https://www.roelvanlisdonk.nl/2014/09/05/reliable-bring-external-process-window-to-foreground-without-c/
I am not quite sure what your problem is but maybe this can help.
1.) Remove StartupUri="MainWindow.xaml" from App.xaml;
2.) Add Startup="Application_Startup"
Your App.xaml.cs should look like this:
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
//Create new Instance of MainWindow
MainWindow mainWindow = new MainWindow();
//Set Properties of that Window
UpdateWindowPositionAndSize(mainWindow);
//Show it !
MainWindow = mainWindow; //This is the Application.MainWindow Property - not needed
mainWindow.ShowDialog();
}
private void UpdateWindowPositionAndSize(MainWindow mainWindow)
{
//Do your modifications here
mainWindow.Top = (SystemParameters.WorkArea.Height - mainWindow.Height) / 2;
mainWindow.Left = (SystemParameters.WorkArea.Width - mainWindow.Width) / 2;
}
}
So basically you just modify your Window until all is done.
There is no need to show it first, change its position and then bring it back on - if I got your "usecase" right.
Because to me it looks like you are hiding the window to do your "positioning".
But I think it's better to do it when Initializing.
Just a short comment on your code so far:
ConfigureWindow() is only doing minimize.
The rest of your code is useless cause obviously the window loses focus when it's minimized.
I would suggest not to create methods with names that already exist.
This will only lead to cusfusion.
If you got problems with WindowState = WindowState.Minimized; you can try Hide() and Activate().
By default when calling Window.Show(); the window will have focus. Check here for details.
Also after setting WindowState = WindowState.Minimized; you don't need to call base.Show(); again - the window is shown already. WindowState = WindowState.Normal; should do the job.

Make ShowDialog() after Show - WPF

Is there any possibility to make an already shown Window in to a Model Dialog (Like what happens when we call ShowDialog())
Blocking or Non Blocking, Any solution is acceptable for me, but all the Windows in the background should be disabled.
Hiding the window and again showing the window using ShowDialog is not possible since i have to maintain the state.
This is the closest I could get to a solution.The only issue is I change the WindowStyle to remove the title bar because otherwise you can still move those Windows.
this.Topmost = true;
foreach (Window window in Application.Current.Windows)
{
if (window.Title != this.Title)
{
window.Focusable = false;
window.WindowStyle = WindowStyle.None;
window.ResizeMode = ResizeMode.NoResize;
window.IsEnabled = false;
}
}

How to minimize all open windows except my program?

I want my program to be the only program showing, is there a way to do that?
I suppose by running something like
WindowState = ALL.Minimized;
Update
I made a Script like this
Set shell = wscript.CreateObject("Shell.Application")
Shell.MinimizeAll
Named it Mini.vbs
Then i used this code in Visual Studio
{
InitializeComponent();
TopMost = true;
System.Diagnostics.Process.Start("c:/mini.vbs");
}
It works, but its not the best solution .
You could simply set the TopMost property to True on the creation of the form.
public Form1()
{
InitializeComponent();
this.TopMost = true;
}
Goodluck.

WPF window force redraw window size

I know there are lots of article over Google related to this, and believe me I have tried almost everything.
So the problem is, I have a wpf application in which when user focuses on any input control like textbox I am showing external touch keyboard using TabTip.exe.
Following code:
public class KeyboardHelper
{
private const string PROCESS_NAME = "TabTip";
private const string PROCESS_PATH = "Common Files/Microsoft Shared/ink/TabTip.exe";
public static void ShowKeyboard()
{
Process keyboard = null;
Process[] pname = Process.GetProcessesByName(PROCESS_NAME);
if (pname.Length == 0)
{
keyboard = new Process();
}
else
{
keyboard = pname[0];
}
string processPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), PROCESS_PATH);
keyboard.StartInfo.FileName = processPath;
keyboard.Start();
}
public static void Closekeyboard()
{
Process[] pname = Process.GetProcessesByName(PROCESS_NAME);
if (pname.Length > 0)
{
pname[0].Kill();
}
}
}
Now problem starts here keyboard open but if it is in docked mode, it causes my app to resize almost half of the screen. And when I close the keyboard app remains same in size, I want to restore to full screen state again.
Controlling my size from cs because it comes from a DB
WindowState = maximized;
ResizeMode= NoResize;
WindowsStyle = None;
Any work around to solve the issue.
I have tried UpdateLayout, Dispatcher.BeginInvoke, Invalidate methods.
Thanks Jason, now I know the cause or can say case scenario of the problem. In my app I have to decide the startup page at runtime, So I am using code like this
private void Application_Startup(object sender, StartupEventArgs e)
{
//Set startup page for the application.
MainWindow window = new MainWindow();
window.ShowDialog();
}
And this is the problem. If I use normal default way than everything works fine.

C# Close processes minimized to tray in a graceful way?

I have an application that has can display a window using a Form. The form is only shown if the application is run using a -debug flag, otherwise it is only shown in tray.
var form = new Form();
if(DebugMode)
form.Show();
The application listens to CloseMainWindow() when run in debug mode, as the form is shown.
How can I make the application also listen to CloseMainWindow() without showing it? I don't want the user to be able to interact with the form if not in debug mode.
I've tried several approaches, like displaying the window but setting the size to 0. This shows a small form, i.e. not hidden.
if (!DebugMode)
{
form.Show();
form.Size = new Size(0, 0);
}
Also showing it, and then hiding it does not work:
if (!DebugMode)
{
form.Show();
form.Hide();
}
Showing it, but started minimized and not shown in taskbar does not work either:
if (!DebugMode)
{
form.Show();
form.WindowState = FormWindowState.Minimized;
form.ShowInTaskbar = false;
}
Am I missing something really obvious here, or is it not possible to close processes minimized to tray in a graceful way?
If i've understood the problem correctly, you want to completely hide the form when not in debug mode (i.e. the window is not seen anywhere but in the task manager) and when someone kills the process via task manager, you want to execute some code for clean-up or just get notified.
Basing my solution on this assumption, the following code should work
public static bool DebugMode = false;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form1();
form.Load += (s, e) =>
{
if (!DebugMode)
{
form.Opacity = 0;
form.ShowInTaskbar = false;
}
};
form.FormClosing += (s, e) =>
{
// Breakpoint hits
};
Application.Run(form);
}
I'm not sure you can do it through Process.CloseMainWindow(). Processes with no visible main window, I seem to recall, have MainWindowHandle set to IntPtr.Zero.
You need some kind of workaround. My advice is to keep track manually of the MainWindow Handles yourself:
static void Main()
{
...
MainWindow mainWindow = new MainWindow();
[HandleRepository] = mainWindow.Handle;
Application.Run(mainWindow);
}
Then when you want to close the process, do it with a workaround:
public void EndProcess()
{
Form mainWindow= (MainWindow)Form.FromHandle([HandleRepository]);
mainWindow.Close();
}
Might not be the most elegant solution but it should work (haven't tested it)

Categories