![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Synchronize внутри DLL. Пытаюсь рисовать из треда на форме. [D6, Win2k]
alienserg © (2004-06-12 00:13:00)Такая проблема:
Есть плагин с двумя формами в виде DLL.
Основная программа динамически линкует эту DLL через LoadLibrary по нажатию кнопки, т.е. в основном потоке.
Затем основная программа вызывает экспортированную процедуру этой DLL, createFormProc, которая создает Form1. Тоже в основном потоке.
Owner этой формы - nil.
Юзер перетаскивает файлы из Эксплорера на Form1.
По событию OnDropFiles я создаю Form2(Owner - Form1) в основном потоке и также создаю отдельный тред, передающий файлы по сокету(использую Indy, TIdTcpClient создаю внутри треда).
Все хорошо создается и передается, но при попытке отрисовать ProgressBar на второй форме из треда, где TcpClient, ничего не получается.
Делаю естественно через Synchronize(DoSomeGUIWork), где DoSomeGUIWork - процедура треда.
Проставлял брейкпойнты в этой процедуре - программа туда вообще не заходит.
Практически тот же код прекрасно рисует на форме из треда, если все делается в основной программе. А вот внутри DLL не хочет.
Мне сказали в том смысле, что Synchronize требует активной очереди сообщений для своей корректной работы и что в моем случае таковая отсутствует. Но я же линковал dll и создавал тамошнюю форму в основном потоке приложения...
Еще мне сказали, что в Delphi 6 полностью переработан механизм Synchronize и что у основной программы и у подсоединяемых dll теперь разные TApplication и соответственно разные очереди сообщений.
Подскажите плиз, как заставить Synchronize корректно работать внутри DLL?
Использую Delphi 6 build 6.163
alienserg (2004-06-14 02:53:00) [1]nikkie © (14.06.04 02:20) [20]
зачем WindowProc переопределять???
Ну сделал сгоряча :) невнимательно посмотрел на [17]...
Работает... Следовательно имеет право на жизнь.
В дальнейшем буду пользоваться [17] приемом :)
зачем назначать какие-то обработчики в рантайм???
А почему это в runtime? Я обработчик назначаю в design time.
И все прекрасно компилируется.
В runtime оно только верещит :)
nikkie (2004-06-14 02:20:00) [2]вот ёёё...
зачем WindowProc переопределять???
зачем назначать какие-то обработчики в рантайм???
тем более форме, созданной в другом модуле?
default (2004-06-14 02:13:00) [3]alienserg (14.06.04 01:59) [18]
решение [17] это ладно...
для чего два Application-а то вот вопрос...
alienserg (2004-06-14 01:59:00) [4]Спасибо всем большое. Очень познавательно было, по крайней мере для меня. Сделал на PostMessage, оказалось не все так сложно, как я себе представлял.
Осталась правда одна непонятная вещь: как только я назначаю какой-либо обработчик для прогресс-окна, созданного внутри dll, в runtime программа начинает верещать 'invalid property'.
Такое наблюдалось при назначении обработчика OnCreate формы или OnClick. Даже если они были пустыми. Сие непонятно для меня...
Поэтому пришлось переопределять WindowProc формы не в событии OnCreate, а в коде сразу после создания формы.
nikkie (2004-06-12 20:10:00) [5]проще все...
procedure WMUpdateTraffic(var Message: TMessage); message WM_UPDATE_TRAFFIC;
...
procedure TMainForm.WMUpdateTraffic(var Message: TMessage);
var
BytesReceived: Integer;
begin
BytesReceived := Message.WParam;
FTraffic := FTraffic + BytesReceived;
...
end;
default (2004-06-12 19:22:00) [6]попробуй заменить Application
alienserg (2004-06-12 19:08:00) [7]default © (12.06.04 16:55) [11]
то есть прилож-ия к которому "присоед-ся" DLL?
Именно так.
доходит-ли до главного потока WM_NULL?
А как мне его ловить в главном потоке? Я первый раз этими тропами хожу...
Где у главного потока коллектор-распределитель всех этих сообщений?
default (2004-06-12 18:54:00) [8]кстати на самом деле есть два Application-а
так что делай замену если что
default (2004-06-12 17:18:00) [9]procedure TForm1.FormCreate(Sender: TObject);
begin
OldWindowProc := WindowProc;
WindowProc := NewWindowProc;
end;
nikkie © (12.06.04 16:38) [8]
"передавая в wParam насколько надо прогресс"
procedure TForm1.NewWindowProc(var Message: TMessage);
begin
if Message.Msg = WM_DOWNLOAD_PROGRESS then DoOnDownloadProgress(Message.WParam) else
OldWindowProc(Message)
end;
alienserg (2004-06-12 17:13:00) [10]nikkie © (12.06.04 16:38) [8]
T.e. мне надо поменять стандартный обработчик оконных сообщений?
типа
procedure TForm1.FormCreate(Sender: TObject);
begin
OldWindowProc := self.WindowProc;
self.WindowProc := NewWindowProc;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
self.WindowProc := OldWindowProc;
end;
procedure TForm1.NewWindowProc(var Message: TMessage);
begin
if Message.Msg = WM_DOWNLOAD_PROGRESS then DoOnDownloadProgress(Message);
OldWindowProc(Message);
end;
?
default (2004-06-12 16:55:00) [11]alienserg (12.06.04 16:39) [9]
то есть прилож-ия к которому "присоед-ся" DLL?
Application-то получ-ся никакой не DLL-ий(если такой есть вообще...) и всё вроде бы должно работать...
"
procedure TApplication.WakeMainThread(Sender: TObject);
begin
PostMessage(Handle, WM_NULL, 0, 0);
end;"
попробуй из потока
PostMessage(TApplication(TMethod(WakeMainThread).Data).Handle
, WM_NULL, 0, 0);
или(и) просто Classes.WakeMainThread(nil)
доходит-ли до главного потока WM_NULL?
alienserg (2004-06-12 16:49:00) [12]nikkie © (12.06.04 16:38) [8]
тебе просто прогрессбар надо отображать?
Нет, не только. Мне надо еще отрисовывать процент исполнения в статусе, кол-во байт в статусе, менять заголовки кнопок по ходу дела, менять наименование текущего файла в лейбле, поскольку пересылка пакетная из нескольких файлов. Еще мне надо каждый новый пересылаемый файл добавлять в TListView в ReportMode, чтобы юзер видел историю процесса, успешно ли прошла пересылка, MD5 confirmation отображать и т.д. Мне надо много VCL работы делать...
Попробую испльзовать Delphi Packages вместо стандартных DLL. Может там Synchronize() будет корректно работать...
alienserg (2004-06-12 16:39:00) [13]default © (12.06.04 11:28) [7]
TApplication(TMethod(WakeMainThread).Data).ExeName
содержит полное имя хостового приложения вместе с путем.
Посмотрел в DebugMode поскольку ShowMessage из треда не работает.
nikkie (2004-06-12 16:38:00) [14]>адрес треда и адрес процедуры
а зачем? тебе просто прогрессбар надо отображать?
перед созданием потока создаешь форму с прогрессбаром.
ее хендл передаешь либо треду в переопределенный конструктор, либо создаешь тред в suspended состоянии и присваиваешь хендл piblic-member-у треда, после чего делаешь resume.
поток по мере того, как что-то происходит, посылает твое сообщение (типа const WM_DOWNLOAD_PROGRESS = WM_USER + 1), передавая в wParam насколько надо прогресс продвинуть. или лучше сколько байт он получил, а форма решает сама, насколько прогресс сдвинуть.
default (2004-06-12 11:28:00) [15]alienserg (12.06.04 04:33) [6]
в этой переменной(WakeMainThread)
обычно содержится адрес TApplication.WakeMainThread
попробуй что-нибудь типа
ShowMessage(TApplication(TMethod(WakeMainThread).Data).ExeName)
работает?
alienserg (2004-06-12 04:33:00) [16]default © (12.06.04 01:28) [1]
походу WakeMainThread в nil-е
WakeMainThread <> nil
только что проверил...
nikkie © (12.06.04 01:48) [3]
А как с помошью PostMessage сообщить окну адрес треда и адрес процедуры, которую надо исполнить? Я не шибко силен в ручном управлении всей этой механикой... И Рихтера под рукой нет. Поискал в MSDN и не нашел подробного описания структуры сообщений.
Что должно быть в
UINT Msg,
WPARAM wParam,
LPARAM lParam
в моем случае?
Или екзампл какой может у кого найдется...
nikkie (2004-06-12 03:34:00) [17]хм... если Forms не подключен, то нет. но в данном случае:
Затем основная программа вызывает экспортированную процедуру этой DLL, createFormProc, которая создает Form1. Тоже в основном потоке.
default (2004-06-12 01:50:00) [18]nikkie © (12.06.04 01:48) [3]
а тамошний он есть?
nikkie (2004-06-12 01:48:00) [19]наверное, надо передать Application в dll и присвоить тамошнему Application.
а вообще забей ты на этот Synchronize. сделай через PostMessage.
default (2004-06-12 01:30:00) [20]вообщем исходники, исходники и ещё раз исходники
поверь они расскажут тебе больше чем "Мне сказали в том смысле"