Форум: "Основная";
Текущий архив: 2002.09.16;
Скачать: [xml.tar.bz2];
ВнизFrame в dll Найти похожие ветки
← →
Ekaterina (2002-09-03 10:10) [0]Вроде и ситуация-то не хитрая. Я уже как-то спрашивала, но так ни чего и не прояснилось. Может кто-нибудь всё-таки знает.
Есть dll. В ней форма и фрейм.
library Project2;
uses
SysUtils,
Classes,
Forms,
Dialogs,
Unit1 in "Unit1.pas" {Frame1: TFrame},
Unit2 in "Unit2.pas" {Form2};
{$R *.res}
procedure Test;
begin
Form2:=TForm2.Create(Application);
try
frame1:=TFrame1.Create(Form2);
frame1.Parent:=Form2;
Form2.Show;
Application.ProcessMessages;
Sleep(2000);
finally
frame1.Free;
form2.Free;
end;
end;
exports
Test;
begin
end.
Вызываем процедуру Test из основной программы. Все работает. Теперь помещаем на фрейм какой-нибудь компонент с TStrings-ами, например, ComboBox. И задаём ему непустой Items (при пустом тоже всё нормально). На строкеframe1:=TFrame1.Create(Form2);
получаем ошибку: "Error reading ComboBox1.Items.Strings: Control "Frame1" has no parent window".
Если то же самое делать без dll, то всё опять работает и с Items-ами.
Просьба: создание Items-ов в Runtime и т.п. не предлагать. Вопрос не в том, как это обойти, а почему не работает так?
← →
Ученик (2002-09-03 10:50) [1]Проблема в том, что Application.Handle в DLL равен 0, инициализации его (Application.Handle) помогает показать форму, но ошибка все-равно происходит, правда другая
← →
Ekaterina (2002-09-03 11:08) [2]Да нет, у меня Application.Handle не равен 0. В dll он тот же, что и в основной программе.
← →
Ученик (2002-09-03 11:10) [3]Ошибка тогда другая
← →
Ekaterina (2002-09-03 11:16) [4]А конкретней?
← →
Ученик (2002-09-03 11:20) [5]У меня 2 AV в ntdll, потом форма показывается (Windows 2000)
← →
Ekaterina (2002-09-03 11:26) [6]У меня тоже Win2000. Код дословно приведён выше(плюс пустая форма и фрейм с одним ComboBoxом). Больше ничего нет, ей-богу. С Application.Handle я ничего не делаю. Оно само инициализируется (вроде, так и положено). Delphi 6. Пробовала в Win98, Delphi5 - то же самое в точности. Других ошибок не возникает.
← →
Ученик (2002-09-03 11:31) [7]А как оно может инициалироваться, если Вы этого не сделаете ?
{ Forms.pas }
constructor TApplication.Create(AOwner: TComponent);
var
begin
...
if not IsLibrary then CreateHandle;
...
end;
← →
Dimk (2002-09-03 11:34) [8]Я не знаю почему так происходит - но есть одна мысль пусть и не совсем в тему :0)
Когда создаешь DLL New-Other-DllWizard в проект сверху сразу вставляются комментарии о необходимости использовать Borland MM если в/из DLL передаются длинные строки. На всякий случай сделай как просят :0) хотя незнаю поможет ли в твоей проблеме.
← →
Внук (2002-09-03 11:41) [9]Пока по этой проблеме могу сказать только то, что она возникает из-за
Uses Forms в DLL
ShareMem не помогает
← →
Ekaterina (2002-09-03 12:03) [10]>Dimk (03.09.02 11:34)
ShareMem действительно не помогает.
>Ученик © (03.09.02 11:31)
CreateHandle создаёт главное окно для приложения, если такового нет. В случае dll по-видимому используется вызывающее приложение. Во всяком случае у меня умные Delphi каким-то образом сами догадываются, что надо сделать.
← →
Shaman_Naydak (2002-09-03 12:05) [11]Проверил.. да, всплывает такая ошибка..
лечится использованием компиляции с пакетами как в основной программе, так и в DLL.
И, этто, не надо Frame1.Free делать.. форма о ней позабодится
← →
Shaman_Naydak (2002-09-03 12:13) [12]> Ekaterina
И все таки первоначальный диагноз, поставленный Учеником верен.
Ошибка из-за того, что Application.Handle в DLL = 0..
Я передал его в процедуру тест, там присвоил, и все как рукой сняло..
Но я еще раз настоятельно рекомендую использовать компиляцию с пакетами.. тогда не надо будет финты ушами делать + разные бонусы :)
Прошу прощения за предыдущий пост, опечатался, надо читать позаботится
← →
Shaman_Naydak (2002-09-03 12:24) [13]Ну и чтобы окончательно закрыть ветку покажем негодника:
procedure TCustomFrame.CreateParams(var Params: TCreateParams);
begin
inherited;
if Parent = nil then
Params.WndParent := Application.Handle;
end;
Вот тут-то и получается белибердистика..
так что можно предложить вам третий путь развития..
создать свой конструктор TFrame1, в котором Parent"у присвоить Owner"a, либо еще раз перекрыть CreateParams..
Удачи
← →
Ученик (2002-09-03 12:29) [14]>Ekaterina © (03.09.02 12:03)
А Application.Handle смотрели в приложении или DLL ?
>Shaman_Naydak © (03.09.02 12:24)
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1031039518&n=0
Это нормально, или Delphi 7, или ... ?
← →
Ekaterina (2002-09-03 13:09) [15]Интересно: ставлю breakpoint где-нибудь внутри процедуры Test, например на Form2:=TForm2.Create(Application). Application.Handle показывает не 0. Жму F7 - внутри TCustomForm.Create уже показывает 0. Вроде и то, и другое в dll.
Это глюк отладчика или я где-то не права?
← →
Ekaterina (2002-09-03 13:14) [16]Более того: WatchList показывает не 0, а ShowMessage(Inttostr(Application.Handle)) выдает 0.
← →
Ученик (2002-09-03 13:17) [17]Сегодня день глобальных глюков :-), солнце опять наверно безобразничает :-)
← →
Ekaterina (2002-09-03 13:47) [18]В чём разница между Application.Handle и Handle главного окна приложения? В Helpe написано вроде, что одно и то же. А вот когда передаю в Test Application.Handle, процедура выполняется, но в основную программу не выходит и благополучно зависает. С Handlе-ом главного окна работает нормально.
← →
Ученик (2002-09-03 13:49) [19]>Ekaterina © (03.09.02 13:47)
Проверьте описания функций, особенно stdcall
← →
Ekaterina (2002-09-03 14:09) [20]stdcall не помогает. Использую динамическую загрузку, так что описание не меняется, только параметр.
← →
Dimk (2002-09-03 14:37) [21]Application.Handle <> MainForm.Handle.
Когда создается TApplication главной формы еще нет.
И к томуже я проверил в отладчике :0)
У Application свое окно - невидимое. Такие окна часто создают чтобы можно было обрабатывать сообщения виндовс. Например TTimer если я не ошибаюсь тоже использует скрытое окно для получения от виндов сообщения что время истекло.
А может Ты чего недоговариваешь? Ненамеренно понятно.
← →
Ekaterina (2002-09-03 15:19) [22]А что означает такое в Helpe
TApplication.Handle
Provides access to the window handle of the main form (window) of the application.
property Handle: HWND;
Description
Use Handle when calling Windows API functions that require a parent window handle. For example, a DLL that displays its own top-level pop-up windows needs a parent window to display its windows in the application. Using the Handle property makes such windows part of the application, so that they are minimized, restored, enabled, and disabled with the application.
← →
Dimk (2002-09-03 15:23) [23]Да, сам читал. Потом просто полез в исходники. Посмотри Forms.pas в соурсах. Потом в отладчике элементарно сравнил два хэндла ( кстати можешь сделать это в своей программе ради интереса ). Что увидел - то и написал.
← →
Старый Паскалист (2002-09-03 15:31) [24]Вот как создаётся Application.Handle:
procedure TApplication.CreateHandle;
var
TempClass: TWndClass;
SysMenu: HMenu;
begin
if not FHandleCreated and not IsConsole then
begin
FObjectInstance := MakeObjectInstance(WndProc);
if not GetClassInfo(HInstance, WindowClass.lpszClassName, TempClass) then
begin
WindowClass.hInstance := HInstance;
if Windows.RegisterClass(WindowClass) = 0 then
raise EOutOfResources.Create(SWindowClass);
end;
FHandle := CreateWindow(WindowClass.lpszClassName, PChar(FTitle),
WS_POPUP or WS_CAPTION or WS_CLIPSIBLINGS or WS_SYSMENU
or WS_MINIMIZEBOX,
GetSystemMetrics(SM_CXSCREEN) div 2,
GetSystemMetrics(SM_CYSCREEN) div 2,
0, 0, 0, 0, HInstance, nil);
// Создаётся специальное окно
FTitle := "";
FHandleCreated := True;
SetWindowLong(FHandle, GWL_WNDPROC, Longint(FObjectInstance));
if NewStyleControls then
begin
SendMessage(FHandle, WM_SETICON, 1, GetIconHandle);
SetClassLong(FHandle, GCL_HICON, GetIconHandle);
end;
SysMenu := GetSystemMenu(FHandle, False);
DeleteMenu(SysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
DeleteMenu(SysMenu, SC_SIZE, MF_BYCOMMAND);
if NewStyleControls then DeleteMenu(SysMenu, SC_MOVE, MF_BYCOMMAND);
end;
end;
А вот откуда берётся MainForm:
procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
Instance: TComponent;
begin
Instance := TComponent(InstanceClass.NewInstance);
TComponent(Reference) := Instance;
try
Instance.Create(Self);
except
TComponent(Reference) := nil;
raise;
end;
if (FMainForm = nil) and (Instance is TForm) then
begin
TForm(Instance).HandleNeeded;
FMainForm := TForm(Instance);
end;end;
Естественно, что Application.Handle и Application.MainForm.Handle
не имеют ничего общего.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.09.16;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.007 c