Последняя версия DataExpress 3 beta от 1 сентября 2019 года.
Изображение Скачать | Изображение Что нового?
См. также: Энциклопедия DX | Форум на develop-soft | Песочница
ИзображениеИзображениеИзображение

Вычисляемое поле в табличном представлении формы(ListWindow))

Все о том как сделать что-то с помощью скриптов.
Vofka18
Опытный
Сообщения: 253
Зарегистрирован: Вс мар 04, 2018 4:54 pm
Благодарил (а): 12 раз
Поблагодарили: 4 раза

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение Vofka18 » Чт сен 20, 2018 11:02 am

доброго времени суток.(Может кому пригодится)
Вот наконец-то добрался, и доделал свой модуль для вывода вычисляемых надписей в статус бар listWindow, теперь работает и в простых формах, и во всех остальных.
Выкладываю на общее суждение опытных пользователей :) и конструктивную критику.
Дело в том что во всех примерах, которые я просматривал, в массиве (для работы подключаемых действий, в нескольких окнах или формах) всегда сохраняются разного рода события. А в моем случае, вроде как и окна меняются, и события я не сохранял, но тем не менее все работает. Может я пока не смог спровоцировать ошибку(может позже что-то вылезет).
Поэтому если кому не сложно, в свободное время, просмотрите пожалуйста и скажите свое "Фе" :D
Заранее благодарен! ;)
Вложения
StatusBarInLWnd.7z
(2.52 КБ) 45 скачиваний

Аватара пользователя
admin
Разработчик
Сообщения: 4613
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская
Благодарил (а): 19 раз
Поблагодарили: 90 раз

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение admin » Чт сен 20, 2018 1:49 pm

Vofka18 писал(а):Дело в том что во всех примерах, которые я просматривал, в массиве (для работы подключаемых действий, в нескольких окнах или формах) всегда сохраняются разного рода события. А в моем случае, вроде как и окна меняются, и события я не сохранял, но тем не менее все работает. Может я пока не смог спровоцировать ошибку(может позже что-то вылезет).

Только потому, что в базе нет действий и скриптов, использующих это событие. Как только они появятся, ошибки неизбежны.

Vofka18
Опытный
Сообщения: 253
Зарегистрирован: Вс мар 04, 2018 4:54 pm
Благодарил (а): 12 раз
Поблагодарили: 4 раза

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение Vofka18 » Чт сен 20, 2018 2:13 pm

Как только они появятся, ошибки неизбежны.

Я не доконца разобрался с подобными ситуациями, вроде и все понятно, но где-то не догоняю... Если я правильно понял мне надо сделать так?

Код: Выделить всё

type
  SetRec = record
  Fm: TdxForm;
  expr1,expr2,expr3,expr4: String;
  col1,col2,col3,col4:string;
  AlignR1,AlignR2,AlignR3,AlignR4:boolean;
  mySat:TStatusBar;
  lbl1,lbl2,lbl3,lbl4:TLabel;
 
 AfterScroll: TNotifyEvent;///!!!!!!!!!!!!
 
end;   


и при подписке на данное событие нужно вроде сделать так:

Код: Выделить всё

  VCData.AfterScroll:=VCData.fm.OnAfterScroll; //fm-это некая форма, которая тоже хранится в массиве
  VCData.fm.OnAfterScroll:=@AfterScroll;


но вот как вызвать именно это событие из массива? вот тут боюсь напортачить... Куда нужно вставить этот код?
За образец я взял Ваш код из 'Дерево для запросов'. Но не понимаю никак, событие вызывает само себя?
У себя я этот код пока не использовал(не удивляйтесь что переменные из Вашего кода, но структура у меня такаяже)

Код: Выделить всё

procedure SourceQueryAfterOpen(Sender: TObject);
var
  QT: TQTData;
begin
  QT := FindDataBySourceQuery(Sender);
  if QT.SrcQAfterOpen <> nil then QT.SrcQAfterOpen(Sender);
  UpdateTree(QT);
end; 

Vofka18
Опытный
Сообщения: 253
Зарегистрирован: Вс мар 04, 2018 4:54 pm
Благодарил (а): 12 раз
Поблагодарили: 4 раза

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение Vofka18 » Пт сен 21, 2018 10:41 am

Ну вроде разобрался, прошу прощения за глупые вопросы, сохраняю события, и вызываю их из штатного события. Надеюсь все правильно понял...

Код: Выделить всё

