Save window state when application in tray - c#

I have an app that minimizes to the system tray by clicking on "close" button and I want to save it's state (position, all elements (comboboxes, textboxes) with their values, etc).
Now I wrote this code, but it creates a new window from tray (instead of recovering the old one, with its parameters):
# app.xaml.cs:
this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
// create a system tray icon
var ni = new System.Windows.Forms.NotifyIcon();
ni.Visible = true;
ni.Icon = QuickTranslator.Properties.Resources.MainIcon;
ni.DoubleClick +=
delegate(object sender, EventArgs args)
{
var wnd = new MainWindow();
wnd.Visibility = Visibility.Visible;
};
// set the context menu
ni.ContextMenu = new System.Windows.Forms.ContextMenu(new[]
{
new System.Windows.Forms.MenuItem("About", delegate
{
var uri = new Uri("AboutWindow.xaml", UriKind.Relative);
var wnd = Application.LoadComponent(uri) as Window;
wnd.Visibility = Visibility.Visible;
}),
new System.Windows.Forms.MenuItem("Exit", delegate
{
ni.Visible = false;
this.Shutdown();
})
});
How I can modify this code for my problem?

When you hold a reference to your `MainWindow´ then you can simple call Show() again after closing it. Closing the Window will simply hide it and calling Show again will restore it.
private Window m_MainWindow;
ni.DoubleClick +=
delegate(object sender, EventArgs args)
{
if(m_MainWindow == null)
m_MainWindow = new MainWindow();
m_MainWindow.Show();
};
If you´re sure that the MainWidnow is your Applications primary Window then you can also use this:
ni.DoubleClick +=
delegate(object sender, EventArgs args)
{
Application.MainWindow.Show();
};
I would prefer the first variant since it´s explicit.

Related

Trying to stall main-thread while background worker displays a user-interactive form in C#

I'm making(trying) to make a dialogue box similar to the openFileDialogue where the program flow of the Main Thread is stalled until the OPF.ShowDialogue() function stalls while running a separate thread.
I have a OpenFileDialogue_Gui class which uses a semaphore and a background worker.
The background worker is first launched to generate a separate form with the necessary user-interface
Then the semaphore stalls the main thread until the user clicks one of the buttons on the background thread's form.
Then it releases the semaphore and the result is sent back to the calling function.
Sounds nice in theory, but there's a problem. The background-worker is not displaying its form and it's not working.
Here's the code :
public class openfiledialogue_Gui
{
Semaphore semStall = new Semaphore(0, 1);
BackgroundWorker bck = new BackgroundWorker();
public openfiledialogue_Gui()
{
bck.WorkerSupportsCancellation = true;
bck.DoWork += Bck_DoWork;
bck.RunWorkerCompleted += Bck_RunWorkerCompleted;
}
public enum enuResult { Ok, Cancel, _num };
public enuResult ShowDialogue()
{
bck.RunWorkerAsync();
semStall.WaitOne();
return eResult;
}
enuResult eResult = enuResult.Cancel;
void EventOk_click(object sender, EventArgs e)
{
eResult = enuResult.Ok;
strFilename = "ok clicked";
semStall.Release();
}
void EventCancel_click(object sender, EventArgs e)
{
eResult = enuResult.Cancel;
strFilename = "cancel clicked";
semStall.Release();
}
private void Bck_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){semStall.Release();}
private void Bck_DoWork(object sender, DoWorkEventArgs e)
{
Form frmShow = new Form();
Button btnOk = new Button();
btnOk.Text = "ok";
Button btnCancel = new Button();
btnCancel.Text = "Cancel";
btnOk.AutoSize
= btnCancel.AutoSize
= true;
frmShow.Controls.Add(btnOk);
frmShow.Controls.Add(btnCancel);
frmShow.ControlBox = false;
btnOk.Location = new Point(100, 25);
btnCancel.Location = new Point(100, 75);
btnCancel.Click += EventCancel_click;
btnOk.Click += EventOk_click;
frmShow.Show();
}
public string strFilename = "this is a test";
public string Filename
{
get { return strFilename; }
}
}
Is there any way to make this work?
Sounds like you want to make a 'Modal Form'.
var form = new MyModalForm();
form.ShowDialog();
This will 'stall' the UI until you cancel (or otherwise close) the form.

ContextMenuStrip in c# tray application not reacting correctly when in expanded icon window

I have made a tray application with an icon that opens a ContextMenuStrip on Icon Click. I have three ToolStripMenuItem that can be clicked.
The Tray Application is working fine as long as the icon is visible directly. However if I have to click on the chevron to expand the non visible tray icons, I run into one Problem.
I can open the Menu by click on the Item. If I click on one of the ToolStripMenuItems the Tray-Menu goes into the Background of the Expanded Tray Icons and cannot be clicked anymore. How can I prevent this?
It seems the background is capturing the click rather then the openend form.
Here is the code for the Menu.
class Menu
{
private static ContextMenuStrip contextMenuStrip;
private static NotifyIcon notifyIcon1 = new NotifyIcon();
public Menu()
{
notifyIcon1.Icon = new Icon("icon.ico");
notifyIcon1.Text = "icon";
contextMenuStrip = new ContextMenuStrip();
ToolStripItem stripItem0 = new ToolStripMenuItem("open");
contextMenuStrip.Items.AddRange(new ToolStripItem[] { stripItem0 });
ToolStripItem stripItem1 = new ToolStripMenuItem("stop");
stripItem1.Click += new EventHandler(ToggleTracking);
contextMenuStrip.Items.AddRange(new ToolStripItem[] { stripItem1 });
ToolStripItem line = new ToolStripSeparator();
contextMenuStrip.Items.AddRange(new ToolStripItem[] { line });
ToolStripItem stripItem2 = new ToolStripMenuItem("close");
stripItem2.Click += new EventHandler(Close);
contextMenuStrip.Items.AddRange(new ToolStripItem[] { stripItem2 });
notifyIcon1.ContextMenuStrip = contextMenuStrip;
//notifyIcon1.ContextMenu = contextMenu1;
notifyIcon1.Click += new EventHandler(IconClick);
notifyIcon1.Visible = true;
}
private void ToggleTracking(object Sender, EventArgs e)
{
ToolStripMenuItem stripItem1 = (ToolStripMenuItem)contextMenuStrip.Items[1];
if (stripItem1.Text == "stop")
{
stripItem1.Text = "restart";
Batch.StopTimer();
}
else
{
stripItem1.Text = "stop";
Batch.RestartTimer();
}
}
private void Close(object Sender, EventArgs e)
{
Application.Exit();
}
private void IconClick(object Sender, EventArgs e)
{
Control strip = Sender as Control;
if (contextMenuStrip.Visible)
{
contextMenuStrip.Hide();
}
else
{
contextMenuStrip.Show(Cursor.Position);
}
}
}
I had to use the BringToFront method like this.
{
contextMenuStrip.Show(Cursor.Position);
contextMenuStrip.BringToFront();
}
https://msdn.microsoft.com/de-de/library/system.windows.forms.control.bringtofront(v=vs.110).aspx

Show an Icon beside an Item in ContextMenuStrip when its clicked

I wrote a windows form application which can change my GateWay automatically by executing two Batch files.
Problem is that I want to show "check.ico" icon beside the item in ContextMenu list when I click on it.
Here is my code :
public Form1()
{
InitializeComponent();
}
Image MenuStripImage = Image.FromFile(#"C:\Users\ALIENWARE\Documents\Visual Studio 2015\Projects\routerSelect\routerSelect\Check.ico");
NotifyIcon TrayIcon;
ContextMenuStrip TrayMenu;
private void Form1_Load(object sender, EventArgs e)
{
Image MenuStripExit = Image.FromFile(#"C:\Users\ALIENWARE\Documents\Visual Studio 2015\Projects\routerSelect\routerSelect\exit.ico");
this.WindowState = FormWindowState.Maximized;
this.ShowInTaskbar = false;
this.Hide();
TrayIcon = new NotifyIcon();
TrayMenu = new ContextMenuStrip();
TrayMenu.Items.Add("GreenPAcket").Click += new EventHandler(GreenpacketSelect);
//if (DLinkSelectcliced == true && GreenPacketSelected == false)
//{
TrayMenu.Items.Add(MenuStripImage);
//}
TrayMenu.Items.Add("D-Link DSL 2890AL 5GHz").Click += new EventHandler(DLinkSelect);
//if (GreenPacketSelected == true && DLinkSelectcliced == false)
//{
TrayMenu.Items.Add(MenuStripImage);
//}
TrayMenu.Items.Add("Exit", MenuStripExit).Click += new EventHandler(Exit);
TrayIcon.ContextMenuStrip = TrayMenu;
TrayIcon.Visible = true;
TrayIcon.Icon = new Icon(#"C:\Users\ALIENWARE\Documents\Visual Studio 2015\Projects\WindowsFormsApplication2\WindowsFormsApplication2\router.ico");
}
private void Exit(object sender, EventArgs e)
{
System.Windows.Forms.Application.Exit();
}
// bool DLinkSelectcliced = false;
private void DLinkSelect(object sender, EventArgs e)
{
// DLinkSelectcliced = true;
Process Proc = new Process();
Proc.StartInfo.FileName = (#"C:\Users\ALIENWARE\Documents\Visual Studio 2015\Projects\routerSelect\routerSelect\Dlink.lnk");
Proc.Start();
TrayMenu.Items.Add(MenuStripImage);
// GreenPacketSelected = false;
}
// bool GreenPacketSelected = false;
private void GreenpacketSelect(object sender, EventArgs e)
{
// GreenPacketSelected = true;
Process Proc = new Process();
Proc.StartInfo.FileName = (#"C:\Users\ALIENWARE\Documents\Visual Studio 2015\Projects\routerSelect\routerSelect\GreenPacket.lnk");
Proc.Start();
TrayMenu.Items.Add(MenuStripImage);
// DLinkSelectcliced = false;
}
If check.ico is a check mark, you don't need it for ContextMenuItem because it has option to show check mark, just enable CheckOnClick property for that item.
But if you want to show your custom icon instead, you must first convert it to image
You can do it yourself or use this method below to let C# do it for you
Use method here to convert icon to bmp image:
http://www.dotnetfunda.com/codes/show/967/icon-to-bitmap-in-csharp-winforms
Or simply create .png/.bmp version of this icon instead.
But first you should add this icons as resources to your project because if this icons will not exist in the location you gave it won't work (so you won't be able to use it on another PC).
To do it open solution explorer, right click on project and select properties, then go to resources, select icons, click Add Resource and add all icons.
Then to load icons from resources you simply type:
notifyIcon1.Icon = Properties.Resources.iconName
To show icon as image in your ContextMenuItem method in the link like this:
menu1ToolStripMenuItem.Image = ConvertFromIconToBitmap(Properties.Resources.iconName, new Size(16,16))
Btw, I glanced at your code and I think there is a lot of problems there...

NotifyIcon hides app from taskbar. How to avoid that?

I have an application that goes to system tray when I minimize it. I created a notify icon to handle some secondary options for the app using right click from mouse using that notify icon.
But I would like the application not to disappear from task bar when I minimize it and mantain the notify icon on system tray.
Is there any way to acomplish thtat?
EDIT: When I minimize the application, I use the Hide() command to use the NotifyIcon. But I want it to remain on task bar.
See code here:
private void MainWindow_OnStateChanged(object sender, EventArgs e)
{
if (WindowState != WindowState.Minimized) return;
Hide();
ShowInTaskbar = true;
if (notifyIcon != null)
notifyIcon.ShowBalloonTip(2000);
}
Note: This NotifyIcon is embeded on a WPF container programatically like this:
DrawNotifyIcon();
private void DrawNotifyIcon()
{
try
{
string source = Path.GetDirectoryName(Assembly.GetAssembly(typeof(MainWindow)).CodeBase);
string tmpSource = source + #"\Resources\mainico.ico";
tmpSource = tmpSource.Replace(#"file:\", "");
// notify Icon
notifyIcon = new NotifyIcon
{
BalloonTipTitle = Cultures.Resources.Title,
BalloonTipText = Cultures.Resources.NotifyIconExecuting,
BalloonTipIcon = ToolTipIcon.Info,
Icon = new System.Drawing.Icon(tmpSource)
};
notifyIcon.DoubleClick += notifyIcon_DoubleClick;
notifyIcon.Click += notifyIcon_Click;
notifyIcon.MouseUp += notifyIcon_MouseUp;
// Create ContextMenu
contextMenu = new ContextMenuStrip();
contextMenu.Closing += contextMenu_Closing;
// Exit item
menuItemExit = new ToolStripMenuItem
{
Text = Cultures.Resources.Exit,
Image = Cultures.Resources.close
};
menuItemExit.Click += menuItemExit_Click;
// Restore item
menuItemRestore = new ToolStripMenuItem
{
Text = Cultures.Resources.Restore,
Image = Cultures.Resources.restore1
};
menuItemRestore.Click += menuItemRestore_Click;
// Active or inactive log
menuItemActive = new ToolStripMenuItem
{
Text = Cultures.Resources.On,
Image = Cultures.Resources.green,
Checked = true
};
menuItemActive.Click += menuItemActive_Click;
menuItemActive.CheckStateChanged += menuItemActive_CheckStateChanged;
// Order of appearance of ContextMenu items
contextMenu.Items.Add(menuItemActive);
contextMenu.Items.Add("-");
contextMenu.Items.Add(menuItemRestore);
contextMenu.Items.Add(menuItemExit);
notifyIcon.ContextMenuStrip = contextMenu;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Any idea on how to keep both icons for WPF?
Well, Its not possible to show forms in taskbar which is in hidden state. Still you can forcefully minimized the form. try below modified code :
private void MainWindow_OnStateChanged(object sender, EventArgs e)
{
if (WindowState != WindowState.Minimized) return;
this.ShowInTaskbar = true;
if (notifyIcon != null)
notifyIcon.ShowBalloonTip(2000);
this.WindowState = FormWindowState.Minimized;
}

C# NotifyIcon stays in tray after the Balloon Tip has been closed

after the Ballon Tip of my NotifyIcon has been close the icon still stays in tray.
It vanishes only when I hover it with my mouse cursor.
I have a class Notification.cs which has one component - NotifyIcon.
I call it from my Console Application as I only want to show the notification when certain conditions are fulfilled.
Some code:
how I call the notification from within my program:
Notification not = new Notification("Error occured, do this or that", "Some error", System.Windows.Forms.ToolTipIcon.Error);
not.getIcon().ShowBalloonTip(1000);
the notification class:
public Notification(string baloonTipText, string baloonTipTitle, System.Windows.Forms.ToolTipIcon icon) : this()
{
this.icon.Visible = true;
this.icon.BalloonTipText = baloonTipText;
this.icon.BalloonTipTitle = baloonTipTitle;
this.icon.BalloonTipIcon = icon;
}
public System.Windows.Forms.NotifyIcon getIcon()
{
return this.icon;
}
private void icon_BalloonTipClosed(object sender, EventArgs e)
{
this.icon.Visible = false;
this.icon.Dispose();
}
Any ideas?
Because you're running in a console application, your icon_BalloonTipClosed handler will not be invoked when the balloon tip is closed (no message pump). You will need to call Dispose manually either as your application exits or set a timer (System.Threading.Timer, System.Windows.Forms.Timer will not work) with a timeout longer than the balloon tip's timeout. e.g.:
timer = new Timer(state => not.getIcon().Dispose(), null, 1200, Timeout.Infinite);
using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace ShowToolTip
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btBallonToolTip_Click(object sender, EventArgs e)
{
ShowBalloonTip();
this.Hide();
}
private void ShowBalloonTip()
{
Container bpcomponents = new Container();
ContextMenu contextMenu1 = new ContextMenu();
MenuItem runMenu = new MenuItem();
runMenu.Index = 1;
runMenu.Text = "Run...";
runMenu.Click += new EventHandler(runMenu_Click);
MenuItem breakMenu = new MenuItem();
breakMenu.Index = 2;
breakMenu.Text = "-------------";
MenuItem exitMenu = new MenuItem();
exitMenu.Index = 3;
exitMenu.Text = "E&xit";
exitMenu.Click += new EventHandler(exitMenu_Click);
// Initialize contextMenu1
contextMenu1.MenuItems.AddRange(
new System.Windows.Forms.MenuItem[] { runMenu, breakMenu, exitMenu });
// Initialize menuItem1
this.ClientSize = new System.Drawing.Size(0, 0);
this.Text = "Ballon Tootip Example";
// Create the NotifyIcon.
NotifyIcon notifyIcon = new NotifyIcon(bpcomponents);
// The Icon property sets the icon that will appear
// in the systray for this application.
string iconPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + #"\setup-icon.ico";
notifyIcon.Icon = new Icon(iconPath);
// The ContextMenu property sets the menu that will
// appear when the systray icon is right clicked.
notifyIcon.ContextMenu = contextMenu1;
notifyIcon.Visible = true;
// The Text property sets the text that will be displayed,
// in a tooltip, when the mouse hovers over the systray icon.
notifyIcon.Text = "Morgan Tech Space BallonTip Running...";
notifyIcon.BalloonTipText = "Morgan Tech Space BallonTip Running...";
notifyIcon.BalloonTipTitle = "Morgan Tech Space";
notifyIcon.ShowBalloonTip(1000);
}
void exitMenu_Click(object sender, EventArgs e)
{
this.Close();
}
void runMenu_Click(object sender, EventArgs e)
{
MessageBox.Show("BallonTip is Running....");
}
}
}

Categories

Resources