Good morning,
I have several questions but I am not sure which is the important one to ask so I'll first state my overall problem. I can't close my Winform App. I have searched and found many answers but they either don't work, I don't understand or both.
If I do all my work and then call Application.Exit the form never closes. Same results if I put this.Close. However if I place a button on the form and call Application.Exit it closes the form.
I obviously do not understand the flow, I hope it is clear to someone what I am trying to do. As a non-programmer I have been piecing this project together for a few months and this is my last step - Close the form after work is complete if it was run from command line with arguments. I would try longer to work it out but my Visual Studio trial runs out this week so I turn to the experts :)
Thank you,
Todd
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ProgramCSToormTest
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(String[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//add if
if (args.Length == 0)
{
Application.Run(new Form1("Form"));
}
else
{
Application.Run(new Form1(args[0]));
}
}
}
}
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 ProgramCSToormTest
{
public partial class Form1 : Form
{
string CLArg1;
string ReturnText;
public Form1(string Arg1)
{
InitializeComponent();
if (Arg1 != null)
{
CLArg1 = Arg1;
textBox1.Text = Display(CLArg1);
//button1.Enabled = false;
}
else
{
textBox1.Text = "click button to start";
}
Application.Exit(); //This seems to be ignored
}
public void button1_Click(object sender, EventArgs e)
{
CLArg1 = null;
textBox1.Text = Display("Hello World");
Application.Exit();
}
public string Display(string DisplayText)
{
if (CLArg1 != null)
{
ReturnText = CLArg1;
return(ReturnText);
}
else
{
ReturnText = DisplayText;
return(ReturnText);
}
}
}
}
See this question. Application.Close() only works if an application has been created. This is done by calling Application.Run(). Now. in your code you call Application.Exit() from the constructor of your form. Which is executed before the Application.Run() that is needed to create the application.
To fix this, either wait until after Application.Run(). Or, if you want to quit the application in the constructor use Environment.Exit(int statusCode). When using Environment.Exit(int statusCode) keep this in mind though.
You can't close the Application when the Form is Loading from the Program class. Try calling the Exit method after Loading the Form:
private void Form1_Load(object sender, EventArgs e)
{
if (CLArg1 != String.Empty)
Application.Exit();
}
Related
I need your help with something I am dealing with. I am new to c# and I am creating a winforms application with multiple forms in it. There's a piece of code that needs to be present on all forms but since I don't want to just copy and paste it in every form, I created a class that stores that code and then I only want to call that class.
My global code that needs to be repeated is as follows,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Delfoi_Tourist_Guide
{
public class Login_User
{
public void CheckStatus()
{
DialogResult dialogResult = MessageBox.Show("Do your want to disconnect?;", "Disconnect", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
Welcome form1 = new Welcome();
form1.Show();
this.Visible = false;
}
else if (dialogResult == DialogResult.No)
{
MessageBox.Show("Συνεχίστε την περιήγηση σας!!!");
}
}
}
}
I am also providing you a portion of code from another form in which I am applying my global code
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Login_User loginUser = new Login_User();
loginUser.CheckStatus();
}
My problem is that I can't transfer the "Visible" method from my global class to the other classes. I suppose this happens because my global class isn't attached to a winform. It's just a piece of code that's been used globally. What am I doing wrong???
try this
public static void CheckStatus(System.Windows.Form currentForm)
{
.....
currentForm.Visible = false;
`````
}
and call it
.....
Login_User.CheckStatus(this);
.....
Your problem occurs because the keyword "this" applies as property to the form, not the class. In your case you have to pass an instance of the form as parameter in your CheckStatus method. But since you want this to apply in all of your forms, you have to type the word "Form". Below I am providing you the answer,
Your Global Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Delfoi_Tourist_Guide
{
public static class Login_User
{
public static void CheckStatus(Form currentForm)
{
DialogResult dialogResult = MessageBox.Show("Do your want to disconnect?;", "Disconnect", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
Welcome form1 = new Welcome();
form1.Show();
currentForm.Visible = false;
}
else if (dialogResult == DialogResult.No)
{
MessageBox.Show("Συνεχίστε την περιήγηση σας!!!");
}
}
}
}
and then you have to apply your global code to your desired forms, as follows.
Please note that you have to set the whole class as static in order for it, to work.
Apply Global Code To Forms
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Login_User.CheckStatus(this);
}
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
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'm somewhat new to C# on the whole and I'm developing a small program to render my backlog of CAD stuff when I'm idle. I'm using the MouseKeyboardActivityMonitor library found here: https://globalmousekeyhook.codeplex.com/ but having major problems such as input frozen upon the launch of my program and from there out no user input is detected by the hooks. I am using Windows 8.1 x64 and compiling both the DLL and my own executable towards .NET 4.0
Note: I am using Version 3 of the project
This is my code (just a small test of the hooks):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MouseKeyboardActivityMonitor;
using MouseKeyboardActivityMonitor.WinApi;
using System.Windows.Forms;
namespace HookTest1
{
class Program
{
static MouseHookListener mouseListener;
static KeyboardHookListener keyListener;
static void Main(string[] args)
{
Activate();
while (true)
{
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
}
}
private static void OnUserActivity()
{
Console.Write("UserAct");
}
private static void Activate()
{
mouseListener = new MouseHookListener(new GlobalHooker());
mouseListener.Enabled = true;
mouseListener.MouseDown += OnMouseActivity;
mouseListener.MouseMove += OnMouseActivity;
mouseListener.MouseWheel += OnMouseActivity;
keyListener = new KeyboardHookListener(new GlobalHooker());
mouseListener.Enabled = true;
keyListener.KeyDown += OnKeyActivity;
}
private static void OnMouseActivity(Object sender, System.Windows.Forms.MouseEventArgs e)
{
OnUserActivity();
}
private static void OnKeyActivity(Object sender, System.Windows.Forms.KeyEventArgs e)
{
OnUserActivity();
}
}
}
Thanks for any and all help!
You may have added this somewhere and just removed it in your sample... but have you called
Application.Run();
in Main()? As I understand it, you're attempting to hook window events without a message loop going. Application.Run will get it running.
Wondering if anyone could help with my problem. Below is the code, and after the code an explination of where the exception is thrown.
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.Web;
using WatiN.Core;
using System.Threading;
using System.IO;
namespace WindowsFormsApplication1
{
public partial class Form1 : System.Windows.Forms.Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(createApplications);
Settings.AutoStartDialogWatcher = false;
t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();
}
private void createApplications()
{
createApp("username", "password", "Test App", "This is just a test description", "http:/mysite.com");
}
private void createApp(String username, String password, String appName, String description, String appUrl) {
var currentBrowser = new IE("http://mysite.com/login/php");
currentBrowser.TextField(Find.ById("username")).TypeText(username);
currentBrowser.TextField(Find.ById("password")).TypeText(password);
currentBrowser.Button(Find.ById("submit")).Click();
currentBrowser.GoTo("http://mysite.com/createmusicapp.php");
currentBrowser.TextField(Find.ById("application_name")).TypeText(appName);
currentBrowser.TextField(Find.ById("application_description")).TypeText(description);
currentBrowser.TextField(Find.ById("application_url")).TypeText(appUrl);
currentBrowser.RadioButton(Find.ById("client_application_desktop_1")).Click();
currentBrowser.RadioButton(Find.ById("client_application_is_writable_1")).Click();
WatiN.Core.Image captchaImage = currentBrowser.Div(Find.ById("recaptcha_image")).Image(Find.ByStyle("display", "block"));
Form2 captcha = new Form2(captchaImage.Src);
captcha.ShowDialog();
}
}
}
The exception is thrown on this line:
currentBrowser.TextField(Find.ById("username")).TypeText(username);
BUT, it's thrown when it gets to this line:
captcha.ShowDialog();
It logs in, and fills in the app details and Form2 loads fine, but once loaded, after around 2-3 seconds the exception happens. I am wondering if it's anything to do with the threads? But I wouldn't know how to solve it if it was.
The complete exception thrown is:
The object invoked has disconnected from its clients. (Exception from HRESULT: 0x80010108 (RPC_E_DISCONNECTED))
Got! Because of your thread, in windows development, microsoft doesn't suggest access UI by thread. If you really need, use mutex to avoid two or more threads accessing the same UI elemnt at the same time.