procedure AfterScroll(Sender: TObject);
begin
//debug('scroll');
  if VCData.arrAfterScroll <> nil then VCData.arrAfterScroll(Sender);
// Вычисляем надписи.
  if VCData.fm <> nil then VC_SetLabel(VCData);
end;

procedure LwndOnAfterOpen(Sender: TObject);
var
vcd: setRec;
begin
//debug('Open'+ inttostr(Length(setArr)));

// Ищем нужный элемент массива при открытии окна Формы.
  vcd:=FindDataByForm(Sender);
  if vcd.arrAfterOpen <> nil then vcd.arrAfterOpen(Sender);
// Присваиваем значение из массива в глобальную переменную,
// для передачи в AfterScroll
  VCData:=vcd;
//debug('Open'+ inttostr(Length(setArr)));
end;

procedure createLWnd(Sender: TObject; aWindow: TForm);
var
n:integer;
begin
// Дополняем глобальную переменную нужными данными, и компонентами
// для занесения в массив  setArr

  //TListWindow(aWindow).FormView.Form.OnAfterScroll:=@AfterScroll;
  VCData.Fm:=TdxForm(TListWindow(aWindow).FormView.Form);

  VCData.arrAfterScroll:=TListWindow(aWindow).FormView.Form.OnAfterScroll;
  VCData.arrAfterOpen:=TListWindow(aWindow).FormView.Form.OnAfterOpen;

  TListWindow(aWindow).FormView.Form.OnAfterScroll:=@AfterScroll;
  TListWindow(aWindow).FormView.Form.OnAfterOpen:=@LwndOnAfterOpen;
 
  with VCData do
  begin
    .......
    .......
  end;

// Добавляем элемент настроек с компонентами в массив
  n := Length(setArr);
  SetLength(setArr, n + 1);
  setArr[n] := VCData;
end;                                         

Спасибо!
Вложения
StatusBarInLWnd.7z
(2.57 КБ) 42 скачивания

Аватара пользователя
admin
Разработчик
Сообщения: 4613
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская
Благодарил (а): 19 раз
Поблагодарили: 90 раз

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение admin » Пт сен 21, 2018 11:29 am

Немного не так.
1. Есть процедура/функция, вызываемая программой при подключении действия (прописанная в OrigName). Вот там и создавайте новый элемент массива.
2. Опять же, Вы подключились к событию объекта OnCreateListWindow. А старый, возможный, обработчик не сохранили и не вызываете его в новом.
3. Подключились к событиям формы правильно. Но...
4. ... никогда не используйте глобальную переменную для хранения элемента массива, чтобы использовать его в разных событиях. В каждом обработчике событий надо снова искать элемент массива. Почему? Потому что есть риск пересечения работы с таким же действием из другой формы. Ведь модуль расширения глобальный, а не свой собственный для каждого экземпляра действия.
5. Если допускается использование нескольких действий в форме, то требуется доработка поиска элемента в массиве. Пример можно глянуть в новом расширении.

Vofka18
Опытный
Сообщения: 253
Зарегистрирован: Вс мар 04, 2018 4:54 pm
Благодарил (а): 12 раз
Поблагодарили: 4 раза

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение Vofka18 » Пт сен 21, 2018 12:01 pm

admin писал(а):Немного не так.
1. Есть процедура/функция, вызываемая программой при подключении действия (прописанная в OrigName). Вот там и создавайте новый элемент массива.
2. Опять же, Вы подключились к событию объекта OnCreateListWindow. А старый, возможный, обработчик не сохранили и не вызываете его в новом.
3. Подключились к событиям формы правильно. Но...
4. ... никогда не используйте глобальную переменную для хранения элемента массива, чтобы использовать его в разных событиях. В каждом обработчике событий надо снова искать элемент массива. Почему? Потому что есть риск пересечения работы с таким же действием из другой формы. Ведь модуль расширения глобальный, а не свой собственный для каждого экземпляра действия.
5. Если допускается использование нескольких действий в форме, то требуется доработка поиска элемента в массиве. Пример можно глянуть в новом расширении.


1. Это требование или рекомендация? Дело в том, что в процедуре(прописанная в OrigName) нет доступа к ListWindow(а мне нужно его в массив добавить), он появляется только в OnCreateListWindow, поэтому и пришлось немного разделить заполнение массива, и сделать это через глобальную переменную. Можно ли оставить так? или надо искать другие пути?
2. Исправлю, тут же не нужно ничего записывать в массив? просто создать переменную типа OLD_OnCreateListWindow, и вызывать ее в событии OnCreateListWindow? Или также добавлять в массив, и вызывать через поиск?
4. Думал будет быстрее работать, чтоб не крутить поиск при скроллинге. Но если так, то исправлю.
5. Понял как это сделать но не понял зачем? это если в текущей форме подключено несколько одинаковых действий? или любых действий с одинаковыми событиями? Ну по сути, надо так надо. Сейчас переделаю ;)

