| | | | |
Окно отображающее ход выполнения длительной операции | Полный текст материала
Другие публикации автора: Cepгей Poщин
Цитата или краткий комментарий: «... Предлагаю вашему вниманию небольшой модуль, в котором содержится потомок класса TThread, позволяющий отображать окно с текстом, пиктограммой
и индикатором хода выполнения операции. ...» |
Важно:- Страница предназначена для обсуждения материала, его содержания, полезности, соответствия действительности и так далее. Смысл не в разборке, а в приближении к истине :о) и пользе для всех.
- Любые другие сообщения или вопросы, а так же личные эмоции в адрес авторов и полемика, не относящаяся к теме обсуждаемого материала, будут удаляться без предупреждения авторов, дабы не мешать жителям нормально общаться.
- При голосовании учитывайте уровень, на который расчитан материал. "Интересность и полезность" имеет смысл оценивать относительно того, кому именно предназначался материал.
- Размер одного сообщений не должен превышать 5К. Если Вам нужно сказать больше, сделайте это за два раза. Или, что в данной ситуации правильнее, напишите свою статью.
Всегда легче осудить сделанное, нежели сделать самому. Поэтому, пожалуйста, соблюдайте правила Королевства и уважайте друг друга.
Добавить свое мнение.
| | Содержит полезные и(или) интересные сведения | [1] | 16 | 94.1% | | | | Ничего особенно нового и интересного | [2] | 1 | 5.9% | | | | Написано неверно (обязательно укажите почему) | [3] | 0 | 0% | | Всего проголосовали: 17 | | | Все понятно, материал читается легко | [1] | 10 | 83.3% | | | | Есть неясности в изложении | [2] | 2 | 16.7% | | | | Непонятно написано, трудно читается | [3] | 0 | 0% | | Всего проголосовали: 12 |
[TThread] [Потоки (нити) Threads] [Обработка длительных процессов (отображение/реакция и т.п.)]
Отслеживать это обсуждение
Всего сообщений: 4822-07-2015 15:56сообщение от автора материала Михаил, если Вас интересует разрешение автора, то пожалуйста.
Обращаю внимание, что здесь представлена не самая последняя версия. Последнюю версию можно скачать с сайта http://roschinspb.narod.ru/develop.html#xslt |
|
22-07-2015 00:41Не знаю, можно ли здесь выложить код, но я уже сам добавил возможность бесконечного ПБ, возможность скрыть кнопку "Отмена" без выключения св-ва Enabled (т.е. окно про-прежнему можно будет таскать), возможность настройки скорости анимации ПБ и его цвета (последнее независимо от цвета самого окна, на основе к-го обычно рассчитывается цвет ПБ). |
|
16-07-2015 07:20Хотелось бы видеть возможность включение режима "бесконечного" прогресс-бара (marque) в классах окон ожидания.
|
|
22-05-2013 04:51К сожалению, мои попытки вызвать SetWindowPos не сохранились, но они не приводили к успеху.
Ваш вариант работает, большое спасибо |
|
21-05-2013 15:15сообщение от автора материала Так можно как-то обновить окно? Можно. Есть метод Invalidate. Если Вы всё равно решили переделывать исходними поместите его в public, или создайте своего наследника. Другое дело что окошко и так обрабатывает сообщения.
В вашем случае оно просто попадает под главную форму. Поднять его наверх можно примерно так: F := TThreadWindow.Show;
Sleep(4000);
if Assigned(F) and (F.WND <> 0) then
begin
SetWindowPos(F.WND, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE)
end;
Sleep(4000); WND — это хэндл окна, его можно использовать в API функциях. |
|
21-05-2013 04:38Я могу обновлять окно из самого процесса.
Так можно как-то обновить окно? |
|
20-05-2013 18:28сообщение от автора материала OnActivate не сработает пока выполняется задача, так что увы.
Сделайте более мелкое окошко где-нибудь в углу экрана. |
|
20-05-2013 11:49Можно как-то принудительно перерисовать окно TThreadWindow?
моим клиентам не понравилось, что окно сверху всех окон. После закомментирования флага WS_EX_TOPMOST окошко исчезает после переключения на другое приложение, но уже не появляется в моем приложение. Так вот, хотелось бы перерисовать окно по событию OnActivate главной формы. Invalidate недоступен, Refresh тоже |
|
14-05-2013 12:39сообщение от автора материала >>не заметил
Cтранное у Вас имя в профиле: Елена Друзенко :)
P.S. Спасибо на добром слове. |
|
13-05-2013 16:47Спасибо за молниеносный ответ :)
У вас в старой версии написано
// Доступность окна (можно ли таскать мышью и т.п.)
property Enabled: boolean read fEnabled write fEnabled;
А в новой еще и добавлено про кнопку Отмена, извините, не заметил
А чего велосипеды изобретать? работает же, потребность есть. Такого компонента, тем более бесплатного, что-то не нагугливается... Особенно понравилось, что подхватывает иконку проекта.
|
|
13-05-2013 13:57
13-05-2013 11:00Спасибо за статью и за окошко.
Ошибку под XP подтверждаю:
На некоторых Windows XP работает корректно, а на некоторых через несколько секунд после отображения окна появляется белый фон на весь экран за пределами окна и присутствует до закрытия окна (на лицензионных виндах всегда так было). Не знаю, с чем это связано. Может кто-нибудь подскажет, в чем может быть дело? Компилировалось в D7.
Однако после перехода на более свежую версию, скачанную с Вашего сайта, ошибка исчезла.
Однако возник вопрос: можно ли убрать кнопку Отмена? (раньше ее не было)
беглый просмотр кода показал, что нет возможности включить/отключить показ кнопки, кроме как убрать фрагменты кода по ее отрисовке |
|
20-08-2009 14:51сообщение от автора материала почему везде string, а не WideString? Даже не знаю... Наверно по тому, что когда я писал первую версию о юникоде еще не задумывался, а когда писал вторую версию, уже не задумывался в связи с выходом Delphi2009 :) |
|
20-08-2009 08:39WindowThread.pas очень понравился, но почему везде string, а не WideString? |
|
29-05-2009 16:13сообщение от автора материала AlphaBlendValue приводит к вызову процедуры TThreadWindow.UpdateBlend которая в общих чертах делает тоже самое.
Не подскажете, как сделать, чтобы само окно было прозрачным, а видимым был только прогресс-бар? Делаете окно размером с прогрессбар и перекрываете метод UpdateLayout, в нем ElementPos.ProgressRect делаете равным ClientRect. Дополнительно можно перекрыть DrawIcon, DrawBorder и т.п. для собственной перерисовки соответствующих элементов.
Если нужно чтобы прогрессбар был непрозрачным, а остальное полупрозрачным, то это более запущеный случай, видимо придётся делать два окна (одно под другим). |
|
29-05-2009 06:33Cepгей Poщин, спасибо, очень полезная статья!
Не подскажете, как сделать, чтобы само окно было прозрачным, а видимым был только прогресс-бар? Установка AlphaBlendValue := 0, влияет на все элементы окна :(
PS Попытался использовать procedure TransparentWindow(Level: byte; Wnd: HWND), предложенную Моральный_урод, но что передавать в качестве второго параметра?
Пробовал
F := TThreadWindow.Show;
F.TransparentWindow(0, F.WND);
- никакой реакции... |
|
01-05-2009 08:16сообщение от автора материала наверное заюзаю у себя в дипломе Зачетку заслать не забудьте :)
Кстати заметил, что размер в комментарии к файлу остался 40Кб и дата 4/18/2006, хотя должно быть 120Кб и 4/16/2009. |
|
28-04-2009 11:01Спасибо, наверное заюзаю у себя в дипломе ;-) |
|
20-04-2009 03:26Приятно, что моя статья хоть кому-то пригодилась =) |
|
05-02-2009 05:07сообщение от автора материала Про изменение прозрачности написано в предыдущем сообщении. Плюс к этому создаёте таймер SetTimer, KillTimer, и по таймеру меняете прозрачность от 0 до 255.
Ошибка - не может найти CWindowThread,CSplashWindow Наверно разумнее было бы разобраться с этой ошибкой. Как ставили компоненты?
P.S. в личную почту шлите. |
|
05-02-2009 01:45Уважаемый, Сергей!
Подскажите как добавить в Ваш код загрузку изображения по типу как сделано у Вас http://roschinspb.narod.ru/develop.html#CSplash ?
Скачал с сайта. Пытаюсь компилировать в D2007. Ошибка - не может найти CWindowThread,CSplashWindow.
Спасибо. |
|
03-12-2008 19:46Отличный компонент, автору спосибо!
Вот, добавил прозрачность окна:
public
...
procedure TransparentWindow(Level: byte; Wnd: HWND);
procedure TThreadWindow.TransparentWindow(Level: byte; Wnd: HWND);
type
TLayeredWndAttr = function(hwnd: integer; color: integer; level: integer; mode: integer): integer; stdcall;
var
LayeredWndAttr: TLayeredWndAttr;
begin
LayeredWndAttr:=GetProcAddress(GetModuleHandle('user32.dll'), 'SetLayeredWindowAttributes');
SetWindowLong(Wnd, GWL_EXSTYLE, WS_EX_LAYERED);
LayeredWndAttr(Wnd, RGB(0,0,0), Level*255 div 100, LWA_ALPHA);
end; |
|
01-12-2008 07:06Не плохая задумка. Автору спасибо. Я с подобной задачей столкнулся при открытии набора данных. Лично я хотел сделать нечто подобное лишь в информативном плане. То есть делаем то-то, выводим информационное окно о том что делаем и когда программа заканчивает свои действия, то закрываем информационное окно.
Данный модуль можно адаптировать под любые задачи при выполнении определенных действий. :-) |
|
17-02-2008 14:43сообщение от автора материала На вашем сайте не смог скачать последнюю версию Что с зеркала тоже http://roschinspb.narod.ru ? Ну значит не судьба :( |
|
17-02-2008 08:04Сергей, компонент брал на delphikingdom полгода назад. На вашем сайте не смог скачать последнюю версию. Было бы интересно на нее взглянуть. |
|
16-02-2008 12:54сообщение от автора материала Версию с моего сайта проверяли? У меня лицензионная винда и на ней такого не наблюдается.
|
|
16-02-2008 07:05На некоторых Windows XP работает корректно, а на некоторых через несколько секунд после отображения окна появляется белый фон на весь экран за пределами окна и присутствует до закрытия окна (на лицензионных виндах всегда так было). Не знаю, с чем это связано. Может кто-нибудь подскажет, в чем может быть дело? Компилировалось в D7. |
|
25-07-2007 09:03А у тебя небыло проблем с отрисовкой Caption а то у меня у класическом стиле не отображает его |
|
18-07-2007 16:42сообщение от автора материала Так держать, onix, успехов!
P.S. Можете посмотреть еще мой сайт, там есть вариант с заголовком. |
|
18-07-2007 06:45я тут несколько его переделал добавил кнопу и свойств несколько но вот долблюсь с Caption окна немогу его нормально отобразить |
|
21-04-2006 09:33сообщение от автора материала Нам не дано предугадать,
Как слово наше отзовется,-
И нам сочувствие дается,
Как нам дается благодать...
©Тютчев Ф. И. |
|
21-04-2006 07:50>>>Про GUI я точно не писал.
Поскольку это окно работает в своем собственном потоке и не использует VCL компоненты есть следующие достоинства:
1. можно использовать в консольных приложениях;
т.е. основное предназначение это использование в "обычных программах" создаваемых Delphi (т.е. GUI) и как дополнительный бонус можно использовать в консольных. |
|
21-04-2006 06:10сообщение от автора материала Вы хоть свою статью внимательно читали? Да я её вообще не читал, я её писал! Про GUI я точно не писал. беспокоиться об уверичении размера программы уже позно Лучше поздно, чем ни когда
Если серьезно, то тут речь идет о личных предпочтениях. Я думаю, что в общем случае программа должна работать максимально одинаково во всех версиях компилятора, что бы не было всяких неожиданностей. К примеру я решил перехватывать ошибку EOSError в работая BDS2006, а в D5 вместо неё EWin32Error. Кому такой подход не нравится, пусть удаляет всё лишнее (ломать - не строить). Если знания позволяют то не проблема, а если не позволяют, то документация не поможет.
Сообщения unsafe type, unsafe code советую не выводить, других способов от них избавиться я не знаю.
Правильнее было бы использовать нить в качестве сервера Писать полноценное многопоточное приложение на порядок сложнее. И этого надо избегать везде, где это только можно и уж совершенно неоправдано делать это ради отображения одного окошка. Потом есть такие операции как запись в маленький файл которые обычно выполняются моментально, но иногда несколько секунд (в случае засыпания диска), что же для сохранения переменной в ini делать свою нить? Думаю, что это не практично. По поводу оформления, полагаю, что пользователь подумает "надо же какая красота!" :o) |
|
21-04-2006 04:03Правильнее было бы использовать нить в качестве сервера , чтобы она сообщала о прогрессе выполнения без всяких VCL через callback или же асинхронно (PostMessage, например). Последнее важно в случае, если синхронная реакция клиентской части занимает много времени (рисование в чарте и т.п.). Об этом были несколько статей в королевстве.
И вообще, что будет, если в неповторимом дизайне проги появится "левое" окошко с совершенно другим оформлением ?
С уважением, Shvonder. |
|
21-04-2006 03:21>>>Добавление Forms в несколько раз увеличивает размер exe-шника
Вы хоть свою статью внимательно читали?
В статье идет разговор о GUI приложении написанном на обычном VCL DELPHI без всяких оптимзаций (KOL, чистый WINAPI), поддержка консольных заявлена как дополнитльный бонус.
А потому, Forms увас уже есть с вероятностью 0,99(9) и беспокоиться об уверичении размера программы уже позно.
Для консольных это может иметь значение, но тогда просто опишите в документации где взять и куда вставить нужные функции, если программер озаботится размером программы. Или сделайте условный include.
>>>EWin32Error приводит к [Warning] WindowThread.pas(122): Symbol 'EWin32Error' is deprecated.
У меня нет символа EWin32Error в той версии что скачал 20.04 и после удаления дублей. В Д5 все компилируется чисто, а в Д7 куча предупреждений о unsafe type, unsafe code. |
|
20-04-2006 11:18сообщение от автора материала Спасибо, но
- EWin32Error приводит к [Warning] WindowThread.pas(122): Symbol 'EWin32Error' is deprecated.
- Добавление Forms в несколько раз увеличивает размер exe-шника
Это конечно не смертельно, но не приятно.
|
|
20-04-2006 08:14RaiseLastOSError в Delphi 5 называется RaiseLastWin32Error, а потому нужно замить на
procedure RaiseLastOSError;
begin
RaiseLastWin32Error;
end;
Остальные функции находятся в модуле Forms.
Модуль SysUtils перенести в секции реализации
и привести к такому виду
uses SysUtils {$IFDEF VER130}, forms{$endif} ;
Константы WS_EX_LAYERED и LWA_ALPHA можно удалить, они не используются. Тоже самое с
resourcestring
SOSError = 'System Error. Code: %d.'+#13#10+'%s';
SUnkOSError = 'A call to an OS function failed';
type
PBoolean=^Boolean;
EOSError=class(EWin32Error)
end;
|
|
18-01-2006 13:47сообщение от автора материала В модуле SysUtils описана функция
procedure RaiseLastOSError;
var
LastError: Integer;
Error: EOSError;
begin
LastError := GetLastError;
if LastError <> 0 then
Error := EOSError.CreateResFmt(@SOSError, [LastError,
SysErrorMessage(LastError)])
else
Error := EOSError.CreateRes(@SUnkOSError);
Error.ErrorCode := LastError;
raise Error;
end;
Если в Delphi 5 её нет, то можно добавить.
А в модуле Classes описаны процедуры AllocateHWnd, DeallocateHWnd. Поскольку в данном случае это методы, то возможно, поможет если их вызывать подставив спереди self.
|
|
18-01-2006 02:14По-моему, полезная штука. Но при попытке скомпилировать предложенные исходники моя Delphi5 почему-то не понимает некоторые имена:
AllocateHWnd, DeallocateHWnd, а также RaiseLastOSError :( .
Или может, я сам торможу и что-то не прописал в uses? |
|
31-10-2005 07:58
31-10-2005 03:19"Ни каких событий в стиле VCL здесь быть не может, т. к. это потребует синхронизации с основным потоком" Это совсем не так, поскольку кнопка может быть реализована на WinApi и при нажатии на ней просто отсылать сообщение потоку или просто вызывать спецальную процедуру. В даной ситуации Synchronize здесь явно лишний. Разумеется прерывание выполнения придется реализовывать самому, но тут нечего неподелаеш. Неможет автор предусмотреть ползовательский код. |
|
26-10-2005 08:29сообщение от автора материала Ни каких событий в стиле VCL здесь быть не может, т. к. это потребует синхронизации с основным потоком (см. Synchronize), что в свою очередь обяжет при выполнении длительной операции обрабатывать события. Тогда вышеописанное окно будет ждать очередной обработки и вести себя точно так же как обычная VCL форма (только с меньшей функциональностью). Тогда смысл этого модуля вообще теряется.
P. S. Часы, кнопки и т.д. только за $ :)
|
|
26-10-2005 06:53Вещь правильная , но :
- прогресс нужно земенить на часы (опционально)
- добавить кнопку "Прервать". В обработчике просить подтверждение "прерывания". Наличие кнопки определяется наличием события обработки "прерывания".
|
|
19-10-2005 10:09В принципе, хорошая вещь, только текст мерцает. |
|
19-10-2005 04:29сообщение от автора материала Для dwrbudr
Во-первых я не силен в английском.
Во-вторых обращаю внимание, что Handle это дескриптор потока, а WND — окна, т. к. мы имеем дело с потомком TThread a не TWinControl.
Для kms
Как показывает практика время окончания операции всегда определяется неверно, так что заморачиваться по этому поводу нет большого смысла. |
|
18-10-2005 13:19You should use LockWindowUpdate(Handle) before drawing and LockWindowUpdate(0) after that to avoid flicker. |
|
17-10-2005 08:43Да, красивая штука. Но она не очень полезна при долговременных операциях, потому что то же самое делается через Application.ProcessMesssages;
Вот если бы ей можно быть сообщить в начале Estimated time, а потом начать долгую непрерываемую в основном потоке операцию, а она в это время крутила бы ProgerssBar , то было бы лучше :)
А если, скажем, estimated time Дошел до конца, а основной поток незакончил, можно пойти по второму кругу...
Но это так, просто мысли вслух.. Спасибо и на том! :) |
|
17-10-2005 06:12Вроде работает, но все-таки мигает!
Причем мигает и текст...непонятно зачем его перерисовывать если он не поменялся
а так довольно рабочая и полезная вещь :-) |
|
|
|