How to create notifyIcon without Form? [duplicate] - c#

This question already has answers here:
How to run an "empty" Windows Application that only has a NotifyIcon?
(3 answers)
Closed 6 years ago.
I added notifyIcon to the container and set Visible = true option, but no icon appeared.
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
this.SuspendLayout();
//
// notifyIcon1
//
this.notifyIcon1.Text = "Manager";
this.notifyIcon1.Visible = true;
//
// Form1
//
this.ClientSize = new System.Drawing.Size(0, 0);
this.ShowInTaskbar = false;
this.Visible = false;
}

I believe you need to add a few more events for this to work, Hope this helps
public Form2()
{
InitializeComponent();
notifyIcon1.Icon = SystemIcons.Asterisk;
notifyIcon1.DoubleClick += new EventHandler(notifyIcon1_DoubleClick);// to bring it back
this.Resize += new EventHandler(Form2_Resize);// to move it to tray
}
void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
Show();
this.BringToFront();
this.WindowState = FormWindowState.Normal;
}
void Form2_Resize(object sender, EventArgs e)
{
if (this.WindowState ==FormWindowState.Minimized)
Hide();
}

notify Icon is shown when form is minimize. Try this
this.WindowState = FormWindowState.Minimized;

Related

How can I wait until form handle has been created before invoke? [duplicate]

This question already has answers here:
"Invoke or BeginInvoke cannot be called on a control until the window handle has been created" only occurs the second time form opens
(1 answer)
Invoke or BeginInvoke cannot be called on a control until the window handler has been created
(1 answer)
Closed 1 year ago.
I have Windows Form project that turns one format of csv file into another.
I am trying to show the converting progress while converting.
Converting method throws an exception if converting fails.
When converting fails, I close ConvertingScreen but when I close ConvertingScreen System.InvalidOperationException occurs.
invoke or begininvoke cannot be called on a control until the window handle has been created
It seems it never happens if I add some waits before I close. I have tried checking HandleCreated but it didnt go well. I used to do this kind of jobs by adding only visible label while it is on progress. This is my first time doing such like this way. Is this bad practice? If not how can I fix this? Below is simple code that can describe everything what is happening to me.
// MainForm
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
ConvertingScreen.ShowScreen();
// Converts here and results in failure so throwing an exception
throw new NotImplementedException();
}
catch (Exception)
{
ConvertingScreen.CloseForm();
MessageBox.Show("error");
}
}
}
// ConvertingScreen
public class ConvertingScreen : Form
{
public ConvertingScreen()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
// label1
this.label1.Font = new System.Drawing.Font("MS UI Gothic", 11F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(128)));
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(316, 22);
this.label1.TabIndex = 0;
this.label1.Text = "";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
// ConvertingScreen
this.BackColor = System.Drawing.Color.LightGray;
this.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.ClientSize = new System.Drawing.Size(340, 40);
this.ControlBox = false;
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size(340, 40);
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(340, 40);
this.Name = "ConvertingScreen";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "ConvertingScreen";
this.TopMost = true;
this.ResumeLayout(false);
}
private Label label1;
private delegate void CloseDelegate();
private delegate void UpdateTextDelegate(string text);
private static ConvertingScreen form;
public static void ShowScreen()
{
if (form != null) return;
form = new ConvertingScreen();
Thread thread = new Thread(new ThreadStart(ConvertingScreen.ShowForm));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
private static void ShowForm()
{
if (form != null) Application.Run(form);
}
public static void CloseForm()
{
form?.Invoke(new CloseDelegate(ConvertingScreen.CloseFormInternal));
}
private static void CloseFormInternal()
{
if (form != null)
{
form.Close();
form = null;
}
}
public static void Update(string text)
{
if (form != null) form.UpdateLabel(text);
}
private void UpdateLabel(string text)
{
if (InvokeRequired)
{
this.Invoke(new UpdateTextDelegate(UpdateLabel), new object[] { text });
return;
}
label1.Text = text;
}
}

c# Why can I not return my application from minimize?

I have googled this and all the sites I have seen tell me the same thing for minimizing my app and then returning it to normal. I can minimize it fine but when I click on the icon in the tray then nothing happens. Here is my code.
private void Form1_SizeChanged(object sender, EventArgs e)
{
bool PointerNotOnTaskbar = Screen.GetWorkingArea(this).Contains(Cursor.Position);
if (this.WindowState == FormWindowState.Minimized && PointerNotOnTaskbar)
{
notifyIcon1.Icon = SystemIcons.Application;
this.ShowInTaskbar = false;
notifyIcon1.Visible = true;
}
}
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
this.ShowInTaskbar = true;
WindowState = FormWindowState.Normal;
notifyIcon1.Visible = false;
}
I have also tried
this.WindowState = FormWindowState.Normal;
Comment out this: this.ShowInTaskbar = false;
If the form is minimized and not visible in taskbar will take a spell to bring it back!

