Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.045 c
1-1089203408
dosik
2004-07-07 16:30
2004.07.25
Двумерные массивы в испекторе объектов


9-1081582061
ArchangelM
2004-04-10 11:27
2004.07.25
Physic Engine


3-1088744616
NAlexey
2004-07-02 09:03
2004.07.25
Прерывание выполнения запроса


3-1088496010
Valeri
2004-06-29 12:00
2004.07.25
ADO


14-1089142694
Knight
2004-07-06 23:38
2004.07.25
Народа!!! Надо спасать дремучего, а то ведь вообще загнётся...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский