Access WinForm in OnFocusChanged() - c#

I have created a list "exe" and new WinForm in Main(). I need to access both in OnFocusChanged(). The idea is that a hidden WinForm is created, and when "firefox" has focus, the WinForm will be displayed. My WinForm has a method, update(), that is used to show the WinForm. If I call "form.update()" in Main, the WinForm appears, however I cannot access it in OnFocusChanged().
How can I access the list and WinForm object in OnFocusChanged()? Thanks.
namespace WinForm1
{
static class Program
{
[STAThread]
static void Main()
{
List<string> exe = new List<string>();
Form1 form = new Form1();
Application.Run(form);
}
static private void OnFocusChanged(object sender, AutomationFocusChangedEventArgs e)
{
string program = "firefox";
if(exe.Any(program.Contains)
{
form.update(true);
}
}
}
}

exe can't be accessed from the OnFocusChanged event handler because it's local in scope to the Main method.
You need to make the list variable static and bring it outside of the method
...
static List<string> exe = new List<string>();
[STAThread]
static void Main()
...

you can use System.Diagnostics.Process for archive to this idea
first get list of all process and check process name
Process[] processes = System.Diagnostics.Process.GetProcesses();
if (processes.Any(c => c.ProcessName == "firefox"))
{
//your update code
}

Related

Track dynamic form automcatically in winforms

I have an application having 2 forms that opens on application start and 3rd form is getting added on runtime.
I have an another class library that currently monitors the activities of a single form. The below code snippet is of application :-
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form[] f = new Form[2];
f[0] = new Form1();
f[1] = new Form2();
f[0].Show();
AppContext nvca = new AppContext(new Form1(), new Form2());
Application.Run(nvca);
}
AppContext class is in class library where I am trying to catch all the forms of the application whether it is static or comes at runtime :-
public class AppContext:ApplicationContext
{
public static Form[] AvailForms = null;
public AppContext(params Form[] forms)
{
AvailForms = forms;
UAction ua = new UAction();
foreach (Form f in forms)
{
for (int i = 0; i < f.Controls.Count; i++)
{
ua.setClickHandlerAsync(f.Controls[i]);
}
}
}
public void setClickHandlerAsync(Control item)
{
//Have to recursively get all the element to wrap the click listener.
item.MouseClick += ClickHandlerAsync;
}
private async void ClickHandlerAsync(object sender, MouseEventArgs e)
{
Console.WriteLine("Click Handler called");
}
}
I am searching for a way through which I can track all the forms that are either already added in application or added at runtime.
I have tried through ApplicationContext, but it failed to capture the win events like click, text change, form events even though all the event handlers has been set properly on it.
Any help would be appreciated.

C# Static Form Added to Project?