Nothing happens when I close maximized MDI child form

I have Form1 with 2 radio buttons (rb1 and rb2) and one ordinary button (btn). When I click on btn I should open Form2, as MDI child of Form1 if rb1 is checked, or as ordinary Dialog if rb2 is checked. Also, there can only be one Form2 opened at any moment.
This is my code:
public partial class Form1 : Form
{
Form2 f2;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (f2 != null)
{
MessageBox.Show("Close form!");
return;
}
f2 = new Form2();
if (radioButton1.Checked == true)
{
this.IsMdiContainer = true;
f2.MdiParent = this;
f2.Show();
}
else
{
f2.Show();
}
f2.FormClosed += f2_FormClosed;
}
void f2_FormClosed(object sender, FormClosedEventArgs e)
{
this.IsMdiContainer = false;
f2 = null;
}
}
Everything works as it should except when I maximize Form2 as MDI child and then close it. After that screen stays the same (as I even didn't closed Form2) but I am able to open new Form2, and then Form1's title is "Form1 - [Form2]", and if I repeat the process it would be "Form1 - [Form2] - [Form2]", etc.
I figured out that I my f2_FormClosed method should be
void f2_FormClosed(object sender, FormClosedEventArgs e)
{
f2.Hide(); // <<<<<<<<-----------NEW
this.IsMdiContainer = false;
f2 = null;
}
but I don't know why; Form2 should be closed, I don't know why should I have to hide it?!
Thanks!
I agree with Hans, switching IsMdiContainer at run-time is wonky and is likely to produce other side-effects you haven't seen yet.
Seriously consider a different design for your app.
With that in mind, here's probably the stupidest hack I'll post all day:
public partial class Form1 : Form
{
Form2 f2;
System.Windows.Forms.Timer tmr = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
tmr.Interval = 100;
tmr.Enabled = false;
tmr.Tick += delegate (object sender, EventArgs e) {
tmr.Stop();
this.IsMdiContainer = false;
};
}
private void button1_Click(object sender, EventArgs e)
{
if (f2 != null)
{
MessageBox.Show("Close form!");
return;
}
f2 = new Form2();
f2.FormClosed += delegate(object sender2, FormClosedEventArgs e2) {
f2 = null;
};
if (radioButton1.Checked == true)
{
this.IsMdiContainer = true;
f2.FormClosed += delegate(object sender3, FormClosedEventArgs e3) {
tmr.Start();
};
f2.MdiParent = this;
}
f2.Show();
}
}
*I originally tried Invoking the call to change IsMdiContainer but that didn't work, so I switched to the Timer. Stupidity that works. Use this solution with caution...

How to draw overlay window winform apps c#

my request is suppose i have two sdi form. one sdi main form has button and when user click on that button then a overlay semi transparent window will appear and cover the main sdi form and as well as another sdi will come on top of the over lay window.
here is my overlay window code
namespace CSRAssistant
{
public partial class MaskedDialog : Form
{
static MaskedDialog mask;
static Form frmContainer;
private Form dialog;
private UserControl ucDialog;
private MaskedDialog(Form parent, Form dialog)
{
this.dialog = dialog;
this.FormBorderStyle = FormBorderStyle.None;
this.BackColor = System.Drawing.Color.Black;
this.Opacity = 0.50;
this.ShowInTaskbar = false;
this.StartPosition = FormStartPosition.Manual;
this.Size = parent.ClientSize;
this.Location = parent.PointToScreen(System.Drawing.Point.Empty);
parent.Move += AdjustPosition;
parent.SizeChanged += AdjustPosition;
}
private MaskedDialog(Form parent, UserControl ucDialog)
{
this.ucDialog = ucDialog;
this.FormBorderStyle = FormBorderStyle.None;
this.BackColor = System.Drawing.Color.Black;
this.Opacity = 0.50;
this.ShowInTaskbar = false;
this.StartPosition = FormStartPosition.Manual;
this.Size = parent.ClientSize;
this.Location = parent.PointToScreen(System.Drawing.Point.Empty);
parent.Move += AdjustPosition;
parent.SizeChanged += AdjustPosition;
}
private void AdjustPosition(object sender, EventArgs e)
{
Form parent = sender as Form;
this.Location = parent.PointToScreen(System.Drawing.Point.Empty);
this.ClientSize = parent.ClientSize;
}
//
public static DialogResult ShowDialog(Form parent, Form dialog)
{
mask = new MaskedDialog(parent, dialog);
dialog.StartPosition = FormStartPosition.CenterParent;
mask.MdiParent = parent.MdiParent;
mask.Show();
DialogResult result = dialog.ShowDialog(mask);
mask.Close();
return result;
}
public static DialogResult ShowDialog(Form parent, UserControl dialog)
{
mask = new MaskedDialog(parent, dialog);
frmContainer = new Form();
frmContainer.ShowInTaskbar = false;
frmContainer.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
frmContainer.StartPosition = FormStartPosition.CenterParent;
frmContainer.Height = dialog.Height;
frmContainer.Width = dialog.Width;
frmContainer.Controls.Add(dialog);
mask.MdiParent = parent.MdiParent;
mask.Show();
DialogResult result = frmContainer.ShowDialog(mask);
frmContainer.Close();
mask.Close();
return result;
}
public static void CloseDialog()
{
if (frmContainer != null)
{
frmContainer.Close();
}
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// MaskedDialog
//
this.ClientSize = new System.Drawing.Size(284, 262);
this.Name = "MaskedDialog";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MaskedDialog_FormClosing);
this.Load += new System.EventHandler(this.MaskedDialog_Load);
this.ResumeLayout(false);
}
private void MaskedDialog_Load(object sender, EventArgs e)
{
}
private void MaskedDialog_FormClosing(object sender, FormClosingEventArgs e)
{
}
}
}
this way i am calling my overlay when user click on main sdi button.
Form2 f2 = new Form2();
f2.Show();
MaskedDialog.ShowDialog(this, f2);
f2.Dispose();
f2 = null;
when i am running the code and MaskedDialog.ShowDialog(this, f2); is calling then i am getting a error....the error message is Form that is already visible cannot be displayed as a modal dialog box. Set the form's visible property to false before calling showDialog.
so i am not being able to understand where i am making the mistake. anyone can help me to fix the problem. thanks
You're doing this wrong - call mask.ShowDialog(), not mask.Show() and dialog.ShowDialog(). The error message is pretty clear - you can't ShowDialog a form that's already visible - and that's exactly what you're doing in dialog.ShowDialog(mask);.
Or, in a way that probably more closely shows what you want to do, when calling MaskedDialog.ShowDialog, do this:
Form2 f2 = new Form2();
MaskedDialog.ShowDialog(this, f2);
In other words - don't show the form you're going to ShowDialog. It's going to be made visible by the ShowDialog call.

