События потока не запускаются правильно - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть приложение формы, которое делает что-то в пользовательском экземпляре Excel.Иногда для длинных сегментов я показываю всплеск загрузки, чтобы пользователь не впал в безумие.В настоящее время пользователь работает в форме, которая была открыта на пользовательской вкладке Excel, в верхней части формы есть форма всплеска, но когда пользователь свернул экземпляр Excel (или поместил, например, браузер в фокус), форма всплеска все еще остается поверхвсе.

Я хочу, чтобы поток заметил, если Excel больше не в фокусе - скрыть всплеск - и заметить, когда он получит фокус - чтобы показать его еще раз.Текущая реализация очень противоречива: событие hide / unhide вызывается только после того, как splashform уже завершен.

Это текущий код;обратите внимание, что у меня очень мало опыта использования потоков, поэтому ниже могут быть тривиальные проблемы.

public partial class SplashForm : Form
{
    // delegates for cross-thread actions
    private delegate void HideDelegate();
    private delegate void UnhideDelegate();

    // the current instance of the splash
    private static SplashForm splashForm;

    static public void ShowSplashScreen(String message)
    {
        // the splashform displaying thread    
        Thread splashThread = new Thread(SplashForm.ShowForm);
        splashThread.IsBackground = true;
        splashThread.SetApartmentState(ApartmentState.STA);

        // the thread monitoring the focus
        Thread focusThread = new Thread(SplashForm.RunFocusMonitor);
        focusThread.IsBackground = true;
        thread.SetApartmentState(ApartmentState.STA);

        focusThread.Start(splashThread);
        splashThread.Start(message);
    }

    static private void ShowForm(object message)
    {
        splashForm = new SplashForm();
        splashForm.Visible = true;

        // show the splashform
        Application.Run(splashForm);
    }

    static private void RunFocusMonitor(object splashThread)
    {
        // create a new instance of fm
        var fm = new FocusMonitor();
        Thread target = (Thread)splashThread;

        // keep this thread alive until while the splashform is being shown to the user
        while (target.IsAlive)
        {
            Thread.Sleep(1000);
        }

        fm = null;
    }

    static private void HideFormInternal()
    {
        splashForm.Visible = false;
    }

    static private void UnhideFormInternal()
    {
        splashForm.Visible = true;
    }
}

public class FocusMonitor
{
    public FocusMonitor()
    {
        // subcribe
        AutomationFocusChangedEventHandler focusHandler = OnFocusChanged;
        Automation.AddAutomationFocusChangedEventHandler(focusHandler);
    }

    private void OnFocusChanged(object sender, AutomationFocusChangedEventArgs e)
    {
        AutomationElement focusedElement = sender as AutomationElement;
        if (focusedElement != null)
        {
            try
            {
                int processId = focusedElement.Current.ProcessId;
                using (Process process = Process.GetProcessById(processId))
                {
                    // if the process is Excel: show the splashform
                    if(process.ProcessName == "EXCEL")
                    {
                        splashForm.Invoke(new UnhideDelegate(UnhideFormInternal));
                    }
                    else // otherwise hide it
                    {
                        splashForm.Invoke(new HideDelegate(HideFormInternal));
                    }
                }
            }
            catch { }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...