Форум: "Основная";
Текущий архив: 2006.07.09;
Скачать: [xml.tar.bz2];
ВнизИ снова форма в dll : инициализация Найти похожие ветки
← →
parovoZZ © (2006-05-23 00:36) [0]Здарова
У меня в dll две формы - одна рабочая (с визуальными компонентами), а вторая DataModule. Вот её то и не получается инициализировать (рабочая с компонентами в данный момент не нужна). Т.е. нужны компоненты ADOcommand, ADOConnection и ADODataSet. Делаю следующее:unit DF;
interface
uses
Windows, Classes, DB, ADODB, Forms;
type
TDMd = class(TDataModule)
ADOConnection: TADOConnection;
ADOCmd: TADOCommand;
ADODS: TADODataSet;
private
public
{ Public declarations }
end;
//procedure DllEntryPoint (Reason : DWord);
procedure InitData; stdcall;
var
DMd: TDMd;
implementation
{$R *.dfm}
procedure InitData; stdcall
begin
DMd := TDMd.Create (Application);
end;
{
initialization
//if (DllProc = nil) then
begin
DllProc := @DllEntryPoint;
DllEntryPoint (DLL_PROCESS_ATTACH);
end;
finalization }
exports
InitData name "InitData";
end.
Так вот на строчке DMd := TDMd.Create (Application); возникает ошибка EOleSysError with message "Не был произведён вызов CoInitialize". Чего я такого не сделал?
Да, вызывающий exe написан на апях.
← →
DrPass © (2006-05-23 00:48) [1]Наступил на грабли VCL - она в общем случае не предназначена для использования в DLL. В данном случае в модуле ComObj не выполнилась секция инициализации (это не ошибка, это фича :-). В этой секции кроме всего прочего производился вызов CoInitialize - необходимое условие для работы основанных на COM компонент, например, ADO
← →
evvcom © (2006-05-23 08:32) [2]Ну так произведи вызов CoInitialize перед Create. Примеров в VCL куча, ты клавишами Ctrl+F пользоваться умеешь?
← →
parovoZZ © (2006-05-23 09:14) [3]Ладно, будем попробовать.
← →
isasa © (2006-05-23 10:53) [4]Собирался добавить, так добавь. :)
procedure DLLEntryPoint(Reason: Integer); // stdcall;
begin
case Reason of
DLL_PROCESS_DETACH: //= 0;
CoUninitialize;
DLL_PROCESS_ATTACH: //= 1;
CoInitializeEx( nil, COINIT_MULTITHREADED); // MTA
// или CoInitializeEx( nil, COINIT_APARTMENTTHREADED); // STA
end;
end;
из MSDN
CoInitializeEx provides the same functionality as CoInitialize and also provides
a parameter to explicitly specify the thread"s concurrency model.
The current implementation of CoInitialize calls CoInitializeEx and specifies
the concurrency model as single-thread apartment.
Applications developed today should call CoInitializeEx rather than CoInitialize.
И что такое Application в DLL? Оно такое, как в EXE? Выставь, хотя бы
Application(из DLL).Handle:=Application(из EXE).Handle
← →
parovoZZ © (2006-05-23 20:14) [5]Exe у меня на апях, там нет никакого Application. Есть просто MainHandle.
← →
parovoZZ © (2006-05-23 20:38) [6]А где объявлена эта функция? на мсдн написан objbase, но у меня нет такого.
← →
isasa © (2006-05-23 21:39) [7]{$Delphi}\Source\Rtl\Common\ComObj.pas
← →
isasa © (2006-05-23 21:43) [8]parovoZZ © (23.05.06 20:14) [5]
Exe у меня на апях,
Если есть
uses ... Forms,...
то имеется :)
В общем, идея такая, Application.Handle в DLL, заполняется ручками ...
← →
parovoZZ © (2006-05-23 22:53) [9]Ура, заработало.
> Если есть uses ... Forms,...то имеется :)
Если я говорю, что Api, значит Api. Ну нравятся мне exe весом 50 кило.
А смысл заменять у Application Handle?
← →
isasa © (2006-05-23 23:42) [10]А подумать?
...
DMd := TDMd.Create (Application);
...
← →
DrPass © (2006-05-23 23:51) [11]
> А смысл заменять у Application Handle?
Ровным счетом никакого. Сообщения-то все равно будут приходить в оконную функцию, объявленную в основной программе, а не в Application.
А в том Application, которое объявлено в DLL, вообще не создается ни оконная функция, ни дескриптор (это тоже фича, начиная с D6)
← →
DrPass © (2006-05-23 23:52) [12]
> isasa © (23.05.06 23:42) [10]
> А подумать?
>
> ...
> DMd := TDMd.Create (Application);
И причем тут дескриптор Application?
← →
isasa © (2006-05-23 23:54) [13]На сон.
Если не морочить голову с Application и освобождать ресурс ручками
DMd.Free
пиши
DMd := TDMd.Create (nil);
← →
isasa © (2006-05-24 00:01) [14]DrPass © (23.05.06 23:52) [12]
И причем тут дескриптор Application?
А хорошо ли, в качестве родителя, указывать проблемный объект?
← →
DrPass © (2006-05-24 00:05) [15]
> isasa © (24.05.06 00:01) [14]
А он абсолютно непроблемный. В том же и смысл отсутствия оконной функции и дескриптора в Application в DLL, чтобы их корректно разруливать. Кстати, в версиях D5 и более старых действительно нужно было их синхронизировать... только более жесткими методами - DLL_Application:= EXE_Application. В данном же случае единственный смысл этого объекта - общий родитель для форм и модулей в DLL.
← →
isasa © (2006-05-24 00:33) [16]Тоесть, для DLL корректно
Application.Terminate
?
← →
isasa © (2006-05-24 00:38) [17]Наверно непонятно написал.
Имел ввиду следующее. Освобождаем ресурсы проще?
procedure DLLEntryPoint(Reason: Integer); // stdcall;
begin
case Reason of
DLL_PROCESS_DETACH: //= 0;
CoUninitialize;
Application.Terminate;
← →
DrPass © (2006-05-24 01:06) [18]
> isasa © (24.05.06 00:38) [17]
А здесь вообще Application.Terminate не нужно. Application.Terminate по умолчанию никаких ресурсов не высвобождает, это же не деструктор. Она просто посылает главному потоку приложения сообщение WM_QUIT - поэтому не важно, обрабатывается ли очередь главного потока в Application или какой-то другой оконной функции, все равно обработается корректно. Т.е. если приложение и так завершает работу (если, конечно, DLL_PROCESS_DETACH не следствие FreeLibrary), лишний раз ему напоминать об этом не к чему (хотя и не повредит).
Вообще, полезно ознакомиться с первоисточником (сиречь исходниками VCL) - тогда бы эти непонятки отпали бы сами собой
← →
parovoZZ © (2006-05-24 21:33) [19]
> Т.е. если приложение и так завершает работу (если, конечно,
> DLL_PROCESS_DETACH не следствие FreeLibrary),
Т.е. DLL_PROCESS_DETACH тоже надо формировать ручками? А почему нельзя автоматом при FreeLibrary?
← →
DrPass © (2006-05-25 00:26) [20]
> parovoZZ © (24.05.06 21:33) [19]
Да не надо ничего формировать, я совсем про другое писал. Библиотека получит свой DLL_PROCESS_DETACH, куда она денется :)
← →
parovoZZ © (2006-05-26 00:06) [21]
> В общем, идея такая, Application.Handle в DLL, заполняется
> ручками ...
В таком случае окно становится модальным, сворачивается не в таскбар, а над пуском, к тому же висит ещё какое-то маленькое окно, с которым ничего сделать нельзя, только подвигать.
Что-то на строчке
MainForm := TMainForm.Create (nil);
выпадает ошибка в духе "Could not ole window handle". А бывает не выпадает.
Короче, ну его... Форма в dll это такой гемор брррр. Да и при выходе ругань Access Vioalatin.
Только весь проект изгадил.
← →
isasa © (2006-05-26 00:25) [22]Ну главную форму запихать в DLL, это круто.
Тут помочь не могу. Я такого еще не встречал. :)
Фанатизм приводит к травмам!
← →
isasa © (2006-05-26 00:40) [23]Немного оклемался. :)
Для VCL, это
Application.Initialize;
Application.CreateForm(TmainForm, mainForm);
Application.Run;
как Библия, остальные пихай в DLL, если есть желание решать проблемы(решаеиые).
← →
parovoZZ © (2006-05-26 01:31) [24]А куда мне её ещё деть? У меня exe написан на АПЯХ!!!
Кароче! Убрал WebBrowser с формы - пропала ошибка с OLE.
Заккомил строчку {$R DelphiXP.res} - прекратились ошибки при завершении проги. А жаль. Всё так красиво.
А почему WebBrowser не дружит с PageControl???? Создал ту же форму в ехе - ошибка осталась. Фигня. Мне без броузера низзя.
← →
isasa © (2006-05-26 08:05) [25]WebBrowser - это COM(скорее всего), значит надо делать CoInitializeEx и в EXE.
Только тип модели должен быть аналогичен, усьановленному в DLL.
Тип потоковой модели "на ходу" не меняется.
← →
parovoZZ © (2006-05-26 09:44) [26]Так ведь без PageControl всё работает.
А как быть с манифестом ХР? и почему он в dll не подхватывается?
Попробую в секцию 24 запихнуть.
← →
GrayFace © (2006-05-26 12:31) [27]По поводу [1] - Укажи ComObj в dpr где-нибудь по раньше - тогда точно должен будет проинициализироваться.
DrPass © (23.05.06 23:51) [11]
> > А смысл заменять у Application Handle?
>
> Ровным счетом никакого. Сообщения-то все равно будут приходить
> в оконную функцию, объявленную в основной программе, а не
> в Application.
> А в том Application, которое объявлено в DLL, вообще не
> создается ни оконная функция, ни дескриптор (это тоже фича,
> начиная с D6)
Есть. Почти такой же как у Form.ParentWindow:=...
← →
parovoZZ © (2006-05-26 22:20) [28]Ладно, в задницу все эти dll с формами. Генератор глюков вышел вместо проги. Всё равно по скорости ничего не получил - dll статически грузится столько же, сколько и exe. А динамически - голова съедет.
← →
Ярослав (2006-05-27 20:50) [29]Смотри пример как это делаю я
Вот дллка :library INFO;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library"s USES clause AND your project"s (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Classes,
Forms ,
system,
infomy in "infomy.pas"{imy},
infouser in "infouser.pas"{usr},
infouserb in "infouserb.pas"{usb},
bvlogo in "bvlogo.pas"{logo};
{$R *.RES}
function infoform : integer; stdcall ;
var
inf: Tmyinfo ;
begin
inf:=tmyinfo.Create(Application);
Result:=inf.ShowModal ;
inf.Free ;
end ;
function userform: integer ;stdcall ;
var
infuser:Tuserinfo ;
begin
infuser:=Tuserinfo.Create(Application) ;
result:=infuser.ShowModal ;
infuser.Free ;
end ;
function userformb: integer ;stdcall ;
var
infuserb:Tuserinfob ;
begin
infuserb:=Tuserinfob.create(Application) ;
result:=infuserb.showmodal ;
infuserb.free ;
end;
function startbvlogo: integer ; stdcall ;
var
logostart:tlogo ;
begin
logostart:=Tlogo.create(Application);
result:=logostart.showmodal ;
logostart.free ;
end ;
exports
infoform,
Userform ,
userformb,
startbvlogo;
begin
end.
Вызов из главной формы
var
Main_Form: TMain_Form;
{------------------------------------}
function infoform : integer; stdcall ;
external "INFO.dll" ;
function userform: integer ; stdcall ;
external "INFO.dll" ;
function userformb:integer; stdcall ;
external "INFO.dll" ;
Function startbvlogo:integer; stdcall ;
external "info.dll" ;
{=====================}
procedure TMain_Form.N18Click(Sender: TObject);
begin
startbvlogo;
end;
procedure TMain_Form.N22Click(Sender: TObject);
begin
userformb;
end;
procedure TMain_Form.N20Click(Sender: TObject);
begin
infoform;
end;
У меня все работает ..
Кроме MDI форм
← →
Ярослав (2006-05-27 21:00) [30]Так если у вас есть дата модуль так где вы его подключаете в длл?
← →
parovoZZ © (2006-05-27 21:31) [31]Да не, проблема WebBrowser + PageControl в dll. Всё коннектится, грузится, но при открытии вкладки с WebBrowser вылетает ошибка типа Could not ole window handle. Всё тоже самое сделал в exe - без ошибок.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.07.09;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.011 c