Opening Winform from taskbar

I have a Winform, which is hidden initially on startup.
Thereafter the user is free to click the notification icon in the bottom and show it if they want, and when it is minimized it needs to go back into the system tray.
It starts in the tray fine - no problems. When you click to show it the first time though it appears, then for a fraction of a second looks like it is disappearing, then comes back. So it looks like it flickers a bit.
Then when you minimize it, it goes into the system tray as it should which is fine. When you click to show it again though (any time after you have done it once) it sort of glides in from either the system tray or the taskbar, I would prefer it to just appear, without the little animation.
public class Program : Form
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Program());
}
private NotifyIcon trayIcon;
private ContextMenu trayMenu;
public Program()
{
trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Exit", OnExit);
trayMenu.MenuItems.Add("Show", OnShow);
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 = false;
ShowInTaskbar = false;
base.OnLoad(e);
}
protected override void OnResize(EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
Visible = false;
ShowInTaskbar = false;
}
base.OnResize(e);
}
private void OnExit(object sender, EventArgs e)
{
Application.Exit();
}
private void OnShow(object sender, EventArgs e)
{
Visible = true;
ShowInTaskbar = true;
TopMost = true;
WindowState = FormWindowState.Normal;
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
trayIcon.Dispose();
}
base.Dispose(isDisposing);
}
}
Any pointers on how to just get it to appear properly would be really appreciated.
Update
I have found the cause of the flickering, it happened when TopMost is set last, after is has been shown, so it redraws it on top, which makes sense.
So as it stands, it's just getting it to appear and disappear without the animations.
EDIT: You should only set the Visibility property in Onload(), just use Show() and Hide() to avoid the animations and be sure to change the WindowState accordingly.
I put your code into a regular Form (not in the Program.cs file) and deleted all superfluous code. This is what I ended up with and it doesn't show the "double" animation.
public partial class Form1 : Form
{
private NotifyIcon trayIcon;
private ContextMenu trayMenu;
public Form1()
{
InitializeComponent();
this.ClientSize = new System.Drawing.Size(284, 262);
this.Name = "Program";
trayMenu = new ContextMenu();
trayMenu.MenuItems.Add("Exit");
trayMenu.MenuItems.Add("Show", FormShow);
trayIcon = new NotifyIcon();
trayIcon.Text = "MyTrayApp";
trayIcon.Icon = new Icon(SystemIcons.Application, 40, 40);
trayIcon.ContextMenu = trayMenu;
trayIcon.Visible = true;
TopMost = true;
Resize += new EventHandler(Form1_Resize);
}
void Form1_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
ShowInTaskbar = false;
Hide();
trayIcon.Visible = true;
}
}
void FormShow(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
WindowState = FormWindowState.Normal;
}
ShowInTaskbar = true;
Show();
Focus();
trayIcon.Visible = false;
}
protected override void OnLoad(EventArgs e)
{
Visible = false;
ShowInTaskbar = false;
}
}

Categories