Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.07.25;
Скачать: CL | DM;

Вниз

Synchronize внутри DLL. Пытаюсь рисовать из треда на форме.   Найти похожие ветки 

 
alienserg   (2004-06-12 00:13) [0]

Такая проблема:
Есть плагин с двумя формами в виде 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


 
default ©   (2004-06-12 01:28) [1]

походу WakeMainThread в nil-е
чтобы её инициал-ать видимо придётся через разд-ую память передать в DLL адрес TApplication.WakeMainThread и всё должно завертеться(это непроверенное на практике...)
DLL вообще же по-моему понятия не имеет о каком-то там Application-е глобальном...


 
default ©   (2004-06-12 01:30) [2]

вообщем исходники, исходники и ещё раз исходники
поверь они расскажут тебе больше чем "Мне сказали в том смысле"


 
nikkie ©   (2004-06-12 01:48) [3]

наверное, надо передать Application в dll и присвоить тамошнему Application.
а вообще забей ты на этот Synchronize. сделай через PostMessage.


 
default ©   (2004-06-12 01:50) [4]

nikkie ©   (12.06.04 01:48) [3]
а тамошний он есть?


 
nikkie ©   (2004-06-12 03:34) [5]

хм... если Forms не подключен, то нет. но в данном случае:

Затем основная программа вызывает экспортированную процедуру этой DLL, createFormProc, которая создает Form1. Тоже в основном потоке.


 
alienserg   (2004-06-12 04:33) [6]

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

в моем случае?
Или екзампл какой может у кого найдется...


 
default ©   (2004-06-12 11:28) [7]

alienserg   (12.06.04 04:33) [6]
в этой переменной(WakeMainThread)
обычно содержится адрес TApplication.WakeMainThread
попробуй что-нибудь типа
ShowMessage(TApplication(TMethod(WakeMainThread).Data).ExeName)
работает?


 
nikkie ©   (2004-06-12 16:38) [8]

>адрес треда и адрес процедуры
а зачем? тебе просто прогрессбар надо отображать?
перед созданием потока создаешь форму с прогрессбаром.
ее хендл передаешь либо треду в переопределенный конструктор, либо создаешь тред в suspended состоянии и присваиваешь хендл piblic-member-у треда, после чего делаешь resume.
поток по мере того, как что-то происходит, посылает твое сообщение (типа const WM_DOWNLOAD_PROGRESS = WM_USER + 1), передавая в wParam насколько надо прогресс продвинуть. или лучше сколько байт он получил, а форма решает сама, насколько прогресс сдвинуть.


 
alienserg   (2004-06-12 16:39) [9]

default ©   (12.06.04 11:28) [7]

TApplication(TMethod(WakeMainThread).Data).ExeName
содержит полное имя хостового приложения вместе с путем.
Посмотрел в DebugMode поскольку ShowMessage из треда не работает.


 
alienserg   (2004-06-12 16:49) [10]

nikkie ©   (12.06.04 16:38) [8]

тебе просто прогрессбар надо отображать?
Нет, не только. Мне надо еще отрисовывать процент исполнения в статусе, кол-во байт в статусе, менять заголовки кнопок по ходу дела, менять наименование текущего файла в лейбле, поскольку пересылка пакетная из нескольких файлов. Еще мне надо каждый новый пересылаемый файл добавлять в TListView в ReportMode, чтобы юзер видел историю процесса, успешно ли прошла пересылка, MD5 confirmation отображать и т.д. Мне надо много VCL работы делать...
Попробую испльзовать Delphi Packages вместо стандартных DLL. Может там Synchronize() будет корректно работать...


 
default ©   (2004-06-12 16:55) [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 17:13) [12]

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 17:18) [13]

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;


 
default ©   (2004-06-12 18:54) [14]

кстати на самом деле есть два Application-а
так что делай замену если что


 
alienserg   (2004-06-12 19:08) [15]

default ©   (12.06.04 16:55) [11]

то есть прилож-ия к которому "присоед-ся" DLL?
Именно так.

доходит-ли до главного потока WM_NULL?
А как мне его ловить в главном потоке? Я первый раз этими тропами хожу...
Где у главного потока коллектор-распределитель всех этих сообщений?


 
default ©   (2004-06-12 19:22) [16]

попробуй заменить Application


 
nikkie ©   (2004-06-12 20:10) [17]

проще все...
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;


 
alienserg   (2004-06-14 01:59) [18]

Спасибо всем большое. Очень познавательно было, по крайней мере для меня. Сделал на PostMessage, оказалось не все так сложно, как я себе представлял.
Осталась правда одна непонятная вещь: как только я назначаю какой-либо обработчик для прогресс-окна, созданного внутри dll, в runtime программа начинает верещать "invalid property".
Такое наблюдалось при назначении обработчика OnCreate формы или OnClick. Даже если они были пустыми. Сие непонятно для меня...
Поэтому пришлось переопределять WindowProc формы не в событии OnCreate, а в коде сразу после создания формы.


 
default ©   (2004-06-14 02:13) [19]

alienserg   (14.06.04 01:59) [18]
решение [17] это ладно...
для чего два Application-а то вот вопрос...


 
nikkie ©   (2004-06-14 02:20) [20]

вот ёёё...
зачем WindowProc переопределять???
зачем назначать какие-то обработчики в рантайм???
тем более форме, созданной в другом модуле?


 
alienserg   (2004-06-14 02:53) [21]

nikkie ©   (14.06.04 02:20) [20]

зачем WindowProc переопределять???
Ну сделал сгоряча :) невнимательно посмотрел на [17]...
Работает... Следовательно имеет право на жизнь.
В дальнейшем буду пользоваться [17] приемом :)

зачем назначать какие-то обработчики в рантайм???
А почему это в runtime? Я обработчик назначаю в design time.
И все прекрасно компилируется.
В runtime оно только верещит :)



Страницы: 1 вся ветка

Текущий архив: 2004.07.25;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.041 c
1-1089358038
ORMADA
2004-07-09 11:27
2004.07.25
Mask


1-1089127014
Buster
2004-07-06 19:16
2004.07.25
Как написать у CheckBox текст в две строки?


4-1086698023
Sergeika
2004-06-08 16:33
2004.07.25
Почему перестаёт работать hook на клаву при переключении окон?


1-1089259525
Артем К.
2004-07-08 08:05
2004.07.25
Форма без заголовка, без рамки, но может изменять размеры?


1-1089483982
Комбинатор
2004-07-10 22:26
2004.07.25
Как передать в процедуру dll параметр