I run a new form
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
}
Then I call into FormMain():
Application.Run(applicationContext);
How can I close FormMain by code?
Here is FormMain:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using EasyTabs;
namespace CefSharp
{
public partial class FormMain : Form
{
public static AppContainer Container = new AppContainer();
public FormMain()
{
InitializeComponent();
Container.Tabs.Add(new EasyTabs.TitleBarTab(Container)
{
Content = new frmTab
{
Text = "New Tab"
}
});
Container.SelectedTabIndex = 0;
TitleBarTabsApplicationContext applicationContext = new TitleBarTabsApplicationContext();
applicationContext.Start(Container);
Application.Run(applicationContext);
this.Hide();
if(Container.ExitOnLastTabClose)
{
this.Close();
}
}
}
}
Ok guys, it's not that simple as i wrote without checking. I figured out solve with threads use. First we need delegate on form:
public delegate void closer();
partial class FormMain {
public closer Closer;
(...)
}
Inside class constructor or in InitializeComponents add Close method to it:
this.Closer += Close;
Create public static FormMain object:
static class Program {
public static FormMain form1;
(...)
}
Then you just run threads with running window and simply (in this case after 5 seconds) close the window:
Program.form1 = new FormMain();
Thread fo = new Thread(() => { Application.Run(Program.form1); });
Thread th = new Thread(() => { Thread.Sleep(5000); Program.form1.Invoke(form1.Closer); });
fo.Start();
th.Start();
You can use two different approaches:
As previously mentionded you can use formMain.Close()
And Application.Exit() to totally close the application.
If you want something more special use Bartek solution. But still, the information you gave us are not enough
Related
(I am very new to C#) I am creating a forms application, and the purpose is to get a string from a Web API, then put that text onto a label. I have successfully gotten the data from the Web, but when I try to update the label, I have no luck.
I have debugged and found that my method inside my class Is executing, but just not setting the label's text. As you can see below, I tried to use this.resultLabel.text = str;. Here's the classes:
Program.cs (not the form cs file)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Http;
using System.Net;
using System.IO;
namespace WebsiteAPITest
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
class PostManager
{
public void setupClient()
{
HttpWebRequest WebReq = (HttpWebRequest)WebRequest.Create(string.Format("https://yakovliam.com/phpApi/csTest.php"));
WebReq.Method = "GET";
HttpWebResponse WebResp = (HttpWebResponse)WebReq.GetResponse();
string respStr;
using (Stream stream = WebResp.GetResponseStream()) //modified from your code since the using statement disposes the stream automatically when done
{
StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8);
respStr = reader.ReadToEnd();
}
MessageBox.Show(respStr);
Form1 form = new Form1();
form.SetResultLabel(respStr);
}
}
}
Actual form class (Form1.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WebsiteAPITest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void GetButton_Click(object sender, EventArgs e)
{
PostManager postManager = new PostManager();
postManager.setupClient();
}
public void SetResultLabel(string str)
{
this.resultLabel.Text = str;
this.resultLabel.Refresh();
}
}
proof of label name:
Inside setupClient you call Form1 form = new Form1(); that creates a second Form1 which you never display, then you call SetResultLabel(respStr) inside this second form you never display, then you leave the method and discard it.
If you want to call SetResultLabel of your calling form, you have to pass the calling form to setupClient:
public void setupClient(Form1 callingForm)
{
...
callingForm.SetResultLabel(respStr);
Then inside your Form1:
postManager.setupClient(this);
It's quite dangerous to pass forms to other methods; a better design is to have the other method return data to your form:
public string setupClient()
{
...
return respStr;
}
And inside Form1:
SetResultLabel(postManager.setupClient());
So I tried to create a new form and reference it...the compiler didn't mind this but it clearly wasn't changing the visibility of my picturebox. this is how I was calling my method found in my form, FROM my c# script.
Form1 updateForm = new Form1();
updateForm.setLights();
It called the method, and seemed like it worked! Until I read a post about instancing forms, and how by creating a "new" instance of Form1, that anything referenced by my updateForm would not change what I would see on my Form1.
So what I need to do is to call the function in setLights() which is in my Form1, and get it to change the visibility of my image on that form, from my C# code. Please see below (i understand the issue of the instancing problem mentioned above, but I left it in so that hopefully it will give better insight into what I am "trying" to do :) ALSO, please keep in mind that setLightCall() is running in a separate thread. Thanks in advance!
This code is also in my main c# script, and is the main function that I use to call my threads
static void Main(string[] args)
{
Thread FormThread = new Thread(FormCall);
FormThread.Start();
Thread setLightThread = new Thread(setLightCall);
setLightThread.Start();
log4net.Config.XmlConfigurator.Configure();
StartModbusSerialRtuSlave();
}
This code is in my main C# script
public void setLightCall(Form1 parent)
{
Form1 updateForm = new Form1();
while(true)
{
updateForm.setLights();
}
}
The below code is in my form1
public void setLights()
{
Input1GreenLight.Visible = false;
}
Here is an example of what I think you are wanting to try. Note the use of Invoking and delegates to be able to access the PictureBox's Visible method. I had to add the System.Windows.Forms Namespace to the Console Application to be able to access the instance of the Form that was created in the FormThread Method, this is assuming that you only have 1 Form in your FormCollection.
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Windows.Forms;
namespace ConsoleApplication59
{
class Program
{
static void Main(string[] args)
{
Thread FormThread = new Thread(FormCall);
FormThread.Start();
Thread.Sleep(2000); //Sleep to allow form to be created
Thread setLightThread = new Thread(setLightCall);
setLightThread.Start(Application.OpenForms[0]); //We can get by with this because just one form
Console.ReadLine();
}
public static void setLightCall(object parent)
{
Form1 updateForm = (Form1)parent;
while (true)
{
updateForm.Invoke(updateForm.setLights, new object[] { false });
}
}
public static void FormCall()
{
Application.Run(new Form1());
}
}
}
Form1
public partial class Form1 : Form
{
public delegate void Lights(bool state);
public Lights setLights;
public Form1()
{
InitializeComponent();
setLights = new Lights(setLightsDelegate);
}
public void setLightsDelegate(bool state)
{
Input1GreenLight.Visible = state;
}
}
I want to create a method which makes my application wait X number of seconds, then continues on down a line of scripts. For example, this is the code that I have so far, after reading many similar help topics:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
methods.WriteTextToScreen(label1, "Hello!");
methods.sleepFor(1);
methods.WriteTextToScreen(label1, "Welcome!");
methods.sleepFor(1);
methods.WriteTextToScreen(label1, "Allo!");
}
public class methods
{
public static int timeSlept;
public static void WriteTextToScreen(Label LabelName, string text)
{
LabelName.Text = text;
}
public static void sleepFor(int seconds)
{
timeSlept = 0;
System.Timers.Timer newTimer = new System.Timers.Timer();
newTimer.Interval = 1000;
newTimer.AutoReset = true;
newTimer.Elapsed += new System.Timers.ElapsedEventHandler(newTimer_Elapsed);
newTimer.Start();
while (timeSlept < seconds)
{
Application.DoEvents();
}
Application.DoEvents();
}
public static void newTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timeSlept = IncreaseTimerValues(ref timeSlept);
Application.DoEvents();
}
public static int IncreaseTimerValues(ref int x)
{
int returnThis = x + 1;
return returnThis;
}
}
}
}
What I want to do is have my program do the methods.WriteTextToScreen(label1, "Hello!")
then wait for 1 second, then continue on in the same fashion. The problem is that the Form I'm displaying the text on doesn't show up at all until it has written "Allo!" onto the screen, so the first time it appears it already says that. Am I doing something wrong, or is there just no way to do this?
The form doesn't show until it has been constructed i.e. all the code in Form1 is run. See here for info on form constructors: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.form.aspx
To fix your problem you could move the writeTextToScreen and sleep code into the forms on load method. See http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onload.aspx
This program is writing numbers from 1 to 5000 in thread, but main form freezes anyway.
Where is an error? Thanks in advance.
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int how, current;
bool job;
Object lockobj = new Object();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Started!");
how = 5000;
current = 0;
job = true;
Thread worker = new Thread(Go);
worker.Name = "1";
worker.Start();
}
private void Go()
{
while (job)
{
if (current < how)
{
lock (lockobj)
{
current++;
}
log(string.Format("Thread #{0}: {1}", Thread.CurrentThread.Name, current));
}
else
{
job = false;
}
}
}
private void log(string text)
{
Action A = new Action(() =>
{
richTextBox1.AppendText(text + System.Environment.NewLine);
});
if (richTextBox1.InvokeRequired)
this.BeginInvoke(A);
else A();
}
}
}
Because most of your work will be spent in
if (richTextBox1.InvokeRequired)
this.BeginInvoke(A);
and while you invoke the form it is locked.
Do some real work, like Thread.Sleep(1000); :-) , instead of current++; and your form will be response between the updates.
It freezes because you are rendering on the textbox very quickly and the GUI doesn't have time to keep in sync. Remember that this rendering happens on the main GUI thread and by calling BeginInvoke to update the textbox so rapidly actually consumes all the resources of this main GUI thread. Try lowering the frequency at which you are logging to avoid this behavior.
I have 2 forms. Form1 (with code below) and Splash (just default form for test).
My problem is that after application run the Splash doesn't hide. Main form is loaded but Splash is still not closed.
The Form1 code:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;
namespace WindowsFormsApplication2
{
class Program : WindowsFormsApplicationBase
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
// Show Form in Single-instance mode
var prg = new Program();
prg.EnableVisualStyles = true;
prg.IsSingleInstance = true;
prg.MinimumSplashScreenDisplayTime = 1000;
prg.SplashScreen = new Splash();
prg.MainForm = new Form1();
prg.Run(args);
}
}
}
You must add reference to Microsoft.VisualBasic to work of this.
Splash form code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Splash : Form
{
public Splash()
{
InitializeComponent();
}
}
}
Thank you in advance for your help.
Ah you're using the Visual Basic Appplication Framework to run the splash screen?
Try this.
This is from a quick Forms application - note that I have left all names and namespace as default, so you may need to change this for your code. The project has two forms only. Form2 is the splash screen. I embedded a background image on it in order to ensure that it popped up okay and that I could differentiate it from Form1.
I added a reference to .NET Microsoft.VisualBasic into my project.
This is from the program.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
new MyApp().Run(args);
}
}
public class MyApp : WindowsFormsApplicationBase
{
protected override void OnCreateSplashScreen()
{
this.SplashScreen = new Form2();
}
protected override void OnCreateMainForm()
{
// Do your initialization here
//...
System.Threading.Thread.Sleep(5000); // Test
// Then create the main form, the splash screen will automatically close
this.MainForm = new Form1();
}
}
}
I know that is different to wht you're using but it seems to work.