Форум: "WinAPI";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
Вниз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 вся ветка
Форум: "WinAPI";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.03 c