Search code examples
c#winformspreloadernotifyicon

My program's notifyicon get duplicated when using Form.Show() to call a preloader form


EDIT: Silly me. My preloader actually shows up all the time even with simple Loading.Show(); but it just was below my web browser. I already posted a solution below. Please check it up if you interested.

My program has no form but shows as a notifyicon in the notification area (My main form is actually hidden to use as dummy form for notifyicon and other controls). It run by getting called from web browser using URI scheme (tkh). If my program is already running and user called it from browser, it will do things according to its argument. For example, if an user called it with tkh:readCard, my program will do stuff in readCard function.

Here's my code for reading argument from URI scheme

public string CommandLine { get; set; }
        public bool CheckForProtocolMessage(Uri uri)
        {
            if (uri.ToString().Length > 1)
            {
                string[] args = uri.ToString().Split(':');
                CommandLine = args[1];
                if (args[0].Trim().ToUpper() == "TKH" && args.Length > 1)
                {
                    if (args[1].Length > 1)
                    {
                        switch (args[1].Trim().ToUpper())
                        {
                            case "READCARD":
                                if (hasCardReader == true)
                                {
                                    var bw_readCard = new BackgroundWorker { WorkerReportsProgress = true };                                        
                                    bw_readCard.DoWork += delegate
                                    {
                                        preloaderShow();
                                        readCard();
                                        preloaderClose();
                                    };
                                    bw_readCard.ProgressChanged += delegate { };
                                    bw_readCard.RunWorkerCompleted += delegate { };
                                    bw_readCard.RunWorkerAsync();
                                    bw_readCard.Dispose();
                                    return true;
                                }
                                else
                                {
                                    MessageBox.Show("Try again", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                    return false;
                                }


                            case "READCARD_IDONLY":
                                if (hasCardReader == true)
                                {
                                    var bw_readCard_IDOnly = new BackgroundWorker { WorkerReportsProgress = true };
                                    bw_readCard_IDOnly.DoWork += delegate
                                    {
                                        preloaderShow();
                                        readCard_IDonly();  
                                        preloaderClose(); 
                                    };
                                    bw_readCard_IDOnly.ProgressChanged += delegate { };
                                    bw_readCard_IDOnly.RunWorkerCompleted += delegate { };
                                    bw_readCard_IDOnly.RunWorkerAsync();
                                    bw_readCard_IDOnly.Dispose();
                                    return true;
                                }
                                else
                                {
                                    MessageBox.Show("Try again", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                    return false;
                                }
                        }       
                    }
                }
            }
            return false;
        }

preloaderShow(); and preloaderClose(); are for show and close a preloader form. (My preloader form named "Loading")

Here's the preloaderShow(); function

private void preloaderShow()
        {
            Loading Loading = new Loading();
            Loading.Show();
        }

and the preloaderClose(); function

 private void preloaderClose()
        {
            Loading Loading = new Loading();
            Application.OpenForms
                .OfType<Form>()
                .Where(form => String.Equals(form.Name, "Loading"))
                .ToList()
                .ForEach(form => form.Close());
        }

My problem is if the program isn't running, the preloader shows up and do stuff normally. But if it already running, the preloader won't show up but stuff in readCard(); and readCard_IDOnly(); works normally.

If I change my preloaderShow(); like this,

private void preloaderShow()
        {
            Loading Loading = new Loading();
            Form1 Form1 = new Form1(); // Declared this even without put Form1 into .Show() also make the program's notifyicon duplicate.
            Loading.Show(Form1);
        }

the preloader will show up and the notifyicon get duplicated Like below

but notifyicon will duplicated and cannot be closed

I will need to close down "main" notifyicon to make it all gone.

What do I need to do? Thanks.


Solution

  • Actually, the preloader shows up but it was below my web browser all the time. All I need to do is create these following override functions to make it always on top (Also make my Windows not going to focus this preloader form.)

    protected override bool ShowWithoutActivation { get { return true; } }
    protected override CreateParams CreateParams
    {
        get
        {
            int WS_EX_TOPMOST = 0x00000008;
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= WS_EX_TOPMOST;
            return cp;
        }
    }
    

    Referred to this thread: https://stackoverflow.com/a/10727337/4535654