Splash Screen in WPF two monitors - c#

I am developing a WPF application. I am using two monitors. I am using splash screen to pop up on window when some function is executing.
The problem I have is when I move the application to secondary monitor and start processing functions splash screen is still being displayed in primary monitor instead on secondary monitor.
Any help on this?

you can try for BusyIndicator if suitable for you or else you can try below code to show Splash Window.
void TemplateSelector_Loaded(object sender, RoutedEventArgs e)
{
showWin();
Thread.Sleep(10000);
CloseWin();
}
private void CloseWin()
{
WindowManager.Close();
}
Window tempWindow = new Window();
public void showWin()
{
WindowManager.LaunchWindowNewThread<SplashWindow>();
}
}
public class WindowManager
{
private static Window win;
public static void LaunchWindowNewThread<T>() where T : Window, new()
{
Thread newWindowThread = new Thread(ThreadStartingPoint);
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
Func<Window> f = delegate
{
T win = new T();
return win;
};
newWindowThread.Start(f);
}
private static void ThreadStartingPoint(object t)
{
Func<Window> f = (Func<Window>)t;
win = f();
win.WindowStartupLocation = WindowStartupLocation.CenterScreen;
win.Topmost = true;
win.Show();
Dispatcher.Run();
}
public static void Close()
{
if (win != null)
win.Dispatcher.BeginInvokeShutdown(DispatcherPriority.Send);
}
}

Related

How to call a public function declared in SecondWIndow from Main WIndow

I have 2 Windows in my WPF application. I'm running the SecondWindow from MainWindow using a background thread like as follows.
Thread newWindowThread = new Thread(new ThreadStart(() =>
{
SecondWindow sw = new SecondWindow(this);
sw.Show();
Dispatcher.Run();
}));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.IsBackground = true;
newWindowThread.Start();
and I also have Public Function in the SecondWindow Like this...
public async void hide_animate()
{
//Some Stuff//
}
I want to call hide_animate from a method from my MainWindow
I tried some options I found by googling, but nothing seems to work. any help?
Update:
I've tried this to call the function but still nothing happening...
Window mywindow = FindMyWindow("SecondWindow");
if (mywindow != null)
{
SeocondWinodw.hide_animate();
}
private Window FindMyWindow(string windowName)
{
foreach (Window wnd in System.Windows.Application.Current.Windows)
{
if (wnd.Title.ToUpper().Equals(windowName.ToUpper()))
{
return wnd;
}
}
return null;
}

modal form does not restore after minimize with 2 ui threads

The problem is that i have some kind of splash screen which shows loading animation.
I have special manager that show and hide it.
class Manager
{
private Form CurForm;
Thread curt;
private Manager()
{
curt= new Thread(start);
curt.ApartmentState = ApartmentState.STA;
curt.IsBackground = true;
curt.Start();
}
void start()
{
CurForm = new Animation();
Application.Run(CurForm);
}
public static readonly Manager Active = new Manager();
public static void Show()
{
if (Active.CurForm != null)
{
Active.CurForm.Invoke(new Action(() => { Active.CurForm.Show(); }));
}
}
public static void Hide()
{
if (Active.CurForm != null)
{
Active.CurForm.Invoke(new Action(() => { Active.CurForm.Hide(); }));
}
}
}
I open some modal form (ShowDialog). This modal form doesn't show in taskbar.
I easily can minimise it and after clicking on main form on task bar it show that modal form on top.
But when I show this loading animation while it's loading all necessary data.
some kind like that (of course it is just a sample to test it work, and in real app it tooks much time to load all data and form with lots of controls)
public modal()
{
Manager.Show();
InitializeComponent();
Thread.Sleep(5000);
Manager.Hide();
}
And when i'm trying to minimise and restore it like i said above it doesn't restore my modal form and just show my main not available form. And more than that it works in some cases but in some not.
Does anybody know why it is happens or how to fix it?
it is strange but when i modify like this, everything seems to work normal.
I just kill separate ui thread.
public class MyApplicationContext:ApplicationContext
{
public Form CurForm;
ManualResetEvent ready = new ManualResetEvent(false);
public MyApplicationContext()
{
CurForm=new Animation();
CurForm.Show();
}
}
class Manager
{
private MyApplicationContext CurContext;
Thread curt;
void start()
{
try
{
CurContext = new MyApplicationContext();
Application.Run(CurContext);
}
catch
{
CurContext.CurForm.Close();
}
}
private void Init()
{
curt = new Thread(start);
curt.SetApartmentState(ApartmentState.STA);
curt.IsBackground = true;
curt.Start();
}
public static Manager Active
{
get
{
if (active == null)
{
active = new Manager();
}
return active;
}
}
private static Manager active;
public static void Show()
{
Active.Init();
}
public static void Hide()
{
Active.curt.Abort();
}

Using SetParent freeze the parent window

I have an application in C# which creates a form and stack it in front of another app's window.
I do this by using SetParent. However, the (new) parent window freezes.
How can I solve that? Is this a matter of threading?
This is working:
private void Test(object sender, EventArgs e)
{
FormCover cov = new FormCover();
IntPtr hwnd = Win32Utils.FindWindowByCaptionStart(IntPtr.Zero, TrackerName, null);
Win32Utils.SetParent(cov.Handle, hwnd);
cov.SetDesktopLocation(0, 0);
cov.Show();
}
But this (with a timer elapsed event) is not:
public partial class Form1 : Form
{
FormCover cover;
void tmrCheck_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
ShowCover();
}
private void ShowCover()
{
cover = new FormCover();
IntPtr hwnd = Win32Utils.FindWindowByCaptionStart(IntPtr.Zero, TrackerName, null);
cover.CoverInitialize(hwnd);
cover.Activate();
}
}
//------
public partial class FormCover : Form
{
public delegate void IntPtrDlg(IntPtr param);
public FormCover()
{
InitializeComponent();
}
internal void CoverInitialize(IntPtr hwdnParent)
{
if (this.InvokeRequired)
{
this.Invoke(new IntPtrDlg(CoverInitialize), new object[] { hwdnParent });
}
else
{
Win32Utils.SetParent(this.Handle, hwdnParent);
this.SetDesktopLocation(0, 0);
}
}
internal void CoverActivate(IntPtr handleFormulario)
{
if (!Visible)
this.Show();
}
internal void CoverFinalize()
{
Hide();
Win32ParentUtils.SetParent(Handle, new IntPtr());
}
}
What is the difference between these two samples? The first one is working fine, the second one is freezing the aprent window.
As I just stated, you'll need to create a message pump for your form.
Try
Thread thread = new Thread( () =>
{
var formCover = new FormCover();
Application.Run(formCover);
});
thread.ApartmentState = ApartmentState.STA;
thread.Start();
Then you should be able to set the parent of your form.
See here for further reference.