I want to create a custom message box for a program so I added a windows form item. I would like it to behave like MessageBox in that it is static and I just call MessageBox.Show(a, b, c, ...). In the forms designer, however, I don't see how I can make it static. Can I just add static to the code? Is there a property setting I'm missing in the designer mode?
Thanks!
MessageBox is not a static class, the Show method however is. Make Show static, in code. E.g.
public class MyMessageBox : Form
{
public static int MyShow()
{
// create instance of your custom message box form
// show it
// return result
}
}
It is a regular class with one method as static which instantiate new instance and act.
public class MyMessageBox
{
public static MyResult Show(params)
{
var myMessageBox = new MyMessageBox();
myMessageBox.Message = params ...
return myMessageBox.ShowDialog();
}
}
Add a static method to your form that displays itself and returns a DialogResult:
public partial class MyMessageBoxForm : Form {
public static DialogResult Show(string message) {
using (MyMessageBoxForm form = new MyMessageBoxForm(message)) {
return form.ShowDialog();
}
private MyMessageBoxForm(string message) {
// do something with message
}
}
If you want create static Form1 for access to it without object reference, you can change Program.cs:
public class Program
{
public static Form1 YourForm;
[STAThread]
static void Main(string[] args)
{
using (Form1 mainForm = new Form1())
{
YourForm = mainForm;
Application.Run(mainForm);
}
YourForm = null;
}
}
and call Form1 class methods from any place of your program:
Program.YouForm.DoAnything();
Do not forget to call Invoke for access from other threads.

c# register commandline argument don't start new instance

Application c:\pinkPanther.exe is running and it is application i wrote in c#.
Some other application starts c:\pinkPanther.exe purpleAligator greenGazelle OrangeOrangutan and i would like not to start new instance of c:\pinkPanther.exe with these arguments, but to currently running c:\pinkPanther.exe register it and react to it somehow.
How to do it?
EDIT!!!: i'm very sorry about pinkPanther.exe and ruzovyJeliman.exe that caused the confusion - i translated question from my native language and missed it :(
This is assuming your application is a WinForms app, as that will make it easier to keep it open. This is a very simple example, but it will show you the basics:
Add a reference to Microsoft.VisualBasic.
Create an Application class inheriting from WindowsFormsApplicationBase. This base class contains built-in mechanisms for creating a single-instance application and responding to repeated calls on the commandline with new arguments:
using Microsoft.VisualBasic.ApplicationServices;
//omitted namespace
public class MyApp : WindowsFormsApplicationBase {
private static MyApp _myapp;
public static void Run( Form startupform ) {
_myapp = new MyApp( startupform );
_myapp.StartupNextInstance += new Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventHandler( _myapp_StartupNextInstance );
_myapp.Run( Environment.GetCommandLineArgs() );
}
static void _myapp_StartupNextInstance( object sender, Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e ) {
//e.CommandLine contains the new commandline arguments
// this is where you do what you want with the new commandline arguments
// if you want it the window to come to the front:
e.BringToForeground = true;
}
private MyApp( Form mainform ) {
this.IsSingleInstance = true;
this.MainForm = mainform;
}
}
All you have to change in Main() is call Run() on your new class rather than Application.Run():
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault( false );
MyApp.Run( new MyMainForm() );
}
}
WindowsFormsApplicationBase has some other capabilities you can explore, as well.
To communicate with the other instance of the application, you need some sort of inter-process communication. Apparently, WCF is the recommended form of IPC in .Net. You can do that with code like this (using WPF, but WinForms would be similar):
[ServiceContract]
public interface ISingletonProgram
{
[OperationContract]
void CallWithArguments(string[] args);
}
class SingletonProgram : ISingletonProgram
{
public void CallWithArguments(string[] args)
{
// handle the arguments somehow
}
}
public partial class App : Application
{
private readonly Mutex m_mutex;
private ServiceHost m_serviceHost;
private static string EndpointUri =
"net.pipe://localhost/RuzovyJeliman/singletonProgram";
public App()
{
// find out whether other instance exists
bool createdNew;
m_mutex = new Mutex(true, "RůžovýJeliman", out createdNew);
if (!createdNew)
{
// other instance exists, call it and exit
CallService();
Shutdown();
return;
}
// other instance does not exist
// start the service to accept calls and show UI
StartService();
// show the main window here
// you can also process this instance's command line arguments
}
private static void CallService()
{
var factory = new ChannelFactory<ISingletonProgram>(
new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), EndpointUri);
var singletonProgram = factory.CreateChannel();
singletonProgram.CallWithArguments(Environment.GetCommandLineArgs());
}
private void StartService()
{
m_serviceHost = new ServiceHost(typeof(SingletonProgram));
m_serviceHost.AddServiceEndpoint(
typeof(ISingletonProgram),
new NetNamedPipeBinding(NetNamedPipeSecurityMode.None),
EndpointUri);
m_serviceHost.Open();
}
protected override void OnExit(ExitEventArgs e)
{
if (m_serviceHost != null)
m_serviceHost.Close();
m_mutex.Dispose();
base.OnExit(e);
}
}

How to make an application HAVE a form but not BE a form?

