Bring already opened winform application to front without API? - c#

Hi,
Say that we got a WinForm application(app1) running in the background, now another application(app2)(the topmost active application) trigger a startProcess with the app1.
Now I need app1 to use the existing instance and bring it to topmost application(not only within the app1 application).
I have found this : http://sanity-free.org/143/csharp_dotnet_single_instance_application.html
Is it true that its not possible to do this without API? I have looked att bringToFront, Activate and Focus but all these does seem to only effect within a application and not between applications?

I don't know what you mean "without API" or why that matters.
However the simplest way is via WindowsFormsApplicationBase. It gives you all you need, with just a few lines of code.
You need to add a reference to the Microsoft.VisualBasic assembly - but it can be used through C#.
Make this class:
public class SingleInstanceApplication : WindowsFormsApplicationBase
{
private SingleInstanceApplication()
{
IsSingleInstance = true;
}
public static void Run(Form form)
{
var app = new SingleInstanceApplication
{
MainForm = form
};
app.StartupNextInstance += (s, e) => e.BringToForeground = true;
app.Run(Environment.GetCommandLineArgs());
}
}
And in your Program.cs, change the run line to use it:
//Application.Run(new Form1());
SingleInstanceApplication.Run(new Form1());

You really need some sort of communications between 2 apps. In article link to you posted communications is through WinApi messages. Also you can do that through sockets or through files and FileWatchers.
UPD1:
Code to simulate minimize with timer simulation message from another app and maximize on that message:
public partial class Form1 : Form
{
private Timer _timer = null;
public Form1()
{
InitializeComponent();
this.Load += OnFormLoad;
}
private void OnFormLoad(object sender, EventArgs e)
{
Button btn = new Button();
btn.Text = "Hide and top most on timer";
btn.Width = 200;
btn.Click += OnButtonClick;
this.Controls.Add(btn);
}
private void OnButtonClick(object sender, EventArgs e)
{
//minimize app to task bar
WindowState = FormWindowState.Minimized;
//timer to simulate message from another app
_timer = new Timer();
//time after wich form will be maximize
_timer.Interval = 2000;
_timer.Tick += new EventHandler(OnTimerTick);
_timer.Start();
}
private void OnTimerTick(object sender, EventArgs e)
{
_timer.Stop();
//message from another app came - we should
WindowState = FormWindowState.Normal;
TopMost = true;
}
}

Related

WinForm new form(waiting) is stuck when opens

I have wcf servise that Update db it is takes 10-15 sec,and i wont to run/show my form with loading/waitting statusbar while servise working, and when service is finished i need to close the watting form.
My problem is when i run ShowDialog(); it is get stuck on it , and don't go to my service.
What i doing wrong here?
My code
My function
public static void UpdateSNXRATES(object sender, EventArgs e)
{
WaitForm waitF = new WaitForm();
waitF.ShowDialog();//here it stuck
using (var Server = new ServiceReference.Service1Client())
{
Server.ClientCredentials.Windows.ClientCredential.Domain = strDomain;
Server.ClientCredentials.Windows.ClientCredential.UserName = strUser;
Server.ClientCredentials.Windows.ClientCredential.Password = strPassword;
success=Server.UpdateSNXRATES();
}
waitF.Close();
}
My WaitForm code
public partial class WaitForm : Form
{
public WaitForm()
{
InitializeComponent();
}
private void WaitForm_Load(object sender, EventArgs e)
{
radWaitingBar1.StartWaiting();
radWaitingBar1.WaitingSpeed = 100;
radWaitingBar1.WaitingStep = 5;
}
}
ShowDialog() is a blocking call, i.e. the current thread will keep waiting on this line until the form is closed (by the user). You should show your WaitForm on a different thread than the main application thread, combined with Invoke() call to ensure that you don't do illegal cross-thread operations. You can use BackgroundWorker component to load and show your WaitForm on a different thread.
Alternately and preferably, you should move your service initialization and running code to the BackgroundWorker. That will ensure you don't need any Invokes.
Example
ServiceReference.Service1Client Server;
WaitForm waitF;
public static void UpdateSNXRATES(object sender, EventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.RunWorkerAsync();
waitF = new WaitForm();
waitF.ShowDialog();
}
static void bw_DoWork(object sender, DoWorkEventArgs e)
{
Server = new ServiceReference.Service1Client();
Server.ClientCredentials.Windows.ClientCredential.Domain = strDomain;
Server.ClientCredentials.Windows.ClientCredential.UserName = strUser;
Server.ClientCredentials.Windows.ClientCredential.Password = strPassword;
success = Server.UpdateSNXRATES();
}
static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
waitF.Close()
}

