У меня есть приложение формы, которое делает что-то в пользовательском экземпляре 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 { }
}
}
}