Написание плагинов на Delphi 2009

Автор SeUp, 20.08.09, 10:33:16

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

YorikER

Кстати метод CreateDSBase используется только в CreateDataSet и OpenCursor... В SetData (при приеме OleVariant от СП ЛОЦМАНА) он никак не используется, что-то в нем менять мне кажется бесполезно...

Chaa

Цитата: YorikER от 03.12.09, 17:11:17
Кстати метод CreateDSBase используется только в CreateDataSet и OpenCursor... В SetData (при приеме OleVariant от СП ЛОЦМАНА) он никак не используется, что-то в нем менять мне кажется бесполезно...
Вызывается OpenCursor.
SetData ->
    FSavedPacket := Value;
    Open ->
        SetActive(True) ->
            OpenCursor ->
                FDSBase := CreateDSBase;
                FDSBase.AppendData(FSavedPacket);

Chaa

Цитата: YorikER от 03.12.09, 14:53:40
это было в Delphi2010, там метод CreateDSBase отличается от Delphi2009.
Напишите здесь код CreateDSBase из D2010. А то у меня только 2009, нет возможности посмотреть.

Цитата: YorikER от 03.12.09, 16:52:02
Интересно, нельзя ли полученный пакет OleVatiant загрузить куда-то в буфер, а затем программным путем загнать в TClientDataSet (не через Data:=...)?
TClientDataSet этим и занимается, вызывая функции из midas.dll. Причем сам midas.dll работает нормально, по крайней мере стандартный клиент Лоцмана работает с новой версией midas.dll без проблем.
Проблема в том, что пакеты данных от СП получаются старой версии, с кодировкой метаданных ANSI, а в новом TClientDataSet ожидаются пакеты данных в кодировке UTF-8. В самом midas.dll кодировка метаданных задается установкой соответствующего свойства dspropUTF8METADATA в True. Разница между старым и новым TClientDataSet именно в значении этого свойства. Его и нужно нам изменить, даже странно, что в D2009 не предусмотрена такая возможность.

YorikER

function TCustomClientDataSet.CreateDSBase: IDSBase;
begin
  CreateDbClientObject(CLSID_DSBase, IDSBase, Result);
  Result.SetProp(dspropUTF8METADATA, integer(True));
  Result.SetProp(dspropUTF8ERRORMSG, integer(True));
end;

Я уже менял dspropUTF8METADATA на False... Не помогло... Но я кажется понял в чем дело, я использую старый midas.dll, в нем этой переменной нет... Скорее всего надо скомпилировать клиента с библиотекой midaslib, которая входит в состав Delphi 2010... Попробую, обязательно сообщу о результатах... Chaa, Спасибо за диалог, много нового открыл для себя...