Thread safe form manipulation between two forms (WinForms C#)

I have two forms, the main form and one that pops up as a modal dialog. From a process spawned in the main form, I want to dynamically update the text on the modal dialog. Here's what I have:
In the main form, I do this:
// show the wait modal
var modal = new WaitDialog { Owner = this };
// thread the packaging
var thread = new Thread(() => Packager.PackageUpdates(clients, version, modal));
thread.Start();
// hopefully it worked ...
if (modal.ShowDialog() != DialogResult.OK)
{
throw new Exception("Something failed, miserably.");
}
The PackageUpdates method takes the modal dialog, and does this:
// quick update and sleep for a sec ...
modal.SetWaitLabelText("Downloading update package...");
Thread.Sleep(2000);
modal.SetWaitLabelText("Re-packaging update...");
To be thread safe, I do this in the modal dialog:
public void SetWaitLabelText(string text)
{
if (lblWaitMessage.InvokeRequired)
{
Invoke(new Action<string>(SetWaitLabelText), text);
}
else
{
lblWaitMessage.Text = text;
}
}
Everything works great ... most of the time. Every three or four times that the modal pops up, I get an exception on the lblWaitMessage.Text = text; and it's not invoking the command.
Am I missing something in this setup?
Like #Hans Passant pointed out, you should wait for the modal.Load-event. One good option is to use the ManualResetEvent to inform your thread to wait until that happens.
The WaitOne method will block the thread until the Set method is called. Here's a very simple setup which should do the trick.
public partial class Form1 : Form
{
ManualResetEvent m_ResetEvent;
public Form1()
{
InitializeComponent();
m_ResetEvent = new ManualResetEvent(false);
}
private void button1_Click(object sender, EventArgs e)
{
Dialog d = new Dialog { Owner = this, ResetEvent = m_ResetEvent };
var thread = new Thread(new ParameterizedThreadStart(DoSomething));
thread.Start(d);
if (d.ShowDialog() != System.Windows.Forms.DialogResult.OK)
{
throw new Exception("Something terrible happened");
}
}
private void DoSomething(object modal)
{
Dialog d = (Dialog)modal;
// Block the thread!
m_ResetEvent.WaitOne();
for (int i = 0; i < 1000; i++)
{
d.SetWaitLabelText(i.ToString());
Thread.Sleep(1000);
}
}
}
And here is the modal form
public partial class Dialog : Form
{
public Form Owner { get; set; }
public ManualResetEvent ResetEvent { get; set; }
public Dialog()
{
InitializeComponent();
}
public void SetWaitLabelText(string text)
{
if (label1.InvokeRequired)
{
Invoke(new Action<string>(SetWaitLabelText), text);
}
else
{
label1.Text = text;
}
}
private void Dialog_Load(object sender, EventArgs e)
{
// Set the event, thus unblocking the other thread
ResetEvent.Set();
}
}
I think you should rewrite the code to let thread.Start() isn't called before modal.ShowDialog().
As a workaround, you can try this:
public void SetWaitLabelText(string text) {
Invoke(new Action<string>(SetWaitLabelText2), text);
}
void SetWaitLabelText2(string text) {
lblWaitMessage.Text = text;
}
The first method always uses Invoke, regardless the value of InvokeRequired. The second method actually does the thing. This pattern is usable when you always call the function from another thread.

C# Run application MINIMIZED at windows startup

I got the following code to run the application at windows startup:
private void SetStartup(string AppName, bool enable)
{
string runKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
Microsoft.Win32.RegistryKey startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey);
if (enable)
{
if (startupKey.GetValue(AppName) == null)
{
startupKey.Close();
startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey, true);
startupKey.SetValue(AppName, Application.ExecutablePath.ToString());
startupKey.Close();
}
}
else
{
startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey, true);
startupKey.DeleteValue(AppName, false);
startupKey.Close();
}
}
It works. but I want the program to start minimized (at windows startup only).
I didnt find a working code / good explanation how to do it.
Can you help me please?
thanks.
Have you tried
this.WindowState = FormWindowState.Minimized;
If you want to start minimized at windows startup only you can add extra argument to command line, like myapp.exe --start-minimized, then you can parse this parameter and detect whether you need to start minimized or not.
Since this is only adding a registry key to SOFTWARE\Microsoft\Windows\CurrentVersion\Run which causes the OS to start the app at startup there isn't a lot you can do unless the application you want to startup accepts a command line parameter to start minimized (You could then add the parameter to the executable path of the key).
If this is a necessary function and you can't modify the program to accept a parameter to minimize the only thing I can think of doing would be to write a program that would minimize these apps after the OS has started them.
Don't normally revive old threads but one Easy way including minimize to system tray, for WPF like this:
public class EntryPoint
{
[STAThread]
public static void Main(string[] args)
{
SingleInstanceManager manager = new SingleInstanceManager();
manager.Run(args);
}
}
public class SingleInstanceManager : WindowsFormsApplicationBase
{
SingleInstanceApplication app;
public SingleInstanceManager()
{
this.IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
app = new SingleInstanceApplication();
app.Run();
return false;
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
base.OnStartupNextInstance(eventArgs);
app.Activate();
}
}
public class SingleInstanceApplication : Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
bool startMinimized = false;
for (int i = 0; i != e.Args.Length; ++i)
{
if (e.Args[i] == "/StartMinimized")
{
startMinimized = true;
}
}
MainWindow mainWindow = new MainWindow();
if (startMinimized)
{
mainWindow.WindowState = WindowState.Minimized;
}
mainWindow.Show();
}
public void Activate()
{
this.MainWindow.Activate();
this.MainWindow.WindowState = WindowState.Normal;
}
}
}
Your Window class:
public partial class MainWindow : Window
{
private Window _window;
public MainWindow()
{
InitializeComponent();
SetStartup("AppName", true);
}
private void SetStartup(string AppName, bool enable)
{
string runKey = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
Microsoft.Win32.RegistryKey startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey);
if (enable)
{
if (startupKey.GetValue(AppName) == null)
{
startupKey.Close();
startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey, true);
startupKey.SetValue(AppName, Assembly.GetExecutingAssembly().Location + " /StartMinimized");
startupKey.Close();
}
}
else
{
startupKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(runKey, true);
startupKey.DeleteValue(AppName, false);
startupKey.Close();
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (this.WindowState == System.Windows.WindowState.Minimized)
{
var minimized = (_window.WindowState == WindowState.Minimized);
_window.ShowInTaskbar = !minimized;
}
else
ShowInTaskbar = true;
}
Worked first time so had to post. I'm using WPF notifyicon, hence why i needed it to go to system tray on windows startup.
Had a really hard time finding a good answer to this, finally found it in a really old book. On my Forms application, just opened the program.cs and changed
Application.Run(new Form1());
to
Form1 f = new Form1();
f.WindowState = FormWindowState.Minimized;
f.ShowInTaskbar = false;
Application.Run(f);
and it opens without a flicker directly to the tray. This app was more just a service, so set it to just have a notify icon and exit button when right clicked. Hope this helps!!
I have strugled with the same issue, and found a working solution:
In your program.cs, handle the parameter, and then pass that parameter to Form1:
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length != 0){
Application.Run(new Form1(args[0]));
}
else
{
Application.Run(new Form1("normalState"));
}
}
In your Form1.cs, you can call a function with the passed parameter and minimize the app:
public Form1(string parameter)
{
InitializeComponent();
MinimizeApp(parameter);
}
For example, with this function i used, if you start the application with the -minimized parameter, then it will start minimized, a notifyicon pops up in the taskbar and a bubble saying the app is started and running in the background.
public void MinimizeApp(string parameter)
{
if (parameter == "-minimized")
{
this.WindowState = FormWindowState.Minimized;
notifyIcon1.Visible = true;
notifyIcon1.BalloonTipText = "Program is started and running in the background...";
notifyIcon1.ShowBalloonTip(500);
Hide();
}
}

Categories