Fail minimizing to system tray in C# - c#

I want to minimize my program to the system tray by clicking an entry in the system menu of the form.
So first I created a notify icon and a context menu:
private void InitializeComponent()
{
this.components = new Container();
...
this.notifyIcon = new NotifyIcon();
this.contextMenu = new ContextMenu();
this.contextMenuItem1 = new MenuItem();
this.contextMenuItem2 = new MenuItem();
this.SuspendLayout();
this.notifyIcon.ContextMenu = this.contextMenu;
this.notifyIcon.Text = "Test";
this.contextMenu.Name = "contextMenu";
this.contextMenu.MenuItems.AddRange(new MenuItem[]
{
this.contextMenuItem1,
this.contextMenuItem2
});
this.contextMenuItem1.Name = "contextMenuItem1";
this.contextMenuItem1.Text = "&Show";
this.contextMenuItem1.Click += new EventHandler(this.contextMenuItem1_Click);
this.contextMenuItem2.Name = "contextMenuItem2";
this.contextMenuItem2.Text = "&Exit";
this.contextMenuItem2.Click += new EventHandler(this.contextMenuItem2_Click);
}
Then I extended the system menu:
private void Form_Load(object sender, EventArgs e)
{
int hmenu = GetSystemMenu(Handle, 0);
AppendMenu(hmenu, 0xA00, 0, null);
AppendMenu(hmenu, 0, 111, "M&inimize to system tray");
}
A click on this menu item should fade out the main window:
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x112)
{
if (m.WParam.ToInt32() == 111)
{
Visible = false;
Hide();
notifyIcon.Visible = true;
}
}
}
A click in the context menu have to reshow the program window or close the whole application:
private void contextMenuItem1_Click(object sender, EventArgs e)
{
notifyIcon.Visible = false;
Show();
Visible = true;
}
private void contextMenuItem2_Click(object sender, EventArgs e)
{
Close();
}
My problem is now the following:
If I click the new entry to minimize then the WndProc method is executed successfully and the form will be hidden but no item with the caption "Test" is displayed in the system tray.
And then there's also another window visible. I think that comes from .NET but the window is completely empty so I'm not sure. Normally I should fallback to the exe file in windows explorer which starts my program, isn't it?
Thanks in advance!
+++ EDIT +++
I found out that the empty window behind my application was the console window. I only forgot to compile my project with the winexe parameter.

Related

NotifyIcon not showing context menu when app running background worker

My WPF application shows a window and when the user clicks a button, it begins to run its tasks and minimizes to a tray item in the notification area with a context menu where I would like the user to be able to cancel the operation.
The context menu worked before using a BackgroundWorker, however, cancellation did not. Since I've implemented a background worker,the context menu does not appear once the .runworkerasync() method has run.
My Notify Icon:
public NotifyIcon myNotifyIcon;
When my application runs I set it up like this:
private void setup_NotifyIcon()
{
myNotifyIcon = new NotifyIcon();
setTrayIcon();
myNotifyIcon.MouseDown += new MouseEventHandler(myNotifyIcon_MouseDown);
var menuItemCancel = new MenuItem("Cancel Parsing");
var contextMenu = new ContextMenu();
menuItemCancel.Click += new System.EventHandler(this.menuItemCancel_Click);
contextMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { menuItemCancel });
myNotifyIcon.ContextMenu = contextMenu;
}
private void menuItemCancel_Click(object Sender, EventArgs e)
{
//do something
}
void myNotifyIcon_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
//do something
}
}
Then when the user clicks the button:
worker.RunWorkerAsync();
Why won't myNotifyIcon.MouseDown += new MouseEventHandler(myNotifyIcon_MouseDown); trigger the context menu?
The solution turned out to be a threading issue as suggested by Sebastian in the comments.
The key was to start the icon on another thread using Application.Run() and to make the icon visible within that code.
Once this was done, right-clicking on the icon worked, as did the cancellation functionality being handled.
private void setup_NotifyIcon()
{
Thread notifyThread = new Thread(
delegate ()
{
myNotifyIcon = new NotifyIcon();
setTrayIcon();
myNotifyIcon.MouseDown += new MouseEventHandler(myNotifyIcon_MouseDown);
mnuCancel = new MenuItem("Cancel Parsing");
menu = new ContextMenu();
mnuCancel.Click += new System.EventHandler(menuItemCancel_Click);
menu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { mnuCancel });
myNotifyIcon.ContextMenu = menu;
myNotifyIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info; //Shows the info icon so the user doesn't thing there is an error.
myNotifyIcon.BalloonTipText = "The P6 Parser will minimize to the system tray while working.";
myNotifyIcon.BalloonTipTitle = "Processing...";
myNotifyIcon.Visible = true;
myNotifyIcon.ShowBalloonTip(500);
myNotifyIcon.Visible = true;
System.Windows.Forms.Application.Run();
});
notifyThread.Start();
}
in Program.cs change the Attribute [STAThread] to [MTAThread]

open a window(wpf) on the foreground from a page(wpf)

