Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi (до версии 2009) - часть 5

Автор: ppkp
Дата сообщения: 27.03.2010 17:29
Подскажите, почему вылетает с Access Violation PropInfo^.Name := Value;

TBaseClass = class
protected
function GetPropCount: integer;

function GetPropName(Index: integer): shortstring;
procedure SetPropName(Index: integer; Value: shortstring);
public
property PropCount: integer read GetPropCount;
property PropName[Index: integer]: shortstring read GetPropName write SetPropName;
end;

//работает
function TBaseClass.GetPropName(Index: integer): shortstring;
var
PropInfo: PPropInfo;
PropList: PPropList;
begin
GetMem(PropList, PropCount * SizeOf(pointer));
GetPropInfos(ClassInfo, PropList);
PropInfo := PropList^[Index];
if PropInfo <> nil then Result := PropInfo^.Name else Result := '';//Здесь все нормально
FreeMem(PropList, PropCount * SizeOf(pointer));
end;

//вылетает, хотя, практически, то же самое.
procedure TBaseClass.SetPropName(Index: integer; Value: shortstring);
var
PropInfo: PPropInfo;
PropList: PPropList;
begin
GetMem(PropList, PropCount * SizeOf(pointer));
GetPropInfos(ClassInfo, PropList);
PropInfo := PropList^[Index];
if PropInfo <> nil then PropInfo^.Name := Value;//А здесь вылетает !!!!!!
FreeMem(PropList, PropCount * SizeOf(pointer));
end;
Автор: Aleksandr N
Дата сообщения: 27.03.2010 17:46
V1s1ter
Про сепаратор я знаю, я не хотел его использовать. Хотел найти место где описывается кнопка и сместить её начальные координаты. В место этого пришлось добавить свойство и по его значению изменить способ прорисовки.
Автор: Frodo_Torbins
Дата сообщения: 28.03.2010 11:07
ppkp
А что вообще должен делать этот код? Вы уверенны что туда принципиально можно писать?
Автор: ppkp
Дата сообщения: 28.03.2010 14:35
Frodo_Torbins
Мне нужно, чтобы в RTTIInspector (или в другом) в левой колонке отображались не имена свойств (типа 'MyProp1'), а их псевдонимы из массива строк ('Мое Свойство Один'). В C# это очень удобно делается атрибутом [DisplayName]
Автор: Frodo_Torbins
Дата сообщения: 28.03.2010 16:56
ppkp
На сколько я знаю RTTI в Delphi предназначено только для чтения. Я бы на вашем месте копал в сторону RTTIInspector.
Автор: ppkp
Дата сообщения: 28.03.2010 17:26
Frodo_Torbins
Дык. Я в него и копаю, только мудрено там, а справки толковой они не сделали
ЗЫ Может кто работал с VertucalGrid - как там заменить значения полей в левой колонке на псевдонимы ?
Автор: Frodo_Torbins
Дата сообщения: 28.03.2010 17:45
ppkp
Нечто типа этого: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=784 ?
Автор: ppkp
Дата сообщения: 28.03.2010 19:51
Frodo_Torbins
В принципе, да. Но глубоко его не копал. А тут уже стоит TcxRTTIInspector.
Автор: AviDen
Дата сообщения: 29.03.2010 12:02
ppkp, RTTI-информация в экзешнике хранится в секции .code, которая не допускает модификации (т.к. при загрузке образа в память страницы помечаются атрибутами read & execute, yо никак не write). И это правильно, т.к. в частности, что бы Вы приказали делать, если присваиваемое значение имеет бОльшую длину (а память под строку выделена по фактическому содержимому без каких-л. запасов). Ну, я уже молчу про много других причин невозможности описанной операции.
Автор: Man_Without_Face
Дата сообщения: 29.03.2010 12:17

Цитата:
В DLL именно в том виде, что ты показал - нет. Я ж говорю, проще всего это компилять в BPL, которую и подключать к проекту. BPL-ки, кстати, можно же и динамически грузить, если я не ошибаюсь, т.е. они полноценно заменяют DLL.

