Запретить анимацию в form.Show() при активации из NotifyIcon

У меня есть очень типичное хакерское решение для сворачивания в системный трей на С#:

private void MainFormResize(object sender, EventArgs e) {
        if (FormWindowState.Minimized == this.WindowState) {
            this.Hide();
            systemTrayIcon.Visible = true;
        }
}

private void systemTrayIconMouseDoubleClick(object sender, MouseEventArgs e) {
    systemTrayIcon.Visible = false;
    this.Show();
    this.WindowState = FormWindowState.Normal;  
}

В идеале я хочу, чтобы мое приложение исчезало/появлялось снова при сворачивании или повторном открытии из системного трея. Сворачивание в системный трей работает как положено - окно исчезает без задержки и появляется новый значок в трее.

Однако двойной щелчок по значку приводит к очень странным эффектам. Окно подвергается анимации изменения размера в соответствии с его положением — кажется, что окно вылетает из совершенно случайного угла экрана.

Я не хочу этого. Я просто хочу Minimize > -Poof- Disappear и Double-click > -Poof- Appear без анимации, задержек или чего-то в этом роде.

Почему в этом коде есть анимация? Если я вызываю Form.Show() в любом другом контексте, окно автоматически появляется так, как я хочу, но при вызове из NotifyIcon оно ведет себя странно. Я думал, что это может быть строка WindowState = FormWindowState.Normal, но если я ее удалю, окно не будет отображаться на переднем плане.

Изменить: эта проблема, похоже, зависит от ОС и темы. Проблема не кажется в Windows XP, но трудно сказать, потому что моя виртуальная машина немного тормозит. В Windows 7 Aero возникает проблема произвольного закадрового положения. В Windows 7 Basic/Classic он сворачивается на панель задач и снова появляется из своего старого положения на панели задач (как если бы он был на самом деле свернут на панель задач, а не на панель задач). Я не тестировал на Vista. Какие-нибудь советы?


person Corey    schedule 22.11.2010    source источник


Ответы (3)


Вы пытались изменить порядок, чтобы поставить WindowState = FormWindowState.Normal перед Show()? Я считаю, что анимация, которую вы видите, является стандартной анимацией восстановления окна. Поскольку вы вызываете Show() перед восстановлением окна, оно становится вне экрана.

Редактировать: Теперь я вижу вашу проблему - я смотрел на нее около секунды и даже пробовал IMessageFilter, но по какой-то причине не смог перехватить WM_SYSCOMMAND при сворачивании (хотя он срабатывает при восстановлении).

Одна простая вещь, которую вы можете сделать, это жить с анимацией minimize — в вашем обработчике изменения размера, непосредственно перед вызовом Hide(), установите WindowState в Normal. Вы увидите анимацию минимизации, но не максимизацию (которая на большинстве платформ менее заметна).

person Philip Rieck    schedule 22.11.2010
comment
Если я это сделаю, то окно вообще никогда не будет отображаться. Он появляется на панели задач, но щелчок по нему, чтобы открыть окно, просто сворачивает его. - person Corey; 23.11.2010
comment
Я добавил немного дополнительной информации в свой пост, если это вообще поможет. - person Corey; 23.11.2010
comment
Спасибо за подсказку, этот эффект немного более желателен. Теперь проблема заключается в том, что изменение WindowState повторно вызывает MainFormResize, и я предполагаю, что что-то внутреннее, вызванное из MainFormResize, которое я не могу контролировать, пытается отобразить окно при вызове WindowState.Normal. Что мне остается, так это то, что форма минимизируется, затем снова появляется на долю миллисекунды (с элементами управления затемненными, потому что система не может загрузить форму так быстро), а затем скрывает ее. Это довольно странно. - person Corey; 23.11.2010
comment
@Corey Вы можете заблокировать это, поместив логическое значение защиты в переопределение OnResize и не вызывая базовую реализацию, но в любом случае это будет выглядеть немного странно. Реальный способ сделать это описан здесь - заголовок stackoverflow.com/questions/46918/. Но обратите внимание, что это включает анимацию. В противном случае вы застряли с использованием P/Invoke и IMessageFilter - я посмотрю на это завтра, если вы все еще застряли (сейчас нет компьютера) - person Philip Rieck; 23.11.2010

Если вам нужно скрыть окно во время работы программы, лучше всего создать класс, производный от ApplicationContext и отображающий NotifyIcon. Затем вы используете этот класс вместо формы в Application.Run.

class TaskTray : ApplicationContext
{
    private NotifyIcon _Icon;
    public TaskTray()
    {
       _Icon = new NotifyIcon();
       //...
    )
}
static void Main()
{
    Application.Run(new TaskTray());
}
person Joel Lucsy    schedule 23.11.2010

По крайней мере, можно создать анимацию там, где она должна - вам нужно переместить свернутое окно рядом с областью уведомлений в трее: см. мой взломать здесь

person maf-soft    schedule 22.04.2016