I want my C# .NET application to have a form but not be a form.
When I normally startup a windows forms application, it's like the form is the master of everything else that follows:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
Instead, I'd like to startup my program, which is then able to show a form, but is not a form itself. In other words, I don't want the master controller of the applicatin being the form, I'd like it instead to be a non-visual logical container, which has the capability to show forms, but isn't a form itself.
I'm not sure if I'm posing the question in a clear way, but I'd like to hear thoughts.
You can just use Application.Run() to get a message-loop running. But you'll need to do something to listen for input - perhaps a systray etc.
You could use an ApplicationContext instead. That gets you the necessary message loop that will keep a form alive, once you decide to create one. Make your Program class look similar to this:
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
AppContext = new ApplicationContext();
Application.Run(AppContext);
}
public static void Quit() {
AppContext.ExitThread();
}
public static ApplicationContext AppContext;
}
Beware that the app will not close automatically when you close the last window. Calling ExitThread explicitly is required.
It's fairly common to create a separate Bootstrapper component which you could move the display of the main form to:
using System;
using System.Windows.Forms;
namespace Example
{
internal static class Program
{
[STAThread]
private static void Main()
{
new Bootstrapper().Run();
}
}
public class Bootstrapper
{
public void Run()
{
// [Application initialization here]
ShowView();
}
private static void ShowView()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
As Mark_Gravell alluded to, Application.Run() blocks until the Form1 closes. You can open your forms on a separate thread, but that thread will be basically consumed by the form. And when you want the exe to exit, you'll have to manually kill each thread. See the following code. (It doesn't create a console window. I got this by creating a default WinForms app and changing the Program class)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication1
{
static class Program
{
static List<Thread> threads = new List<Thread>();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
for (int i = 0; i < 10; i++)
{
StartThread();
System.Threading.Thread.Sleep(500);
}
//kill each thread so the app will exit, otherwise, the app won't close
//until all forms are manually closed...
threads.ForEach(t => t.Abort());
}
static void StartThread()
{
Thread t = new Thread(ShowForm);
threads.Add(t);
t.Start();
}
static void ShowForm()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Create the app as a console app and then call Application.Run as Marc said when you need a form.
You can also create your own ApplicationContext
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(AppController.Instance);
}
And within AppController.cs
namespace MyApplication
{
public class AppController
{
static AppController _AppController;
public LoginWIndow LoginWIndow;
//Constructor
public void AppController()
{
//Do what you will here, Start login form, bind events, w.e :)
if(true) //Your check
{
ShowLoginWindow();
}
}
public void ShowLoginWindow()
{
LoginWIndow = new LoginWIndow();
LoginWIndow.ClosedForm += new FormClosedEventHander(ExitApplication);
LoginWIndow.Show();
}
public void ExitApplication(Object Sender, FormClosedEventArgs Args)
{
//Some shutdown login Logic, then
Application.Exit();
}
static AppController Instance
{
get
{
if(_AppController == null)
{
_AppController = new AppController();
}
return _AppController;
}
}
}
}

How do I modify a form's text box from a separate class?

I am trying to create a form where I can update text in a text box without requiring interaction from the user. Right now I am trying to create a method in my form's class that updates the TextBox.Text field. Outside of the class I am not able to access the function.
Right now I am trying
static void Main()
{
Form status = new Window();
Application.Run(status);
status.UpdateTextBox("NewText");
}
My form class looks like (from the designer)
public partial class Window : Form
{
public Window()
{
InitializeComponent();
}
public void UpdateTextBox(string text)
{
textBox1.Text = text;
}
}
I have also tried making the Textbox a public property like this.
public string DisplayedText
{
get
{
return textbox1.Text;
}
set
{
textbox1.Text = value;
}
}
I am trying to edit the field during runtime. Is this possible?
You can access the function, but if you look at the code, there is a problem:
static void Main()
{
Form status = new Window();
Application.Run(status); // Blocks here!
status.UpdateTextBox("NewText");
}
When you call Application.Run(), it will not return control to your program until the status form has closed. At that point, setting the status is too late...
You can set it before you run, but after you've constructed:
static void Main()
{
Form status = new Window();
status.UpdateTextBox("NewText");
Application.Run(status);
}
It's this code...the Application.Run will block, status.UpdateTextBox isn't going to execute until you close the form.
static void Main()
{
Form status = new Window();
Application.Run(status);
status.UpdateTextBox("NewText");
}

Categories

Resources