Где можно прочитать про создание bpl, в гугле ничего не нашел?
И вопрос второй:

Цитата:
кстати
Код:
Procedure PluginExec(AppHandle:THandle)
begin
Application.Handle:=AppHandle;
...
finally
Application.Handle:=0;

не создает отдельного окна

Куда это вставить?

Автор: ppkp
Дата сообщения: 29.03.2010 12:32
AviDen
Это все я понял, потому и использую TcxRTTIInspector из DevExpress. Только для него прктически никакой справки нет. Подсказали написать обработчик OnDrawRowHeader. Написал
with AHeaderViewInfo do CaptionsInfo[0].Caption := sMyPropName[Row.Index];
и все получилось. Только у RTTIInspector по умолчанию поля сортируются по алфавиту, поэтому неправильно присваиваются значения. А как это устранить - наверное, это уже из другого топика.
Автор: AviDen
Дата сообщения: 29.03.2010 13:11
Man_Without_Face, BPL (Borland Package Library) - это то же самое DLL, только с доп. возможностями специально для Delphi-приложений. Почитать - в хелпе или любой книге/статье по Delphi. Создаётся оно, как и DLL, из меню File | New | Other (и на вкладке New выбрать пункт Package).

В целом же, основное их отличие от DLL состоит в том, что наряду с кодом, они могут экспортировать и типы данных (при использовании DLL приходится городить целый огород с type libraries и интерфейсами)

Добавлено:
ppkp, реализовывать локализацию имен свойств, перекрывая OnDraw - это жеээсть. А что, TcxRTTIInspector не позволяет задать что-то типа алиасов или отображаемых имен для свойств? Чтобы по-человечески было.

Man_Without_Face, "это" нужно вставить в процедуру в DLL-ке, отображающую отчёт. И вообще, ты определись, что ли, будешь ты идти путём написания BPL, или пользовать этот способ (а то они вроде как взаимоисключающие). Судя по всему, тебе проще будет забить на BPL и использовать способ с присвоением Application.Handle.
Автор: ppkp
Дата сообщения: 29.03.2010 15:44
AviDen

Цитата:
А что, TcxRTTIInspector не позволяет задать что-то типа алиасов или отображаемых имен для свойств? Чтобы по-человечески было.

Вот я тоже думал про псевдонимы свойств. Это было бы чудо. В C# все очень удобно делается атрибутом [DiplayName]. По TcxRTTIInspector справка минимальная и ничего не понятно. Даже не знаю как отключить сортировку свойств по алфавиту или узнать какой объект инспектируется
Автор: Man_Without_Face
Дата сообщения: 29.03.2010 15:47
AviDen
Все равно не догоняю, ошибка: [DCC Error] bbc5_reports.dpr(21): E2003 Undeclared identifier: 'Application'

library bbc5_reports;

uses
SysUtils,
Classes,
uReports in 'uReports.pas' {frmReports};

{$R *.res}
procedure DisplaySampleReport(AppHandle:THandle);
begin
Application.Handle:=AppHandle;
//frmReports := frmReports.Create(nil);
try
frmReports.frxReport1.showreport;

finally
//frmReports.Free;
Application.Handle:=0;
end;
end;

exports DisplaySampleReport;

begin
end.
Автор: volser
Дата сообщения: 29.03.2010 16:18
Man_Without_Face

Цитата:
Undeclared identifier: 'Application'

И что здесь не понятно? Или вы первый раз видите такую ошибку? Тогда вам рано писать плагины.
Автор: Man_Without_Face
Дата сообщения: 29.03.2010 16:57
volser
Я про то что нельзя сюда вставить:
procedure DisplaySampleReport(AppHandle:THandle);
и
Application.Handle:=0;
Автор: AviDen
Дата сообщения: 29.03.2010 17:01
Man_Without_Face, добавь forms в Uses-list

