i just used this snippet for creating a tray application with two buttons (settings and exit):
using System;
using System.Windows.Forms;
using System.Drawing;
using WindowsFormsApplication1;
//*****************************************************************************
abstract class NotIco
{
private static NotifyIcon notico;
//==========================================================================
public static void Main(string[] astrArg)
{
ContextMenu cm;
MenuItem miCurr;
cm = new ContextMenu();
miCurr = new MenuItem();
miCurr.Index = 0;
miCurr.Text = "&Settings";
miCurr.Click += new System.EventHandler(SettingsClick);
cm.MenuItems.Add(miCurr);
miCurr = new MenuItem();
miCurr.Index = 1;
miCurr.Text = "Beenden";
miCurr.Click += new System.EventHandler(ExitClick);
cm.MenuItems.Add(miCurr);
notico = new NotifyIcon();
notico.Icon = new Icon("tanss.ico");
notico.Text = "TANSS Busylight Connector";
notico.Visible = true;
notico.ContextMenu = cm;
notico.DoubleClick += new EventHandler(NotifyIconDoubleClick);
Application.Run();
}
//==========================================================================
protected static void ExitClick(Object sender, EventArgs e)
{
notico.Dispose();
Application.Exit();
}
//==========================================================================
protected static void SettingsClick(Object sender, EventArgs e)
{
/// <summary>
/// Der Haupteinstiegspunkt für die Anwendung.
/// </summary>
// This should open the "Settings"-Popup, containing 3 textboxes and a button to save them to xml.
}
//==========================================================================
protected static void NotifyIconDoubleClick(Object sender, EventArgs e)
{
// ...
}
}
Now i want to open a new Form as a Popup containing 3 textboxes to write some values in and a button to save them.
In the background, a never ending loop is requesting a url and parsing a value out of a json.
could you help me opening the new form (its not made yet, i just need it to open first :/)
and where do i embedd my background loop-code?
thanks so much!
It is as simple as
MyForm form1 = new MyForm();
form1.Show();
You have to create a new form object and show it on screen.
and, if you want to, you can set all others properties
form1.Location = new Point(20, 20);
form1.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
form1.MaximizeBox = true;
form1.ControlBox = true;
......
I think is better (easier actually) to create the form from the designer and avoid the creation of every textbox and everything from code.
Related
My application has a need to hide an initial form and open any one of four new forms. I can hide the initial and open the selected form with:
private void btn_Option1_Click(object sender, EventArgs e){
Visible = false;
Application x = new Application();
x.show();
}
My question is how to close the second form and reopen the original form? Or I suppose it would be plausible to close each form on each form opening, but that seems wasteful.
It sounds like you need the FormClosed event.
When you create instances of the new Form from your initial Form you can subscribe to the new Form's FormClosed event and show your initial Form from the handler.
This way, whenever one of your new Forms close, the event handler will fire and your initial Form will become visible again.
// This is a method that you would add to your initial Form.
private void SubForm_Closed(object sender, FormClosedEventArgs e)
{
Visible = true;
}
private void btn_Option1_Click(object sender, EventArgs e)
{
Visible = false;
Application x = new Application();
x.FormClosed += SubForm_Closed;
x.show();
}
If you use Hide(), the form "essentially" disappears, you won't even see it in the taskbar. Then you can open by Showing it from one of the subsequent forms. I threw the below together and only tested it quickly so YMMV, you'll need to clean it up and make it work for you, but it should illustrate the point. Create a Windows Form Application. Call it "WindowsFormsApp2" since that's what I used. Paste in the below code:
using System;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Form2 form2;
Form3 form3;
Form4 form4;
Form5 form5;
private void button1_Click_1(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
form2 = new Form2(this);
form2.Show();
}
if (checkBox2.Checked)
{
form3 = new Form3(this);
form3.Show();
}
if (checkBox3.Checked)
{
form4 = new Form4(this);
form4.Show();
}
if (checkBox4.Checked)
{
form5 = new Form5(this);
form5.Show();
}
this.Hide();
}
}
}
Paste the below code into the Form1 designer:
namespace WindowsFormsApp2
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.checkBox2 = new System.Windows.Forms.CheckBox();
this.checkBox3 = new System.Windows.Forms.CheckBox();
this.checkBox4 = new System.Windows.Forms.CheckBox();
this.button1 = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.checkBox4);
this.groupBox1.Controls.Add(this.checkBox3);
this.groupBox1.Controls.Add(this.checkBox2);
this.groupBox1.Controls.Add(this.checkBox1);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(274, 73);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Forms";
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Location = new System.Drawing.Point(17, 32);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(55, 17);
this.checkBox1.TabIndex = 0;
this.checkBox1.Text = "Form2";
this.checkBox1.UseVisualStyleBackColor = true;
//
// checkBox2
//
this.checkBox2.AutoSize = true;
this.checkBox2.Location = new System.Drawing.Point(78, 32);
this.checkBox2.Name = "checkBox2";
this.checkBox2.Size = new System.Drawing.Size(55, 17);
this.checkBox2.TabIndex = 1;
this.checkBox2.Text = "Form3";
this.checkBox2.UseVisualStyleBackColor = true;
//
// checkBox3
//
this.checkBox3.AutoSize = true;
this.checkBox3.Location = new System.Drawing.Point(139, 32);
this.checkBox3.Name = "checkBox3";
this.checkBox3.Size = new System.Drawing.Size(55, 17);
this.checkBox3.TabIndex = 2;
this.checkBox3.Text = "Form4";
this.checkBox3.UseVisualStyleBackColor = true;
//
// checkBox4
//
this.checkBox4.AutoSize = true;
this.checkBox4.Location = new System.Drawing.Point(200, 32);
this.checkBox4.Name = "checkBox4";
this.checkBox4.Size = new System.Drawing.Size(55, 17);
this.checkBox4.TabIndex = 3;
this.checkBox4.Text = "Form5";
this.checkBox4.UseVisualStyleBackColor = true;
//
// button1
//
this.button1.Location = new System.Drawing.Point(12, 91);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(199, 23);
this.button1.TabIndex = 1;
this.button1.Text = "Open Selected Forms";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click_1);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.button1);
this.Controls.Add(this.groupBox1);
this.Name = "Form1";
this.Text = "Form1";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.CheckBox checkBox4;
private System.Windows.Forms.CheckBox checkBox3;
private System.Windows.Forms.CheckBox checkBox2;
private System.Windows.Forms.CheckBox checkBox1;
private System.Windows.Forms.Button button1;
}
}
Add 4 Windows Forms: Form2, Form3, Form4 and Form5.
Paste in the below code to each and just change the form name on each to it's correct name (Form3, Form4, Form5):
using System;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form2 : Form
{
public Form2(Form1 Form1In)
{
InitializeComponent();
form1 = Form1In;
}
Form1 form1;
private void button1_Click(object sender, EventArgs e)
{
form1.Show();
}
}
}
Finally paste in the below code to the designer of each form and change the name for the forms other than Form2 to their respective name:
namespace WindowsFormsApp2
{
partial class Form2
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(22, 21);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(104, 23);
this.button1.TabIndex = 0;
this.button1.Text = "Show Form1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form2
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.button1);
this.Name = "Form2";
this.Text = "Form2";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
}
}
Then run it.
Here's a shiny new wheel. It concentrates all the logic in a Manager class.
A SubForm Base Class
First, we'll create a base class for all the sub forms. This way, you don't need to put the form switching logic into every form.
Create a new Form in your project, name it ShowHideFormBase , change to the "View Code" view and change the boilerplate so it looks like this:
public partial class ShowHideFormBase : Form
{
public ShowHideFormManager Manager { get; private set; }
public ShowHideFormBase()
{
Manager = null;
InitializeComponent();
}
public void SetManager (ShowHideFormManager manager)
{
Manager = manager;
}
}
We'll create the Manager class in a bit
I really wanted to have a constructor on ShowHideFormBase that took a ShowHideFormManager instance as a parameter. The Windows Forms designer really doesn't like having forms base classes with non-default constructors. Such is life.
In the designer for this form, show the properties of the form, and change to the Events view (the lightening bolt icon). Double-click on the FormClosing event. That will add this code for a ShowHideWindowBase_FormClosing handler to your base class. Change it so it looks like this.
private void ShowHideWindowBase_FormClosing(object sender, FormClosingEventArgs e)
{
Debug.Assert(Manager != null); //Make sure that SetManager was called
e.Cancel = true;
Manager.HideAll();
}
The e.Cancel=true; says "I know someone tried to close this form, don't let it close". Instead, we'll cause all the sub forms to be hidden including this one.
That class is done. Now let's do the manager class.
The Manager
Create a new class in your project name ShowHideFormManager. Use this code:
public class ShowHideFormManager
{
private Dictionary<string, ShowHideFormBase> _forms = new Dictionary<string, ShowHideFormBase>();
private Form _mainForm;
public ShowHideFormManager(Form mainForm)
{
_mainForm = mainForm;
}
// This will add a sub form to be managed
public void Add(string windowsName, ShowHideFormBase form)
{
_forms.Add(windowsName, form);
}
// This will hide all managed sub forms and show the main form
public void HideAll()
{
_mainForm.Show();
foreach (var formPair in _forms)
{
formPair.Value.Hide();
}
}
// this will hide the main form and show the named sub form
public void Show(string formToShowName)
{
_mainForm.Hide();
foreach (var formPair in _forms)
{
if (formPair.Key != formToShowName)
{
formPair.Value.Hide();
}
}
if (_forms.TryGetValue(formToShowName, out var formToShow))
{
formToShow.Show();
}
}
}
Note that the shiny new wheel is up to about 75 or 80 lines of code.
The Application's Main Form
I'm assuming that you have a form named Form1 in your application (the one that gets created when you create your application.
Add this private field:
private ShowHideFormManager _manager = null;
and this public method:
public void SetManager(ShowHideFormManager manager)
{
_manager = manager;
}
Drop three buttons on the main form, set their Name properties to "SubForm1Btn", "SubForm2Btn", and "SubForm3Btn" and set the Text properties to something useful. In the click handlers do something like this for each button:
private void SubForm1Btn_Click(object sender, EventArgs e)
{
_manager.Show("Sub Form 1");
}
changing the numbers, obviously
The Sub Forms
Now create three new forms in your project. Name the classes SubForm1, SubForm2 and SubForm3.
Note, I create three sub forms, not 4 - creating the fourth would be easy
Open the code view for each form. The only change we are going to make to these three forms is to change the class declaration and constructor to:
public partial class SubForm1 : ShowHideFormBase
{
public SubForm1(ShowHideFormManager manager)
{
InitializeComponent();
SetManager(manager);
}
}
For all three forms: 1, 2, and 3, obviously
This changes the base class from Form to ShowHideFormBase. It also makes it so each of these forms must be initialized with a ShowHideFormManager instance, and we call SetManager (which is a base class method) to initialize the form with the manager.
Finally, changes to Program.cs
Finally, we'll make some minor changes to the Main method in Program.cs. These changes:
Create the Manager
Instantiate the main form as well as the three sub forms.
And call the normal Application.Run method
Here's the new Main method:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var mainForm = new Form1();
var manager = new ShowHideFormManager(mainForm);
mainForm.SetManager(manager);
var subForm1 = new SubForm1(manager);
var subForm2 = new SubForm2(manager);
var subForm3 = new SubForm3(manager);
manager.Add("Sub Form 1", subForm1);
manager.Add("Sub Form 2", subForm2);
manager.Add("Sub Form 3", subForm3);
Application.Run(mainForm);
}
Important: The strings you use in the manager.Add call (e.g. "Sub Form 1") must exactly match the string you pass in each of the calls to _manager.Show("Sub Form 1"); in the button handlers. When I finished this, I decided that I should have used an enum, but everything was working.
How it Works
Press F5 and the main form (with three buttons on it) should pop up. Press any of the buttons and the corresponding form will pop up (and the main form will hide). Close the sub form, and the main form will re-open letting you press that button again or another button.
While you are looking at this, notice that there are almost no changes to the Main Form or the Sub Forms. The magic is all in the form base class and the manager class. You can do whatever you want with any of the forms (as long as you get those minimal changes in the right places.
When I'm trying to add a drop-down menu to my form in a wizard, it gives following error.
Here are the code lines I have written for drop-down menu.
dropDownMenu1 = new ToolStripDropDownMenu();
dropDownMenu1.Location = new System.Drawing.Point(90, 45);
dropDownMenu1.Size = new System.Drawing.Size(70, 20);
this.Controls.Add(dropDownMenu1);
Update
This solution didn't fix my problem. I have used following code already. But still gives the same error.
UserInputForm inputForm= new UserInputForm();
inputForm.TopLevel = false;
inputForm.ShowDialog();
On the basis of your code,you also have to set Items for dropDownMenu1 and set it to display after you set dropDownMenu1.TopLevel = false;. You could try to refer to the following code.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
ToolStripDropDownMenu dropDownMenu1 = null;
private void Form1_Load(object sender, EventArgs e)
{
dropDownMenu1 = new ToolStripDropDownMenu();
dropDownMenu1.Items.Add("item1");
dropDownMenu1.Items.Add("item2");
dropDownMenu1.Items.Add("item3");
dropDownMenu1.Location = new Point(90, 45);
dropDownMenu1.Size = new System.Drawing.Size(70, 20);
dropDownMenu1.TopLevel = false;
this.Controls.Add(dropDownMenu1);
}
protected override void OnSizeChanged(EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
//_formContextMenu or this.contextMenuStrip1
dropDownMenu1.Visible = true;
dropDownMenu1.Close();
}
base.OnSizeChanged(e);
}
private void button1_MouseClick(object sender, MouseEventArgs e)
{
dropDownMenu1.Show(e.Location);
}
}
The result:
If there is not specific goal for using ToolStripDropDownMenu you can also use ContextMenuStrip component and Set ContextMenuStrip property of form. This way you don't need to write code to show context menu.
For more usage methods of ToolStripDropDownMenu, you can refer to ToolStripDropDownMenu Class and ToolStripDropDown Class.
I am currently working on a project of mine, i call it "Automated speech detector" Basically this program sits in the system tray most of the time just listening for user input.
I have now come to a conclusion that i will not be able to fill the "command" array with all the commands people want so i have decided i want tointegrate a "AddCommand" user input. Where the user can input a desired command themself and the program will later do whatever i decide it to do. However i really need help with this.
How can i make a string array method that takes 1 argument, the argument will be the userinputs string "command". adding that userinput to the string array. Is this possible?
this is my current given code for the "default" commands i have set.
Choices commands = new Choices();
commands.Add(new string[] { "dollar", "euro", "hotmail", "notepad", "outlook", "onedrive", "discord" });
GrammarBuilder gBuilder = new GrammarBuilder();
gBuilder.Append(commands);
Grammar grammar = new Grammar(gBuilder);
So it will work something like this only that the other array like commands2 will be able to take 1 argument and insert that to the array. Code below is the whole project if neccesary to look at.
public partial class Form1 : Form
{
public SpeechRecognitionEngine recEngine;
public static bool keyHold = false;
NotifyIcon IconPicture;
Icon ActiveIcon;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
#region Icon and windows system tray dropdown text & click events
//Creating icon and setting it to default.
ActiveIcon = new Icon("speak_lzW_icon.ico");
IconPicture = new NotifyIcon();
IconPicture.Icon = ActiveIcon;
//iconPicture.Visible = true;
//Creating menu item for window in system tray.
//MenuItem ProgNameMenuItem = new MenuItem("Voice detection by: Lmannen");
MenuItem QuitMenuItem = new MenuItem("Quit");
ContextMenu contextMenu = new ContextMenu();
contextMenu.MenuItems.Add(ProgNameMenuItem);
contextMenu.MenuItems.Add(QuitMenuItem);
//Adding the icon to the system tray window.
IconPicture.ContextMenu = contextMenu;
//System tray click event handlers
QuitMenuItem.Click += QuitMenuItem_Click;
IconPicture.MouseDoubleClick += IconPicture_MouseDoubleClick1;
#endregion
#region SpeechRecognition commands & event handlers
recEngine = new SpeechRecognitionEngine();
recEngine.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recEngine_SpeechRecognized);
recEngine.AudioStateChanged += new EventHandler<AudioStateChangedEventArgs>(recEngine_AudioStateChange);
Choices commands = new Choices();
commands.Add(new string[] { "dollar", "euro", "hotmail", "notepad", "outlook", "onedrive", "discord" });
GrammarBuilder gBuilder = new GrammarBuilder();
gBuilder.Append(commands);
Grammar grammar = new Grammar(gBuilder);
recEngine.SetInputToDefaultAudioDevice();
recEngine.LoadGrammarAsync(grammar);
recEngine.RequestRecognizerUpdate();
recEngine.RecognizeAsync(RecognizeMode.Multiple);
#endregion
}
internal void recEngine_AudioStateChange(object sender, AudioStateChangedEventArgs e)
{
InputStatusLbl.Text = string.Format("{0}", e.AudioState);
}
internal static void recEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
switch(e.Result.Text)
{
case "notepad":
System.Diagnostics.Process.Start("notepad.exe");
break;
case "hotmail":
System.Diagnostics.Process.Start("https://outlook.live.com/owa/");
break;
case "outlook":
System.Diagnostics.Process.Start("https://outlook.live.com/owa/");
break;
case "ondrive":
System.Diagnostics.Process.Start("https://onedrive.live.com/");
break;
case "discord":
string name = Environment.UserName;
string path = string.Format(#"C:\Users\{0}\AppData\Local\Discord\app-0.0.300\Discord.exe", name);
System.Diagnostics.Process.Start(path);
break;
}
}
private void Form1_Resize(object sender, EventArgs e)
{
if(WindowState == FormWindowState.Minimized)
{
ShowInTaskbar = false;
ShowIcon = false;
IconPicture.Visible = true;
}
}
private void IconPicture_MouseDoubleClick1(object sender, MouseEventArgs e)
{
ShowInTaskbar = true;
IconPicture.Visible = false;
ShowIcon = true;
WindowState = FormWindowState.Normal;
}
private void QuitMenuItem_Click(object sender, EventArgs e)
{
IconPicture.Dispose();
this.Close();
}
private void addToolStripMenuItem_Click(object sender, EventArgs e)
{
string input = Microsoft.VisualBasic.Interaction.InputBox("Add a voice-command by text", "Command");
MessageBox.Show(input + " is now added to the command list");
}
}
}
Having some background on your task, I believe you need a Dictionary. It will be a public variable at the form level. The key will be the command and the value will be the path of execution. In the form, you'll initialize it with your 5 values BEFORE assigning your events.
Public Dictionary<String, String> Commands = new Dictionary<String, String>();
So in the form load (you'll need 5 of these):
Dictionary.Add("notepad", "notepad.exe");
Dictionary.Add("hotmail", "https://outlook.live.com/owa/");
Instead of a case statement, you will search the dictionary and if the key exists, you will start the value. Assuming you have a dictionary called commands it would be:
string command = "";
if ( Commands.TryGetValue(e.Result.Text, out command))
System.Diagnostics.Process.Start(command)
The add command will path in the command name and the application path and add to the dictionary.
Commands.Add(commandName, pathToCommand);
Note that when you do this, you should ALSO save to a file in the users local application data area that can be brought back on form load, so its retained, but that's out of scope.
Im new to c#, and trying to write code w/o vs.
i am trying to build a system tray app that will change the notifyIcon at runtime.
I read a few tutorials on the topic, and wrote the following code, but i am getting these errors, and cannot get around it:
new 2.cs(41,9): error CS0103: The name 'notifyIcon1' does not exist in the current context
new 2.cs(41,37): error CS0026: Keyword 'this' is not valid in a static property, static method, or static field initializer
Can anyone help me out? (this is a pared down version of my code... tried to isolate the problems.)
using System;
using System.Windows.Forms;
using System.Threading;
using System.Drawing;
using System.Diagnostics;
namespace sysTrayApp
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
NotifyIcon notifyIcon1 = new NotifyIcon();
ContextMenu contextMenu1 = new ContextMenu();
MenuItem menuItem1 = new MenuItem();
contextMenu1.MenuItems.AddRange(new MenuItem[] { menuItem1 });
menuItem1.Index = 0;
menuItem1.Text = "Exit";
menuItem1.Click += new EventHandler(menuItem1_Click);
notifyIcon1.Icon = new Icon("On.ico");
notifyIcon1.Text = "some text";
notifyIcon1.ContextMenu = contextMenu1;
notifyIcon1.Click += new EventHandler(notifyIcon1_Click);
notifyIcon1.Visible = true;
Application.Run();
}
private static void menuItem1_Click(object Sender, System.EventArgs e)
{
Application.Exit();
}
private static void notifyIcon1_Click(object Sender, EventArgs e)
{
notifyIcon1.Icon = new Icon(this.GetType(),"Off.ico");
}
}
}
I think problem in your notifyIcon1_Click EventHandler. change the code as give sample below.
private static void notifyIcon1_Click(object Sender, EventArgs e)
{
((NotifyIcon)Sender).Icon = new Icon(Sender.GetType(), "Off.ico");
//notifyIcon1.Icon =
}
Please in my code i try to catch win32.systemevents.sessionended event to procede with saving of my app data by the end of session in case the app is not closed manually .. some time ago this has been workin and now that i had my project grown a lil it is not any more..? i have tried to find something meaningfull for few days but found nothing really.. when i try to catch another systemevent like MonitorResolutionChanged it works well but this one not. I have also tried to register within the mainWindow (app form ..), nothing :-( Please any idea?
I think all the relevant information should be in the beginning till void Main but i put it all in case you would need or want to see more .. Thanx a lot Tomas
My code:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using MovablePython; // my own class within this project
using Avn; //my own referenced assembly
namespace DirDist
{
class Program
{
private static string appGuid = "Cddbserviceman";
private static System.Windows.Forms.ContextMenu nIMenu;
internal static System.Windows.Forms.NotifyIcon notifyIcon1;
private static MenuItem showItem;
public static MenuItem justCDsItem;
private static MenuItem searchItem;
private static MenuItem settingsItem;
private static MenuItem quitItem;
internal static Form1 mainWindow;
private static Hotkey hk;
internal static Registration.LicenceState mode; // app mode - registered/trial/blocked/demaged ..
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
using (Mutex mutex = new Mutex(false, appGuid))
{
if (!mutex.WaitOne(0, false))
{
MessageBox.Show("CDDB is already running on your machine \n (Check status bar for access ..)");
return;
}
GC.Collect();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
mode = Registration.Startup();
Program.mainWindow = new Form1();
mainWindow.Activate();
//mainWindow.Validate();
//mainWindow.Update();
mainWindow.Visible = false;
PutIcon();
//Microsoft.Win32.SystemEvents.SessionEnded += SystemEvents_SessionEnded;
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);//**zkousime zda funguje pro hibernaci ..
RegisterHotKey(true);
Application.Run();
}
}
static void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
//MessageBox.Show("SessionEnded fired");
RegisterHotKey(false);
notifyIcon1.Visible = false;
notifyIcon1.Dispose();
notifyIcon1 = null;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
Microsoft.Win32.SystemEvents.SessionEnded -= new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
mainWindow.Close();
}
// zaregistruje globalni hotkey ctrl+shift+F Pro hledani
private static void RegisterHotKey(bool active)
{
if (!active)
{
if (hk != null) hk.Unregister();
}
else
{
if(hk ==null) hk = new Hotkey();
hk.KeyCode = Keys.F;
//hk.Windows = true;
hk.Shift = true;
hk.Control = true;
//hk.Pressed += delegate { Console.WriteLine("Windows+1 pressed!"); };
hk.Pressed += delegate { searchItemClick(new object(), new EventArgs()); };
if (hk.GetCanRegister(mainWindow)) hk.Register(mainWindow);
else ; // just do nothing
}
}
private static void PutIcon()
{
if (notifyIcon1 == null)
{
showItem = new MenuItem ("&Show interface", new System.EventHandler (showInfaceClick));
justCDsItem = new MenuItem ("&Jus'CDs",new System.EventHandler ( justCDsClick));
justCDsItem.Checked = Form1.settings.justCDs;
searchItem = new MenuItem("Search CDDB",new System.EventHandler (searchItemClick));
searchItem.Shortcut = Shortcut.CtrlShiftF;
searchItem.ShowShortcut = true;
settingsItem = new MenuItem("Settings", new System.EventHandler(settingsItemClick));
quitItem = new MenuItem("&Quit", new System.EventHandler(quitItemClick));
nIMenu = new System.Windows.Forms.ContextMenu(new MenuItem[5] { showItem, justCDsItem, searchItem,settingsItem, quitItem });
notifyIcon1 = new System.Windows.Forms.NotifyIcon();
notifyIcon1.ContextMenu = nIMenu;
notifyIcon1.Icon = new System.Drawing.Icon(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Icon1.ico");
//notifyIcon1.Icon = new System.Drawing.Icon(System.IO.Path.GetDirectoryName(
//System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase ) + "Icon1.ico");
//notifyIcon1.Icon = new System.Drawing.Icon("Icon1.ico");
notifyIcon1.DoubleClick += new EventHandler(notifyIcon1_DoubleClick);
notifyIcon1.Visible = true;
}
}
/* private static void notifyIcon1_MouseMove(object sender, MouseEventArgs mea)
* aby to fungovalo je treba upravit contextmenu na contextmenustrip a taky ty items .. az nakonec
* je tu kolem uz rozdelana priprava ..
{
notifyIcon1.ShowBalloonTip(2000,AppName,"Active",ToolTipIcon.None);
} */
// clicks on NotificationIcon context menu ..
private static void showInfaceClick(object sender, EventArgs e)
{
mainWindow.tabControl1.SelectedIndex = 0;
mainWindow.Show();
}
private static void justCDsClick(object sender, EventArgs e)
{
Form1.settings.justCDs = mainWindow.checkBox1.Checked = justCDsItem.Checked = !Form1.settings.justCDs;
if (mainWindow.Visible) mainWindow.Update();
}
private static void searchItemClick(object sender, EventArgs e)
{
mainWindow.tabControl1.SelectedIndex = 1 ;
//this.Size = new Size(this.Width, SystemInformation.PrimaryMonitorSize.Height);
mainWindow.Location = new System.Drawing.Point(SystemInformation.PrimaryMonitorSize.Width - mainWindow.Width, SystemInformation.PrimaryMonitorSize.Height - mainWindow.Height);
//mainWindow.Location = new System.Drawing.Point(880, 500);
mainWindow.Show();
}
private static void settingsItemClick(object sender, EventArgs e)
{
mainWindow.tabPage3_GotFocus(new Object(), new EventArgs());
mainWindow.tabControl1.SelectedIndex = 2;
mainWindow.Show();
}
public static void quitItemClick(object sender, EventArgs e)
{
if (DialogResult.Cancel == MessageBox.Show("Really exit application and stop scanning?",Form1.AppName,MessageBoxButtons.OKCancel,MessageBoxIcon.Question)) return;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
//if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
if (Form1.settings.fileIndex) mainWindow.SaveIndex(Form1.settings.indexPath);
mainWindow.Close();
mainWindow = null;
notifyIcon1.Visible = false;
Application.Exit();
}
static void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
//throw new NotImplementedException();
//if (!mainWindow.Visible) mainWindow.WindowState = FormWindowState.Normal; else mainWindow.WindowState = FormWindowState.Minimized;
//if (!mainWindow.Visible) mainWindow.Show(); else mainWindow.Hide();
if (!mainWindow.Visible) mainWindow.Visible = true; else mainWindow.Visible = false;
}
}
}
OK. So here is the catch and solution . In Windows it is not determined whether win32.systemevents.sessionended shall be risen or form.close() will be called first by operating system. moreover it seems that if form.close() is called first then sessionended is omited even though form is not closed and disposed due to canceling closing process. in my system this behaviour changed after i ran some registry cleaning software. anyway understanding this we have to take care of both possible scenarios.
1. catch win32.systemevents.sessionended (or sessionending) event whatever suits our needs better and be
.
.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
Program.mainWindow = new Form1();
mainWindow.Activate();
mainWindow.Visible = false;
PutIcon();
RegisterHotKey(true);
Application.Run();
}
}
public static void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
// do whatever needed and exit application ..
RegisterHotKey(false);
notifyIcon1.Visible = false;
notifyIcon1.Dispose();
notifyIcon1 = null;
if (!mainWindow.dBSaved) mainWindow.SaveDb(Form1.settings.dBPath);
if (mainWindow.index != null) mainWindow.SaveIndex(Form1.settings.indexPath);
Microsoft.Win32.SystemEvents.SessionEnded -= new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
if (mainWindow != null)
{
mainWindow.Dispose();
mainWindow = null;
}
Application.Exit();
}
2. properly override form.OnClosing() because this is being called when form is closing either manually by user or by system when shuting down, loging off etc. or create hanler for main form.Closing:
public Form1()
{
this.Closing += new CancelEventHandler(this.Form1_Closing);
InitializeComponent();
}
private void Form1_Closing(Object sender, CancelEventArgs e)
{
if (systemShutdown) Program.SystemEvents_SessionEnded(this, new Microsoft.Win32.SessionEndedEventArgs(Microsoft.Win32.SessionEndReasons.SystemShutdown));
else
{
e.Cancel = true;
this.Hide();
}
}
just want to mention that message pump must be runnig in order to sessionended be risen. Application.run() accomplishes that.
in my case as you can see i had to dig even deeper as i had closing redirected just to hide the app not to close it ( i just hide the app to notification irea icon and close it manually when i need .. ) and so i had to use some kind of way to specify the situation when this is called because sender is unfortunatelly and unexpectedly always this ..?
this is done by overring WndProc and catching propper message .here you can listen pretty much to everything inside windows ( like disc inserted / removed )but it is hooked only to a form and implementation gets often not so simple as you have to manully define various values and structs and compare against those values .. other then that its pretty simple:
private static int WM_QUERYENDSESSION = 0x11;
private static bool systemShutdown = false;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg==WM_QUERYENDSESSION)
{
systemShutdown = true;
}
base.WndProc(ref m);
}
this was found here:
http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.sessionending.aspx
Thinking a bit further we can possibly omit point 1 as system shall probably always try to call mainForm.close() but i keep it as i can not be certain about windows behaviour once it runs those things in different order again .. and also it is the mainly suggested solution for reacting to system shut down ..
hope this is helpfull for someone. greets from prague tomas
Here is something that you could try
For a shutdown, override the OnShutdown method:
protected override void OnShutdown()
{
//your code here
base.OnShutdown();
}
For a logoff:
First, add an event handler to Microsoft.Win32.SystemEvents.SessionEnded in the Service Constructor:
public MyService()
{
InitializeComponent;
Microsoft.Win32.SystemEvents.SessionEnded += new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);
}
Then add the handler:
void SystemEvents_SessionEnded(object sender, Microsoft.Win32.SessionEndedEventArgs e)
{
//your code here
}
This should catch any ended session, including the console itself (the one running the services).