Периодическая всплывающая форма - PullRequest
0 голосов
/ 27 сентября 2010

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

Теперь я использую таймеры для скрытия \ отображения этой формы, но у меня странные проблемы.Если я запускаю только процесс показа \ скрытия всплывающей формы, все в порядке, но когда я пытаюсь запустить другие потоки в базовой форме, которые переходят в поток vcl (рисование математики), поведение всплывающей формы становится странным.

Как реализовать поточно-ориентированную всплывающую форму в многопоточном приложении?Спасибо

РЕДАКТИРОВАТЬ

Странная вещь: мои настройки таймеров показывают скрытую форму с периодом 5 с.Когда процесс начинается, все в порядке.Всплывающая форма показывает и скрывает более 5 секунд, как и ожидалось.Но потом я получил несколько циклов всплывающих окон (show popup from) с паузой.Тогда снова период всплывающего окна в порядке (5 с).
Тогда мои интервалы таймера не работают правильно.Я согласен с периодом ~ 4,6 с.Но иногда между всплывающими окнами нет периодов.

Ответы [ 3 ]

3 голосов
/ 28 сентября 2010

Поскольку вы упустили много важной информации («форма ведет себя странно» может быть истолковано примерно миллионами раз, с таким же количеством решений), я собираюсь GUESS в чем ваша проблемаесть, и попытаться дать вам решение.Пожалуйста, предоставьте соответствующую информацию, если я ошибаюсь!

О TTimer:

TTimer - это простое решение, когда вам нужны некоторые сигналы синхронизации, но оно не должно быть очень точным.Вы устанавливаете таймер на «срабатывание» на заданном интервале, и Windows будет отправлять вашему приложению WM_TIMER сообщения с настроенной периодичностью.Хитрость заключается в том, что в очереди вашего приложения никогда не будет двух сообщений WM_TIMER одновременно.

Если бы вы делали часы и использовали TTimer, чтобы дать вам 1 секунду сердцебиения, вашчасы будут в основном вовремя, когда ваш компьютер простаивает, но они будут работать медленно, если ваш компьютер занят.Если процессы, выполняющие часы, заняты, часы будут работать еще медленнее.

О вашей проблеме:

Вы говорите:

Если я запускаю только Показать\ Скрыть процесс всплывающей формы все в порядке, но когда я пытаюсь запустить другие потоки в базовой форме, которые переходят к потоку vcl (рисование математики), поведение всплывающей формы становится странным.

Интерпретация: Я предполагаюthread math painting происходит где-то в потоке VCL, и это блокирует очередь сообщений вашего приложения.Этот ход приводит к тому, что ваше приложение пропускает сообщения WM_TIMER, вызывая the behaviour of popup form become strange.

Возможные решения:

Это, очевидно, сложно, не зная проблемы (опять же, странно * 1028)* - как?), но я собираюсь дать вам некоторые идеи в любом случае.Прежде всего, позвольте мне сказать вам, я не думаю, что вы можете решить вашу проблему, используя лучший таймер.Ваша проблема связана с графическим интерфейсом, а графический интерфейс является однопоточным.В то время как у некоторых фоновых потоков есть кое-что, они должны marshall to vcl thread - независимо от того, насколько точен ваш таймер, он не может помешать основному потоку VCL выполнить marshall, поэтому таймер должен будет ждатьчтобы закончить marshall, чтобы сделать то, что нужно сделать.

Получение подсказки от I need implement smoothly showing\hiding of this popup form Я предполагаю, что вам нужно несколько шагов для smooth showing\hiding, и это то, что вы используетеTTimer для.

Если вы получили код, подобный следующему: (предупреждение, это псевдокод, я сомневаюсь, что он компилируется)

procedure Timer1OnTimer(Sender:TObject);
begin
  SomeCounter := SomeCounter + 1;
  if SomeCounter > 10 then
    HidePopupForm
  else
    SetPopupFormTransparencyTo((SomeCounter * 255) div 10);
end;

Замените его примерно так:

var HideAtTime:TDateTime;
    ShownAtTime:TDateTime;

procedure Timer1OnTimer(Sender:TObject);
var ExpectedVisibleTime:TDateTime;
    ElapsedVisibleTime:TDateTime;
begin
  if Now > HideAtTime then
    HidePopupForm
  else
    begin
      ExpectedVisibleTime := HideAtTime - ShownAtTime;
      ElapsedVisibleTime := Now - ShownAtTime;
      SetPopupFormTransparencyTo(ElapsedVisibleTime/ExpectedVisibleTime*255);
    end;
end;

Общая идея этого решения состоит в том, чтобы вычислять сроки, сохранять их в TDateTime переменных, сравнивать с Now из вашего TTimer.OnTimer;Таким образом, не имеет значения, если события таймера не приходят через запрошенные интервалы, вы будете в основном вовремя со всем остальным.Конечно, отображение формы может быть не таким гладким, как хотелось бы, но оно выполнит свою работу.

0 голосов
/ 28 сентября 2010

Благодаря хорошему сообщению Cosmin Prund я разрешаю свою проблему.Проблема заключалась в следующем: фоновый поток имеет небольшую математическую процессию и часто (в цикле) маршалируется в поток VCL.Так что почти все время выполнения фонового потока он рисует свой потокобезопасный способ.

Поскольку поток vcl был очень "занят" и

background threads it can't stop the main VCL thread from doing the marshall thing, 
so the timer will need to wait for the marshall to finish in order to do what
needs to be done.

Хорошо, я решил создать свой поток bacjgroundболее независимый от vcl и вставьте

 Sleep(50);

в мой метод execute.Хорошо, я получаю "нормальное" :) поведение моих таймеров.

Но я не удовлетворен новой реакцией потока vcl.Поэтому я решаю собрать растровое изображение в потоке и назначить его графическому интерфейсу при синхронизации вместо манипулирования холстом при синхронизации.Таким образом, я ожидаю реакции vcl и поведения всплывающих окон.Спасибо за все.

0 голосов
/ 28 сентября 2010

Вы пытались использовать альтернативные таймеры?
Стандартные таймеры VCL используют основную очередь сообщений, что означает, что если ваша очередь сообщений засоряется другими потоками, отправляющими миллионы сообщений, фактическое время полностью отключается от реального времени.

...