Automatically hide one form in C# after many second and show another form

I need to hide current form after many second and then show any form
I'm writing this code but it doesn't work.
namespace tempprj
{
public partial class ProfileFrm : Telerik.WinControls.UI.RadForm
{
public ProfileFrm()
{
InitializeComponent();
}
private void ProfileFrm_Load(object sender, EventArgs e)
{
Frm2 child = new Frm2();
Thread.Sleep(3000);
this.Hide();
child.ShowDialog();
}
}
}
Thread.Sleep(3000);
is going to prevent your project from doing anything at all for 3 seconds (not counting other threads) and freeze the UI. I suggest using the standard .NET timer.
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx
This is a solution to my question:
private void ProfileFrm_Load(object sender, EventArgs e)
{
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Enabled = true;
timer1.Interval = 4000;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
this.Hide();
Frm2 f = new Frm2();
f.ShowDialog();
}

Problem with ShowDialog when ShowInTaskbar is false

Here is a small code that will illustrate my problem:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Interval = 3000;
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
using (Form form = new Form())
{
form.ShowInTaskbar = false;
form.ShowDialog();
}
}
}
If I press button1 (which calls button1_Click) and then click on another application in the taskbar so that it comes to the top, and then after 5 secs I go back to my application, the created form won't be visible and I won't have a way to bring it back to the top, while my Form1 will be unresponsive because of having an invisible dialog on top.
What's a workaround for this?
Make your main form an owner of your modal box.
Form form = new Form();
form.Owner = this;
form.ShowInTaskbar = false;
form.ShowDialog();

How to stop System.Timers.Timer

I'm using Windows Forms to start a System.Timers.Timer to fire an event every 3 seconds. When I close the form the process keeps firing, and that's fine. The problem happens when I reopen the form to stop the timer on click of a button btnSendOff_Click.
System.Timers.Timer sendTimer = new System.Timers.Timer();
sendTimer.Elapsed += new ElapsedEventHandler(sendProcessTimerEvent);
sendTimer.Interval = 3000;
private void sendProcessTimerEvent(object sender, EventArgs e)
{
MessageBox.Show("Send 3 sec");
}
private void btnSendOn_Click(object sender, EventArgs e)
{
sendTimer.Start();
}
private void btnSendOff_Click(object sender, EventArgs e)
{
sendTimer.Stop();
}
There will be more asynchronous timers on this form. How can I stop this timer when I reopen the form?
The form should not be creating a new timer every time you create a new instance of the form if it needs to keep running after the form closes. The way you have declared the timer, it will create another one each time the form is created. You should put the timer on a different form or declare it in some global module and only make the form activate or deactivate the timer. If the timer needs to keep running when the form is closed, the form should not be the one owning or creating the timer. If the timer doesn't need to keep running when the form is closed, then you should be using a Forms.Timer instead of a System.Timer.
Edit: Add Sample Code
static class Program
{
public static System.Timers.Timer sendTimer;
public static System.Text.StringBuilder accumulatedText;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
sendTimer = new System.Timers.Timer();
accumulatedText = new System.Text.StringBuilder("Started at " + DateTime.Now.ToLongTimeString() + Environment.NewLine);
sendTimer.Interval = 3000;
sendTimer.Elapsed += new System.Timers.ElapsedEventHandler(sendProcessTimerEvent);
Application.Run(new MainForm());
}
static void sendProcessTimerEvent(object sender, System.Timers.ElapsedEventArgs e)
{
accumulatedText.AppendLine("Pinged at " + DateTime.Now.ToLongTimeString());
}
}
class MainForm : Form
{
ToolStrip mainToolStrip = new ToolStrip();
public MainForm()
{
mainToolStrip.Items.Add("Log Control").Click += new EventHandler(MainForm_Click);
Controls.Add(mainToolStrip);
}
void MainForm_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
frm.ShowDialog();
}
}
class Form1 : Form
{
private Button button1 = new Button();
private TextBox text1 = new TextBox();
public Form1()
{
button1.Dock = DockStyle.Bottom;
button1.Text = Program.sendTimer.Enabled ? "Stop": "Start";
button1.Click += new EventHandler(button1_Click);
text1 = new TextBox();
text1.Dock = DockStyle.Fill;
text1.Multiline= true;
text1.ScrollBars = ScrollBars.Vertical;
text1.Text = Program.accumulatedText.ToString();
Controls.AddRange(new Control[] {button1, text1});
}
void button1_Click(object sender, EventArgs e)
{
Program.sendTimer.Enabled = !Program.sendTimer.Enabled;
button1.Text = Program.sendTimer.Enabled ? "Stop" : "Start";
}
}

