Форум: "Основная";
Текущий архив: 2003.01.23;
Скачать: [xml.tar.bz2];
ВнизФорма из DLL Найти похожие ветки
← →
Петров Денис (2003-01-13 12:28) [0]Доброе время суток.
Проблема: создаю форму из DLL через TForm.CreateParented (владелец формы не всегда VCL"ный). Вроде бы все в порядке, но, если переключаться между окнами, открытыми в системе, не по Alt+Tab, а, например, щелкая мышью по панели задач, то моя форма не отображается, а главное окно приложения, которое ее создало, остается свернутым. Причем это происходит как в случае с не-VCL владельцем формы, так и с VCL. А если еще эта форма отображается часто (т. е. имеет место процесс "показать-выполнить действия-спрятать", который происходит в цикле), то вообще начинаются чудеса. Окно-владелец может легко свернуться, моя форма может свободно исчезать с экрана и тому подобные неприятности.
Все это проихсодит, когда в системе открыто больше одного окна. С одним открытым окном вроде бы все нормально.
Стиль формы - fsNormal, стиль границы - bsSingle, все иконки отключены. Форму показываю через TForm.Show (модально ее показывать нельзя).
Если кто сталкивался, подскажите, пожалуйста, чего надо сделать, чтобы убрать этот глюк.
← →
passm (2003-01-13 14:02) [1]Петров Денис © (13.01.03 12:28)> Попробуй при загрузке DLL (LoadLibrary) передать Application.Handle из приложения. Но не забудь восстановить при выгрузке DLL.
Т. е.
Library...
...
function GetApplicationHandle: HWND; stdcall;
begin
Result:= Application.Handle
end;
procedure SetApplicationHandle(const Hanldle: HWND); stdcall;
begin
Application.Handle:= Handle
end;
Project...
...
type
TGetApplicationHandleProc = function: HWND; stdcall;
TSetApplicationHandleProc = procedure(const Hanldle: HWND); stdcall;
var
Hl: THandle;
Ha: HWND;
GetApplicationHanldeProc: TGetApplicationHanldeProc;
SetApplicationHandleProc: TSetApplicationHandleProc;
begin
...
Hl:= LoadLibrary(...);
if Hl <> 0 then
begin
GetApplicationHandleProc:= GetProcAddress(Hl, "GetApplicationHandle");
SetApplicationHandleProc:= GetProcAddress(Hl, "SetApplicationHandle");
if Assigned(GetApplicationHandleProc) and Assigned(SetApplicationHandleProc) then
begin
Ha:= GetApplicationHandleProc;
SetApplicationHandleProc(Application.Handle)
end;
try
{ Твои действия }
finally
if Assigned(GetApplicationHandleProc) and Assigned(SetApplicationHandleProc) then
SetApplicationHandleProc(Ha);
FreeLibrary(Hl)
end { try }
end { if }
← →
asmith (2003-01-13 14:10) [2]Нижеприведенное относится к ситуации, когда головная программа также написана на D6 (из сообщения это не очевидно). Если это так - поможет сборка всего с runtime packages. Эта тема неоднократно уже здесь обсуждалась.
← →
Петров Денис (2003-01-13 15:56) [3]passm> Спасибо за идею про Application.Handle. Частично проблема решена, хотя и не так, как в твоем примере - при переключении между окнами моя форма остается наверху и все отображается как надо.
Другая часть проблемы (когда форма используется в цикле), все еще живет, сволочь...
Опишу ситуацию подробнее. DLL, о которой идет речь, COM-сервер, подключенный к "1С". Форма - обычный прогресс-бар, показывает прогресс выполнения какой-нибудь задачи.
Первая часть проблемы решилась так: при подключении "1С" к моей DLL я получаю дескриптор ее главного окна и присваиваю его дескриптору приложения в моей DLL:
...
Application.Handle := GetActiveWindow;
...
То, что GetActiveWindow в момент ее вызова возвратит хэндл главного окна "1С" - это абсолютно точно.
Дальше начинаются проблемы. Есть некоторый циклический процесс - например, проведение документов. При проведении каждого документа "1С" делает следующее:
1. Вызывает форму с прогрессбаром на экран и инциализирует ее начальными значениями. Вот код этой процедуры:
ProgressBarFrm := TProgressBarFrm.Create(Application);
ProgressBarFrm.Caption := Caption;
ProgressBarFrm.Width := Width;
ProgressBarFrm.ProgressBar.Min := Min;
ProgressBarFrm.ProgressBar.Max := Max;
ProgressBarFrm.ProgressBar.Position := Position;
ProgressBarFrm.Description.Caption := "Выполнено " + IntToStr(Position) + " из " + IntToStr(Max);
ProgressBarFrm.Show;
2. В цикле (например, по табличной части проводимого документа) обновляет прогрессбар, показывая, сколько строк документа обработано:
ProgressBarFrm.Description.Caption := "Выполнено " + IntToStr(Position) + " из " + IntToStr(ProgressBarFrm.ProgressBar.Max);
ProgressBarFrm.ProgressBar.Position := Position;
3. По окончании цикла убирает прогрессбар с экрана:
ProgressBarFrm.Free;
Так вот, эти три пунтка выполняются в цикле - цикл по количеству обрабатываемых документов. В момент вызова функции, создающей прогрессбар первый раз, Application.Handle = GetForegroundWindow.
А вот во второй раз это условие почему-то не выполняется. И в цикле наблюдается такая картина: после выполнения ProgressBarFrm.Free активным становится другое окно (почему-то НЕ главное окно "1С"!), и изображение на экране мелькает, потому как переключение на это другое окно надо перерисовать...
Вопрос: почему после удаления окна активным становится не его владелец, а какое-то левое окно?
← →
asmith (2003-01-13 18:05) [4]А потому, что для формы, созданной в DLL, владелец определяется неправильно - смотри код функции Forms.GetParentForm. Не срабатывает if Control is TCustomForm, если при компиляции не используются пакеты времени выполнения.
← →
Петров Денис (2003-01-13 18:09) [5]asmith> Блин, да перестраивал я проект с run-time packages. Та же фигня. Это понятно, что владелец определяется неправильно. Вопрос в том, как это победить.
← →
Palladin (2003-01-13 18:32) [6]Если чесно то при использовании handle и тп
возникают огромные глюки, ибо vcl который в exe совсем не считает что в dll тоже vcl`ьные объекты, так что exeшнику абсолютно паралельно vcl они в dll или нет.
Выход:
либо использовать bpl,
либо создать "кухню" формы в dll и общатся с этой формой через функции обьявеные в разделе
Exports в dll
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.01.23;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.007 c