Добавлено:
P.S. А в целом согласен с volser
Автор: Man_Without_Face
Дата сообщения: 30.03.2010 08:05
volser
AviDen
Скорее всего рано, но поставленную задачу нужно выполнить. Все равно вылетает та же ошибка при вызове отчета:
Access violation at address 034673E4 in module 'bbc5_reports.dll'. Read of address 00000378
Помогите пож, мне главное чтобы отчет вызывался, остальное все по аналогии будет. Спасибо.
Автор: greenpc
Дата сообщения: 30.03.2010 10:41
Man_Without_Face

Цитата:
Access violation at address 034673E4 in module 'bbc5_reports.dll'. Read of address 00000378

а не подскажешь что находится в 'bbc5_reports.dll' по смещению 0х034673E4 ?
у нас телепатов нету

Код: procedure DisplaySampleReport(AppHandle:THandle);
begin
Application.Handle:=AppHandle;
frmReports := frmReports.Create(nil);
try
try
frmReports.frxReport1.showreport;
except
    on e: Exception do ShowMessage(E.message);
end; // try/except
finally
FreeAndNil(frmReports);
Application.Handle:=0;
end;
end;
Автор: Man_Without_Face
Дата сообщения: 30.03.2010 12:44
greenpc
Не тот, не тот вариант не работает у меня (Access violation). Вот полностью весь код: [more]
program bbc5;

uses
Forms,
uMain in 'uMain.pas' {frmMain};

{$R *.res}

begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TfrmMain, frmMain);
Application.Run;
end.



unit uMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, cxGraphics, cxLookAndFeels, cxLookAndFeelPainters, Menus, StdCtrls,
cxButtons, DB, DBTables, uReports;

type
TfrmMain = class(TForm)
cxButton1: TcxButton;
Database1: TDatabase;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure cxButton1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmMain: TfrmMain;

implementation
{$R *.dfm}

procedure TfrmMain.cxButton1Click(Sender: TObject);
var
LibHandle: THandle;
fDisplaySampleReport: procedure;
begin
LibHandle := LoadLibrary('bbc5_reports.dll');
if LibHandle = 0 then
raise Exception.Create('Не могу загрузить файл отчета...')
else
begin
try @fDisplaySampleReport := GetProcAddress(LibHandle, 'DisplaySampleReport');
if @fDisplaySampleReport <> nil then

fDisplaySampleReport; // Вызов процедуры из Dll
except
on E: Exception do
ShowMessage('Ошибка: ' + E.Message);
end;
end;
FreeLibrary(LibHandle); // Освобождение памяти занятой Dll

end;


procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
Release;
frmMain := nil;
end;

end.





library bbc5_reports;

