tags:

views:

498

answers:

4

I have a strange problem with my Windows Form Application (C#). I have a form (Form1) with a NotifyIcon and a another form (Form2) in my project. Form1 has some code that basically does some XML parsing and adds a bunch of LinkLabels onto Form2. This all work fine.

On the NotifyIcon, I have a ContextMenu MenuItem (called "Refresh") with an EventHandler to, basically, run through the XML parsing on command. I also have, on the NotifyIcon, a MouseDoubleClick command which, when the system tray icon is double-clicked, it open up Form2 (using ShowDialog()) to display the link of LinkLabels. This also works fine.

I have a Button Control on Form2 (called "Close"), that is using this EventHandler code:

private void btnClose_Click(object sender, EventArgs e)
{
    this.Close();
}

to close Form2. This also works fine.

However, depending on how many times the "Refresh" ContextMenu MenuItem, on Form1's NotifyIcon, is hit, this is how many time the "Close" Button Control on Form2 must be pressed before Form2 closes. For example, if a user hits the "Refresh" MenuItem on Form1 three times, they will have to hit the "Close" Button Control on Form2 three times to it. It's almost like Form2 visibly closes, but the code doesn't seem to recognize that it is closed.

I'm new to Windows Form's development, so maybe it's a lifecycle thing I'm not aware of. Any help would be appreciated.

EDIT. I'll try to post the appropriate code:

//NotifyIcon Form (Form1)
//ico is the ID of the NotifyIcon
public partial class TrayIcon : Form
{
    Message msg = new Message(); //Form2
    ContextMenu contextMenu = new ContextMenu();

    public TrayIcon()
    {
        InitializeComponent();
    }

    private void TrayIcon_Load(object sender, EventArgs e)
    {
        contextMenu.MenuItems.Clear();
        contextMenu.MenuItems.Add(0, new MenuItem("Refresh", new System.EventHandler(ico_Refresh)));

        ico.DoubleClick += new MouseEventHandler(ico_ShowMsg);

        DoXmlParsing();
    }

    private void ico_Refresh(object Sender, EventArgs e)
    {
        TrayIcon_Load(null, null);
    }

    private void ico_ShowMsg(object Sender, MouseEventHandler e)
    {
        if (msg.Visible == false)
            msg.ShowDialog();
    }
}

On Form2 (Message) I have a Button with this Click handler code:

private void btnClose_Click(object sender, EventArgs e)
{
    this.Close();

    //I have also tried:
    if (this.Visible)
        this.Hide();
}
+2  A: 

From your explanation it seems that your Refresh MenuItem launches a new instance of your Form 2 over the previous form.

Could you show the code behind the Refresh menuitem?

ZippyV
see code posted above
+2  A: 

I think you're creating a new instance of Form2 every time, so you have to close each one...

Could you post the code of the NotifyIcon MouseDoubleClick event handler ?


UPDATE : OK, I see, that's because every time you click the menu item, it adds a new handler to the events (menuitem and notifyicon) : there is nothing to prevent duplicate handlers, so the handler is called several times. Since the form is showed modally, it closed, then reopened, then closed...

You need to register the handlers only once (in the constructor for instance). Also, you could just call DoXmlParsing in ico_Refresh

Thomas Levesque
see code posted above
+2  A: 

I'm not 100% sure from your question, as there's no code, but it sounds to me like you're using something like the following when Form2 is launched:

Form2 f = new Form2();
f.Show();

If that's the case, and the form always shows up in the exact same location, it's not that you have to close "it" that many times, it's that there are that many of them actually there and visible. Try moving the form around and seeing if there are any beneath it. :)

What I recommend instead is having one instance of the Form2 class that remains in memory and is not closed until your app exits. Show and Hide it as needed.

John Rudy
I thought of that, but when I grab the titlebar and move it around, there is only one form.
+6  A: 

I think this line is the problem:

ico.DoubleClick += new MouseEventHandler(ico_ShowMsg);

You keep adding more event handlers to the double click, but never removing them (because TrayIcon_Load is called in ico_Refresh.

After you close the dialog, the .ShowDialog() is called again however many times this event handler has been added.

recursive
Shame this hasn't been upvoted more. When I went back and re-read the question (after the code edit), I didn't spot that. Good call!
John Rudy