Создание cxGridDBColumn в DLL вызывает Access violation, если форма создана второй раз

X11
Дата: 19.05.2011 16:06:47
Создание cxGridDBColumn в DLL вызывает Access violation, если форма создана второй раз.

Продолжение этой темы: http://www.sql.ru/forum/actualthread.aspx?tid=852063

Есть на форме пустой cxGrid (без колонок) и кнопка с кодом создания колонки
procedure TfmApartSearch2.Button1Click(Sender: TObject);
Var
 col: TcxGridDBColumn;
begin
 col := cxGrid1DBTableView1.CreateColumn;
end;

Если форма создана первый раз, то проблем нет и колонка создается.
Но если (не закрывая главное приложение) форма создана второй раз, третий, то код создания колонки вызывает AV.

Пробовал даже так.
Открыл форму, закрыл форму. второй раз открыл форму, нажал кнопку - > AV.

Что-то опять где-то с GDI+
X11
Дата: 19.05.2011 16:22:31
Принцип простой.
DLL (их, плагинов, может быть несколько) загружаеются все при старте программы.
Для каждого плагина в нужном месте создается пункт меню в главном меню приложения, создается также Action. На Action.onExecute вешается процедура из плагина. Эта процедура создает и показывает главную форму плагина.

+

procedure TfmMain.LoadPlugins();
Var
PlugExec : procedure(sender: TObject) of object;
PlugType : function: integer; //Объявление функции, которая будет возвращать тип плагина
GetConnectInfo : procedure(fbclient, DB: PChar; db_connected: boolean);
GetUserData : procedure(UID: integer; UserName: PChar);
MenuCaption : function : PChar;

dxInitializeGDIPlus, dxFinalizeGDIPlus: procedure;

//для вывода кнопки (меню) плагина
act: TAction;
ItemLink: TdxBarItemLink;
mnItem: TdxBarSubItem;
im, MenuTag: integer;
isFound: boolean;
i, iDllHandle: integer;
begin
iDllHandleAreas := 0;//для поиска и загрузки плагина Участки
slPlagins := TStringList.Create;
slPlaginsHandles := TStringList.Create;
Log(IncludeTrailingPathDelimiter(sAppPath2) + 'Plugins\');

FindPlugins(IncludeTrailingPathDelimiter(sAppPath2) + 'Plugins\');

Log('Найдено: ' + IntToStr(slPlagins.Count));

if slPlagins.Count <= 0 then
begin
FreeAndNil(slPlagins);
exit;
end;

LOG(self.Name + ' Загрузка плагинов');

//если найдены плагины, то пытаемся их загрузить
for I := 0 to slPlagins.Count - 1 do begin
//iDllHandleAreas
iDllHandle := LoadLibrary(PChar(slPlagins[i]));//загружаем библиотеку
slPlaginsHandles.Add(IntToStr(iDllHandle));

//если библиотека успешно загружена
if iDllHandle <> 0 then begin

dxInitializeGDIPlus := GetProcAddress(iDllHandle, 'dxInitializeGDIPlus');
if Assigned(dxInitializeGDIPlus) then
dxInitializeGDIPlus;

//ищем адрес нужных функций и процедур
@plugExec := GetProcAddress(iDllHandle, 'PluginExec');
@plugType := GetProcAddress(iDllHandle, 'PluginType');
@GetConnectInfo := GetProcAddress(iDllHandle, 'GetConnectInfo');
@GetUserData := GetProcAddress(iDllHandle, 'GetUserData');

//передаём в плагин данные о пользователе и базе
GetUserData(UserData.UserID, PChar(UserData.UserName));
GetConnectInfo(PChar(DM.fibDB.LibraryName), PChar(DM.fibDB.DBName), DM.fibDB.TestConnected);

// NewButton := TdxBarButton.Create(self);

@MenuCaption := GetProcAddress(iDllHandle, 'MenuCaption');
act := TAction.Create(am1);
act.ActionList := am1;
act.onExecute := plugExec;//прикручиваем процедуру plugExec из плагина
act.caption := MenuCaption;
act.Hint := MenuCaption;

// если нашли плагин Участки
if MenuCaption = constAreasPluginsName then iDllHandleAreas := iDllHandle;

{ ищем нужный пункт меню, к нему прикрутим процедуру вызова главного окна плагина}
mnItem := TdxBarSubItem.Create(MainMenu);
isFound := False;
MenuTag := plugType; { Tag кнопки, которую нужно найти }
for im := 0 to MainMenu.ItemLinks.Count -1 do
begin
ItemLink := MainMenu.ItemLinks[im];

if ItemLink.Item.Tag = MenuTag then
begin
isFound := True;
mnItem := TdxBarSubItem(ItemLink.Item);
break;
end;
end;//for im := 0 to MainMenu.ItemLinks.Count -1 do

if isFound then
begin
ItemLink := mnItem.ItemLinks.Add;
ItemLink.Item := TdxBarButton.Create(Self);
ItemLink.Item.Action := act;
end;
Log(self.Name + ' Плагин успешно подключен: ' + MenuCaption);
end;// if iDllHandle <> 0 then begin
end;//for
end;
AndroidZombi
Дата: 19.05.2011 16:27:22
X11, а если протрэйсить дебугером до этого самого кода создания колонки? Может, там cxGrid1DBTableView1 = nil?
X11
Дата: 19.05.2011 16:30:07
Не, думаю, что nil тут не причём. Скорее всего опять GDI+
Gwa
Дата: 19.05.2011 16:36:22
X11,
что значит форма создана второй раз?
новый экземпляр формы?
Ramin Hashimzade
Дата: 19.05.2011 16:44:54
1) оформируй код с тегом SRC
2) не имея значение сколько раз открывается форма (хоть 50) не может быть АВ если написать правильно...
X11
Дата: 19.05.2011 16:52:39
Ура. Я сделал ещё проще.

У главной формы плагина в модуле, в самом конце дописал

initialization
  dxInitializeGDIPlus;

finalization
  dxFinalizeGDIPlus;

Все остальные dxInitializeGDIPlus и dxFinalizeGDIPlus поубирал из главного приложения и из плагина.
X11
Дата: 19.05.2011 16:53:50
Ramin
1) оформируй код с тегом SRC
2) не имея значение сколько раз открывается форма (хоть 50) не может быть АВ если написать правильно...


1. Процедура большая, думал так сократить
2. Если бы знать ещё, как правильно я бы здесь и тему не создавал.
Ramin Hashimzade
Дата: 19.05.2011 16:54:46
X11
Ура. Я сделал ещё проще.

У главной формы плагина в модуле, в самом конце дописал

initialization
  dxInitializeGDIPlus;

finalization
  dxFinalizeGDIPlus;

Все остальные dxInitializeGDIPlus и dxFinalizeGDIPlus поубирал из главного приложения и из плагина.

все это мне не нравится!
X11
Дата: 19.05.2011 17:02:55
Тем не менее работает :)

А как по другому в моём случае?