{ 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, forms, uMain,
Classes, dialogs,
uReports in 'uReports.pas' {frmReports};

{$R *.res}
procedure DisplaySampleReport(AppHandle:THandle); stdcall;
begin
Application.Handle:=AppHandle;
frmReports := frmReports.Create(nil);
try
frmReports.frxReport1.showreport();
finally
FreeAndNil(frmReports);
Application.Handle:=0;
end;
end;

exports DisplaySampleReport;

begin
end.




unit uReports;

interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, frxClass;

type
TfrmReports = class(TForm)
frxReport1: TfrxReport;
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmReports: TfrmReports;


implementation
uses uMain;
{$R *.dfm}

end.
[/more]
CodeGear 2009 + FastReports 4.8

Добавлено:
frmReports := frmReports.Create(nil); //Вроде сюда ругается, но почему?
Автор: greenpc
Дата сообщения: 30.03.2010 12:59
Man_Without_Face
во-первых несоотвествие параметров !

Код: procedure TfrmMain.cxButton1Click(Sender: TObject);
var
LibHandle: THandle;
fDisplaySampleReport: procedure(appHandle : THandle);
....

if @fDisplaySampleReport <> nil then
fDisplaySampleReport(Application.Handle); // Вызов процедуры из Dll
Автор: volser
Дата сообщения: 30.03.2010 14:14
Man_Without_Face
Может все таки так?

Цитата:
frmReports := TfrmReports.Create(nil); //Вроде сюда ругается, но почему?

Автор: Man_Without_Face
Дата сообщения: 30.03.2010 14:49
greenpc Спасибо
volser В точку, спасибо, все пошло.
Я же могу через компонент Tdatabase, кот находится на главной форме, конектиться к базе в Dll? Может дописать нужно что нибудь в Uses, потому что так ошибку выдает:
project bbc5.exe raised exception class EClassNotFount with message 'Class TfrxBDEQuery not found".

Автор: greenpc
Дата сообщения: 30.03.2010 15:02
Man_Without_Face

Цитата:
Я же могу через компонент Tdatabase, кот находится на главной форме, конектиться к базе в Dll
нет.
в длл можно передать коннект, id и т.д. это будет правильно.
а если хочется получить Tdatabase и еще из главного приложения то разруливать надо через хэндл - большой гемор. сделать проще - решение подсказывал AviDen
через bpl.
ЗЫ: вопрос. а зачем пихать отчет в отдельный модуль если все денные для этого отчета в главном окне? имело бы смысл это делать если в самой длл читались/создавались данные.
Автор: Odysseos
Дата сообщения: 30.03.2010 15:05
Man_Without_Face

Я же могу через компонент Tdatabase, кот находится на главной форме, конектиться к базе в Dll?

Нет, не можете. Если используются просто dll - не bpl! - то НИКАКИМИ из объектов, объявленных и созданных в exe, из dll пользоваться нельзя - и наоборот (не, ну попробовать-то можно - но результат, скорей всего, разочарует). В Вашем случае - нужно два отдельных коннекта к БД, для exe и для dll.
Автор: greenpc
Дата сообщения: 30.03.2010 15:06
Man_Without_Face

Цитата:
project bbc5.exe raised exception class EClassNotFount with message 'Class TfrxBDEQuery not found".

переводим ошибку: класс TfrxBDEQuery не найден. ищем где описан данный клас.
unit frxBDEComponents.
Автор: Man_Without_Face
Дата сообщения: 30.03.2010 15:20
greenpc

Цитата:
ЗЫ: вопрос. а зачем пихать отчет в отдельный модуль если все денные для этого отчета в главном окне? имело бы смысл это делать если в самой длл читались/создавались данные.

Это выдумал не я, у старшего программиста есть проект, в кот примерно 50 отчетов, по ему ведомым причинам нужно вынести отчеты в dll или bpl файл. Конект с базой, он сказал лучше сделать через exe, но вроде можно и так. По dll у меня есть хоть какая то информаци (DelphiWorld6), про bpl там ничего нету, в нете тоже ничего не нарыл интересного.
Odysseos

Цитата:
два отдельных коннекта к БД, для exe и для dll.

Я так понимаю если я на форму в dll вытащу и настрою Tdatabase как в главной форму, то так не получится, нужно как то по другому?


Автор: greenpc
Дата сообщения: 30.03.2010 15:24
Man_Without_Face
что за база?
Автор: Man_Without_Face
Дата сообщения: 30.03.2010 15:27
greenpc
Понял конект есть, а вот если на маин положить компонент то запрашивает пароль спасибо.
Odysseos Наверное выше написанный вопрос снят, спасибо.
Что бы данные передать для запроса из меин формы я так понимаю можно использовать:
procedure SetData(Kind:TDataKind;const Buffer;Size:Integer)). ?



Добавлено:
greenpc sybase 8.0
Автор: AviDen
Дата сообщения: 30.03.2010 15:28
Odysseos

Цитата:
Если используются просто dll - не bpl! - то НИКАКИМИ из объектов, объявленных и созданных в exe, из dll пользоваться нельзя - и наоборот (не, ну попробовать-то можно - но результат, скорей всего, разочарует)

Хм, а я вот задумался - с чего бы это? Вроде никаких принципиальных препятствий для этого не существует, адресное пространство и области видимости различных системных объектов/хендлом и прочего у основного модуля и dll общие. Единственное, что нужно передавать хендл объекта Application, если шарится работа с GUI и пользовать borldmm, если передаются/возвращаются параметры типа строка / variant / interface / dynamic array. Но пробовать - не пробовал, скажу честно ))

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

Предыдущая тема: Clipper 5


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.