YorikER

 :( Что-то не получается... Включил, изменил переменную в CreateDSBase... Все без изменений...

Chaa

#25
Цитата: YorikER от 05.12.09, 09:09:05
Что-то не получается... Включил, изменил переменную в CreateDSBase... Все без изменений...
Оказалось все немного сложнее. TClientDataSet из D2009 всегда ждет метаданные в формате UTF-8, независимо от этого флага. Если его установить, то тогда метаданные будут сохраняться в UTF-8, но читаться они все равно будут как есть. Это видно в функции AddFieldDesc, там вызывается MetaDataToUnicode, которая вызывает UTF8ToUnicode.
Я изменил фрагмент функции AddFieldDesc
FName := MetaDataToUnicode(szName);
на следующий:
FName := String(szName);
и у меня заработал модифицированный класс.

P.S.
Функция InternalInitFieldDefs объявлена как protected и virtual, так что можно смело наследовать оригинальный TClientDataSet, переопределять эту функцию и AddFieldDesc и все будет работать. Кажется, нашлось простое и правильное решение.

YorikER

Chaa спасибо... В Delphi 2010 еще желательно скомпилировать новый midas.dll, проект исходника открыт в BC++ и заменить стандартный в System32 на новый... У меня пока временная пауза... Обязательно попробую... и сообщу...

Chaa

Цитата: YorikER от 08.12.09, 08:35:04
В Delphi 2010 еще желательно скомпилировать новый midas.dll
А зачем? Что-то изменится при этом?

YorikER

Вопрос законный... Новый файл серьезно отличается от стандартного... Кто знает... Просматривая в суматохе TCustomClientDataSet и его предков достаточно глубоко я нарвался на некоторые функции, которые прописаны в midas.dll, на всякий случай, если делать свой T...ClientDataset, я думаю или надо включить midas в свою программу или скомпилировать новый...

YorikER

Chaa еще раз спасибо... Попробовал изменить функцию AddFieldDesc, все получилось... Только просто создать потомка TClientDataSet и переопределить процедуру InternalInitFieldDefs в лоб не прошло, она пользуется переменными из раздела private TCustomClientDataSet... Как в чистом виде открыть их в потомке я что-то плохо помню, надо покопаться в памяти... Поэтому я пошел по предыдущему пути, скопировал DBClient, переименовал TClientDataSet, исправил функцию AddFieldDesc, добавил процедуру Registred для регистрации компонента в своем пакете (чтобы визуально кидать его на форму), добавил модуль в свой пакет и скомпилировал... Все прошло "как в лучших домах Ландона, Парижу и Чухлинки"... Мне кажется что корректнее будет пересобрать существующий пакет с компонентом TClientDataSet, включить в компонент новое свойство UTF8MetaDataType тип boolean, и открыть его для пользователя. В зависимости от значения переписать AddFieldDesc... Скомпилировать... Вот только где файл исходного проекта я так не нашел... На досуге надо поискать... Еще раз спасибо, серьезная проблема решена... К сожалению уровень идей в разработках дошел до того, что уже необходимо вносить изменения в ядро ЛОЦМАНа, учитывая что оно мне недоступно, начинают бродить шальные мысли о написании своего аналога... Почетно, но нудно и долго... Пока взял паузу, и изучаю C#... Кто его знает, может пригодится...

Chaa

Быстренько написал потомок TClientDataSet.
Работает, но есть недостаток: длина имени поля из русских букв ограничена 16 символами из-за упаковки в UTF-8. Чтобы это устранить, нужно переписать весь метод AddFieldDesc. Если будет время, попробую позже.
А так в принципе просто:
FieldDesc := @FieldDescs[DescNo];
NewName := UTF8Encode(FieldDesc.szName);
StrLCopy(FieldDesc.szName, PAnsiChar(NewName), SizeOf(MIDASNAME) - 1);
inherited AddFieldDesc(FieldDescs, DescNo, FieldID, FieldDefs);

YorikER

Суматоха и нехватка времени - плохой помощник в таком деле, как объектно-ориентированное программирование (это я про себя, в качестве самокритики)... До меня наконец-то дошло, где я промахнулся при создании своего компонента - потомка от TDataSet...
В файле компонент TVLClientDataSet со свойством UTF8MetaData тип boolean, все работает, вроде бы без ограничений... Написано на Delphi 2010... Chaa, еще раз спасибо, балдею...

ptica_oz

Добрый день, уважаемые.
Пытаюсь написать плагин на Delphi 2010 и сразу же столкнулась с проблемкой...
В функции PgiCheckMenuItem не удаётся определить активность команд меню из-за несовпадения кодировок. А именно условие
if stFunction = 'menu_GetAttrList' then
никогда не выполняется.
Подскажите, пожалуйста, как это поправить?

ptica_oz

#33
Поторопилась я с вопросом, извините. Почитала по внимательнее ссылки и разобралась.

Chaa

Цитата: ptica_oz от 28.06.10, 10:22:16
Пытаюсь написать плагин на Delphi 2010
В этом случае лучше всего использовать COM-интерфейс для плагинов, т.е. функции InitUserDLLCom и PgiCheckMenuItemCom.

Chaa

Цитата: Chaa от 03.07.10, 20:12:32
В этом случае лучше всего использовать COM-интерфейс для плагинов, т.е. функции InitUserDLLCom и PgiCheckMenuItemCom.
Во вложении пример плагина на Delphi 2010.

Некоторые тонкости:
1. Нельзя использовать в плагине
Application.Handle := APluginCall.AppHandle;
так как объекты Application устроены по-разному.
Из-за этого есть небольшие проблемы с переключением между окном плагина и окном Лоцмана.
2. Нельзя, чтобы исключения из плагина попадали в Лоцман, так как объекты исключений разные.

Chaa

Цитата: Chaa от 13.07.10, 10:37:56
1. Нельзя использовать в плагине
Application.Handle := APluginCall.AppHandle;
так как объекты Application устроены по-разному.
Из-за этого есть небольшие проблемы с переключением между окном плагина и окном Лоцмана.
Собрался с силами и решил эту проблему.

Во вложении исправленный пример плагина для Delphi 2010 (должен работать и на Delphi 2009, хотя я не проверял).

Так же там исправлен один мелкий баг в VCL, который проявляется при использовании хинтов в некоторых компонентах, таких как TVirtualTreeView, когда DLL плагина постоянно загружается/выгружается (что делает Лоцман).