Winforms Controlling Forms

How can i control all my forms from main ()
Form1 frm1 = new Form1();
Form1 frm2 = new Form1();
Form1 frm3 = new Form1();
Application.Run(frm1); // This way form-control goes to the frm1.
// In frm1 i have to write
frm1.Clicked += ()=>frm2.Show;
// I want the form-controlling style more explicitly
// I dont want to use Application.Run()
frm1.Show();
frm1.Clicked += frm2.Show();
form.ShowDialog () helps much but the execution stack can overflow.
Form.Show and Form.Hide methods runs when an application class has been set.
In Application.Run (Form) way there's always a main form. and i dont want this one. Any other approach you use in this problem
Your problem is, that you have four forms. All of them should exist side by side, but because you made Form1 to the master you got some problems.
To solve this you need another FormMaster above all four of them. This one will be started from Application.Run(). Now this form can be Visible = false, but in its constructor you can create all your four forms and decide how they will be glued together, which one will be shown first and under which circumstances your whole application will be closed.
The usual way is to use event handlers.
All I can understand is that you have several WinForms and you want some main Form to control them? Well, if I understanding/assumption is correct, then about controlling like following?
public partial class Form3 : Form
{
private void Form3_Load(object sender, EventArgs e)
{
Demo();
}
MyMainForm main = new MyMainForm(); //Your actual form
private void Demo()
{
main.Click += new EventHandler(main_Click);
main.ShowDialog();
}
void main_Click(object sender, EventArgs e)
{
MyNotificationForm notify = new MyNotificationForm();//Your notification form
notify.Name = "notify";
notify.Click += new EventHandler(notify_Click);
notify.ShowDialog(main);
}
void notify_Click(object sender, EventArgs e)
{
MyWarningForm warning = new MyWarningForm();//Your warning form
warning.Click += new EventHandler(warning_Click);
warning.ShowDialog(main.ActiveMdiChild);
}
void warning_Click(object sender, EventArgs e)
{
((Form)sender).Close(); //Click on form would close this.
}
}
Following is how I'd implement the classes.
public class CBaseForm : Form
{ public CBaseForm() { this.Text = "Main App"; } }
public class MyWarningForm : CBaseForm
{ public MyWarningForm() { Label lbl = new Label(); lbl.Text = "Warning Form"; this.Controls.Add(lbl); } }
public class MyNotificationForm : CBaseForm
{ public MyNotificationForm() { Label lbl = new Label(); lbl.Text = "Notification Form"; this.Controls.Add(lbl); } }
public class MyMainForm : CBaseForm
{ public MyMainForm() { Label lbl = new Label(); lbl.Text = "Controller Form"; this.Controls.Add(lbl); } }
And you MainForm would start conventionally
Application.Run(new Form3());
Let me know if I dragged your question to 180 degrees!

Categories

Resources