I am working at a WPF desktop application, in this application I open a wpf page which contains a listbox of contacts on a frame.
When I double-click on a contact, a window opens to modify it. The problem is that the window is opened in the back and I want it on the foreground , I used this code
private void HandleDoubleClick(object sender, MouseButtonEventArgs e)
{
if (listBox.SelectedItem != null)
{
modify_contact window = new modify_contact(list[listBox.SelectedIndex]);
window.Owner=this;
window.Show();
}
}
It didn't work because it's and not a window
So what can I do to make my opened on the foreground ?
private void HandleDoubleClick(object sender, MouseButtonEventArgs e)
{
if (listBox.SelectedItem != null)
{
modify_contact window = new modify_contact(list[listBox.SelectedIndex]);
window.Owner = MainWindow.GetWindow(this);
window.Show();
}
}
You can always create a Window and set it's Content like this
private void HandleDoubleClick(object sender, MouseButtonEventArgs e)
{
modify_contact window = new modify_contact(list[listBox.SelectedIndex]);
Window windowHost = new Window
{
Title = "I'm the title",
Content = window
};
windowHost.ShowDialog();
}

register desktop application shorcut key in shell of window

I want to register my desktop application shortcut in windows shell.so that if my desktop application is in minimized mode then i want to run the shortcut key i.e is set by me in desktop application that i have created.
My main motive is that when my application is in minimized mode then i want to run a shortcut key to take screenshot of active screen.
I have tried the below code that will minimized my desktop application.
public TemplatesCreation()
{
InitializeComponent();
trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Exit", OnExit);
trayIcon = new NotifyIcon();
trayIcon.Text = "MyTrayApp";
trayIcon.Icon = new Icon(SystemIcons.Application, 40, 40);
trayIcon.ContextMenu = trayMenu;
trayIcon.Visible = true;
protected override void OnLoad(EventArgs e)
{
Visible = true; // Hide form window.
ShowInTaskbar = false; // Remove from taskbar.
base.OnLoad(e);
}
private void OnExit(object sender, EventArgs e)
{
Application.Exit();
}
Thanks in advance

Bring dialog window to front

I am showing a window on a button click like this:
private void showWindow(object obj)
{
var dialog = new AddItemView();
dialog.Show();
}
If the button is clicked again, while this window is still open, how do I bring this window to the front and not create a new one?
Just store the dialog object and check whether it's already been created in showWindow.
Used the windows Closed event to clear the reference to the dialog object.
AddItemView dialog;
private void showWindow(object obj)
{
if ( dialog == null )
{
dialog = new AddItemView();
dialog.Show();
dialog.Owner = this;
dialog.Closed += new EventHandler(AddItemView_Closed);
}
else
dialog.Activate();
}
void AddItemView_Closed(object sender, EventArgs e)
{
dialog = null;
}
Just a quick sketch but this should do what you want:
Window1 W = new Window1();
private void Button_Click(object sender, RoutedEventArgs e)
{
if (W.IsVisible)
W.Activate();
else
W.Show();
}
If this does not do it, maybe I have misread your question.
Edited to correct a bug.
Add this on the class constructor where you are instantiating the window. A window cannot be closed after is opened.
W.Closing += (s, e) =>
{
e.Cancel = true;
((Window)s).Hide();
};

Strange ToolStripButton click to open an OpenFileDialog behavior

I found a strange ToolStripButton double click problem. These steps will reproduce the problem:
Create a Windows Form Application.
Add a ToolStrip on the main form.
Add a ToolStripButton on the ToolStrip.
Add an OpenFileDialog on the main form.
Double click the ToolStripButton's Click event on the property toolbox.
Add this in toolStripButton1_Click method:
openFileDialog1.ShowDialog();
Start debug.
Quickly double click the ToolStripButton.
Here comes the problem. First, an open file dialog pops up, and I close it, then another dialog pops up. This shouldn't happen. I close it again, then the main form may have some redraw problem. Finally, I close the main form, but the program is still running.
Please try it yourself and let me know if all those happens.
Why those happens? What should I do to solve it?
You can use this to reproduce the problem:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace WinForm
{
class MyForm : Form
{
private IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
openFileDialog1 = new OpenFileDialog();
toolStrip1 = new ToolStrip();
toolStripButton1 = new ToolStripButton();
toolStrip1.SuspendLayout();
this.SuspendLayout();
toolStrip1.Items.AddRange(new ToolStripItem[] { toolStripButton1 });
toolStripButton1.Text = "toolStripButton1";
toolStripButton1.Click += new EventHandler(toolStripButton1_Click);
this.Controls.Add(toolStrip1);
toolStrip1.ResumeLayout(false);
toolStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
private OpenFileDialog openFileDialog1;
private ToolStrip toolStrip1;
private ToolStripButton toolStripButton1;
public MyForm()
{
InitializeComponent();
}
private void toolStripButton1_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyForm());
}
}
}
Why those happens?
I really don't know, it's a surprise for me!!
What should I do to solve it?
This is a simple workaround:
private bool clicked = false;
private void toolStripButton1_Click(object sender, EventArgs e)
{
if (clicked) return;
clicked = true;
openFileDialog1.ShowDialog();
clicked = false;
}
EDITED:
I suppose that problem is not double-click itself, but OpenFileDialog behaviour.
If you try this code the error disappears even for (accidental) double-click:
private void toolStripButton1_Click(object sender, EventArgs e)
{
using (OpenFileDialog dlg = new OpenFileDialog()
{
Title = "Open file",
Filter = "PDF files|*.pdf|All files|*.*"
})
{
dlg.ShowDialog();
Debug.WriteLine(dlg.FileName);
}
}
If you use tsb1.DoubleClickEnabled = true the error disappear... but I'm not sure this is a good solution
I decided to use this (for now):
private void toolStripButton1_Click(object sender, EventArgs e)
{
toolStripButton1.Enabled = false;
openFileDialog1.ShowDialog();
toolStripButton1.Enabled = true;
}

Categories