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;
}
}
Related
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
I have made a class, I make an instance of. In said instance I have these lines of code to show and close the splashscreen.
// Open (show)
public void ShowSplashScreen(bool autoClose = false)
{
splashscreen.Show(autoClose, true);
}
// Close (don't show)
public void CloseSplashScreen()
{
splashscreen.Close(TimeSpan.FromSeconds(0.3));
}
It shows up fine, but never closes, just stays there.
This is the documentation of splashscreen Close: https://learn.microsoft.com/en-us/dotnet/api/system.windows.splashscreen.close?view=netframework-4.8
[System.Security.SecurityCritical]
public void Close (TimeSpan fadeoutDuration);
Note: I am using the show method with the parameters AutoClose set to false, and TopMost set to true, this makes it not auto close as I want to close it programmatically and not subscribe to existing events.
I am running the lines of code from a Console (.NET framework) application for testing purposes before implementing it into my UI fully.
What I have tried:
Debugging and even trying to call show again before calling close.
It is definitely something going wrong with the class, as calling the class and directly manipulating the property works:
ClassSplashScreen rss = new ClassSplashScreen();
rss.splashscreen.Show(false);
rss.splashscreen.Close(TimeSpan.FromSeconds(1));
My best guess is something is hanging the UI and freezing it? But I am unsure what to do about it.
Code to run to test this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace NamespaceName
{
public class StackOverFlowCode
{
static void Main(string[] args)
{
ClassSplashScreen screen = new ClassSplashScreen();
screen.ShowSplashScreen();
screen.CloseSplashScreen();
}
}
public class ClassSplashScreen
{
public SplashScreen splashscreen { get; set; }
public ClassSplashScreen()
{
splashscreen = new SplashScreen("Resource Image Link");
}
public void ChangeSplashResource(SplashScreen resource)
{
splashscreen = resource;
}
public void ShowSplashScreen(bool autoClose = false)
{
splashscreen.Show(autoClose, true);
}
public void CloseSplashScreen()
{
splashscreen.Close(TimeSpan.FromSeconds(1));
}
}
}
The SplashScreen relies on a dispatcher but there is no one in a console application by default. If you create a System.Windows.Application, it should work as expected:
public class StackOverFlowCode
{
[STAThread]
static void Main(string[] args)
{
Application app = new Application();
app.Startup += (s, e) =>
{
ClassSplashScreen screen = new ClassSplashScreen();
screen.ShowSplashScreen();
screen.CloseSplashScreen();
};
app.Run();
}
}
public class ClassSplashScreen
{
private readonly SplashScreen splashscreen;
public ClassSplashScreen() => splashscreen = new SplashScreen("Resource Image Link");
public void ShowSplashScreen() => splashscreen.Show(false);
public void CloseSplashScreen() => splashscreen.Close(TimeSpan.FromSeconds(1));
}
I'm stuck in declaring a variable with a trigger. This trigger is fired whenever the value of the variable changes and the trigger mechanism is supposed to alter the value of another variable.
Below code compiles fine but throws NullReferenceException (screenshot after exception).
file: Program.cs
using System;
using System.Windows.Forms;
namespace test {
class Program {
public static Active active = new Active();
public static FormMain formMain = new FormMain();
[STAThread]
static void Main() {
Application.Run(formMain);
}
}
}
file: DataStruct.cs
namespace test {
public class Active {
public string UserName {
get {
return (Program.formMain.labelUserName.Text);
}
set {
Program.formMain.labelUserName.Text = value;
}
}
}
}
file FormMain.cs
using System;
using System.Windows.Forms;
namespace test {
class FormMain : Form {
public Label labelUserName = new Label();
public FormMain() {
this.Controls.Add(labelUserName);
Program.active.UserName = "User Name";
}
}
}
It's because when you are in the FormMain constructor, the static variable Program.formMain has not been initialized yet, because you are creating the FormMain object which with you want to initialize Program.formMain.
Update labelUserName directly instead.
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();
}
I have the following C# code:
using System;
using System.Windows.Forms;
namespace WinFormErrorExample
{
public partial class Form1 : Form
{
public static Form1 Instance;
public Form1()
{
Instance = this;
InitializeComponent();
}
public void ChangeLabel1Text(String msg)
{
if (InvokeRequired)
Invoke(new Action<String>(m => label1.Text = m), new object[] {msg});
else
label1.Text = msg;
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
Instance.ChangeLabel1Text("cool");
}
}
}
}
When i'm calling the Instance.ChangeLabel1Text("cool"); nothing is happening in the GUI.
This is a small program i constructed to show my problem in a larger program.
Why is the GUI not being updated?
The call to
Application.Run(new Form1());
is blocking your application until the Form1 closes. So your subsequent line is not executed until you try to close
Of course, if you just want to test the functionality of the Instance call then remove that line after the Application.Run. Instead you need to create a separate thread that tries to call that method on the Form1 current instance
The Application.Run(new Form1()); method call performs running a standard application message loop on the current thread. So, this line Instance.ChangeLabel1Text("cool"); will be executed when the application is closed.
Why not change the text of the label inside the constructor? No static variables needed.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
ChangeLabel1Text("Hello!");
}
}
This would do,
First set the text to textbox control and then Run()
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 form = new Form1();
form.Controls["ChangeLabel1Text"].Text = "cool";
Application.Run(form);