Vofka18
Опытный
Сообщения: 253
Зарегистрирован: Вс мар 04, 2018 4:54 pm
Благодарил (а): 12 раз
Поблагодарили: 4 раза

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение Vofka18 » Пт сен 21, 2018 12:56 pm

Код: Выделить всё

// Ищем данные, принадлежащие действию. Поиск идет с конца, потому что на форме
// может быть более одного действия, а сначала будет выполняется обработчик события
// последнего подключенного действия.
// Т. к. на форме может быть более одного действия, в массиве могут быть
// элементы с одинаковой ссылкой на форму и чтобы цепочка действий работала
// корректно в обработчиках событий перед вызовом обработчика предыдущего
// действия мы должны "отключать" текущий элемент (флаг Disabled).

function FindARData(Fm: TObject): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := High(ARArr)-1 downto 0 do
    if (ARArr[i].Fm = Fm) and not ARArr[i].Disabled then
    begin
      Result := i;
      Exit;
    end;
end;   

У меня почемуто этот код не заработал, пока не убрал -1 в цикле.Это нормально? :D
Вот моя копия

Код: Выделить всё

function FindDataByForm(frm: TObject): integer;
var
  i: Integer;
begin
Result := -1;
  for i := High(setArr)  downto 0 do
    if (setArr[i].fm= frm) and not setArr[i].Disabled then
    begin
      Result := i;
      Exit;
    end;

  //RaiseException(erCustomError, 'Не удается найти форму.');
end;   

Аватара пользователя
Гocть
Эксперт
Сообщения: 1583
Зарегистрирован: Пн ноя 27, 2017 8:02 am
Поблагодарили: 9 раз

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение Гocть » Пт сен 21, 2018 1:15 pm

Вариантов может быть два:
for i := High(ARArr) downto 1 do и for i := High(ARArr)-1 downto 0 do
а делать смещение или нет, это уже зависит от того, что вы циклюете и что нужно получить на выходе (i, i-1 или i+1). Массивы обычно считаются с нуля. Если надо пройтись по тексту, можно начинать с единицы.
Фрилансер. Разработка на заказ. Консультирование.

Аватара пользователя
admin
Разработчик
Сообщения: 4613
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская
Благодарил (а): 19 раз
Поблагодарили: 90 раз

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение admin » Пт сен 21, 2018 1:19 pm

1. Все, что касается разработки подключаемых действий - это рекомендации. Я предлагаю универсальный шаблон, по которому можно разработать подключаемое действие, которое не будет конфликтовать с любыми другими действиями. Я не беру в счет случаи, когда действия могут конфликтовать в силу особенностей работы. Думаю, это будет редким явлением. А вот "стырить" событие - это запросто. Если кто найдет более простой способ разработки действий, будет очень интересно посмотреть. Я других способов не вижу.
2. Лучше все-таки в элемент массива. На всякий случай. Даже если действия не будут конфликтовать всегда найдется база, где это событие может использоваться - в модуле формы, например.
4. Вряд ли это сильно повлияет на скорость.
5. Да. Дело в том, что элемент в массиве ищется по указателю на форму (или другой компонент). Два действия будут иметь одинаковый указатель на форму. Т. е. всегда будет находится только первый элемент. Поэтому надо каким-то образом обойти эту проблему. Например, можно использовать флаг, который временно исключает элемент из поиска. Флаг устанавливается перед вызовом старого обработчика и сбрасывается после. В Вашем случае в этом нет необходимости, но желательно сделать проверку, чтобы не было двух одинаковых действий на форме.

Аватара пользователя
admin
Разработчик
Сообщения: 4613
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская
Благодарил (а): 19 раз
Поблагодарили: 90 раз

Re: Вычисляемое поле в табличном представлении формы(ListWindow))

Сообщение admin » Пт сен 21, 2018 1:20 pm

Vofka18 писал(а):У меня почемуто этот код не заработал, пока не убрал -1 в цикле.Это нормально?

Не путайте High с Length. High возвращает верхнюю границу массива, а Length - длину.