Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  05:19[Войти] | [Зарегистрироваться]
Ответ на вопрос № 77021

18-05-2010 07:32
Можете пинать, можете закидать помидорами, но помогите ради бога, безлимитное потребление кофе и 22 часа работы сделали свое дело. Имею MDIForm и 2 MDIChild окна. Первое окно вызывает второе при помощи этой процедуры

  private
    { Private declarations }
      procedure CreateColVisible(const N: string);
...
procedure TQWorkerForm.CreateColVisible(const N: string);
var
  Child: TColVisible;
begin
  Child:=TColVisible.Create(Application);
end;
...
procedure TQWorkerForm.FieldVisibleMenuClick(Sender: TObject);
begin
...
CreateColVisible('');
end;

Не могу понять, как в первой MDIChild (QWorkerForm) узнать, открыта вторая MDIChild (ColVisible) или нет. Дело в том, что ColVisible должна передать в QWorkerForm некоторые значения перед своим закрытием, причем, сразу после ее закрытия QWorkerForm должна выполнить ряд процедур. Ну тупой я, наверно, помогите, пинать разрешается. Пробовал "ловить" через QWorkerForm.onActivate или QWorkerForm.onDeActivate, но получается ерунда, потому что достаточно "пнуть" QworkerForm и соответственно происходит onActivate/onDeActivate ...

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

26-05-2010 22:18
Более чем исчерпывающее объяснение, спасибо, скопипастил себе в документацию как памятку, уверен другим тоже пригодится и решит многие проблемы. Спасибо!

25-05-2010 14:54
Продолжение...

При создании новой формы Delphi автоматически объявляет глобальную переменную для созданной формы. Для чего? А для того, чтобы сделать эту форму автосоздаваемой и присвоить этой переменной ссылку на созданный экземпляр формы. На мой взгляд, от такого подхода - один вред, поскольку такой подход:

1. Формирует у новичков впечатление, что они разрабатывают один готовый экземпляр формы, с которым они потом и работают, который не надо ни создавать, ни уничтожать. То, что они разрабатывают не один экземпляр формы, а класс форм, доходит потом очень долго и с трудом. К тому времени, когда это, наконец, доходит, успевает сформироваться куча неправильных стереотипов и неправильных приёмов работы. Об этом я писал, в частности, в »вопрос КС №68068«
2. Сильно отодвигает понимание новичками механизма создания форм, а также того, что в общем случае объекты следует создавать и уничтожать самостоятельно.
3. Приучает новичков работать с глобальными переменными, что само по себе плохо.
4. Создаёт глобальные переменные даже для тех, кто их не использует и кому они вовсе не нужны.

Включение форм и дата-модулей в список автосоздаваемых можно отключить в опциях, в частности, для D2006:
Tools/Options/Environment Options/VCL Designer/Module creation options/Auto create forms & data modules
Но объявления глобальных переменных всё равно генерируются и их приходится удалять вручную.
Главная форма включается в список автосоздаваемых в любом случае, а один-два датамодуля можно включить и вручную.

Большинство форм в проекте используются в модальном режиме. Это все справочники, диалоги настройки, диалоги выбора чего-либо для печати и т.д. Рассмотрим минимально необходимую видимость для переменных таких форм.
Переменная для модальной формы нужна в только одном месте, где она создаётся, возможно, настраивается, отображается и уничтожается. За пределами того блока, где это происходит, такая переменная не нужна. Внутри формы доступ к своим данным происходит через Self. Кстати, грубейшая ошибка: внутри метода пытаться обратиться к своему объекту через... глобальную переменную... Смешно? Не очень... А таких ошибок у спрашивающих на КС - полно. И это не просто неоправданная, но безобидная несуразность. Это именно ошибка, и именно грубейшая и опасная. Посмотрите »вопрос КС №75155« и далее по ссылкам.
Возвращаясь к модальным формам... Переменная для модальной фомы нужна только внутри одной процедуры, таким образом, максимально (даже не минимально) необходимая видимость для такой переменной - локальная в процедуре:

procedure TForm1.Button1Click(Sender: TObject);
var
  Form2: TForm2;
begin
  Form2 := TForm2.Create(nil);
  Form2.Caption := 'Очень нужная форма';
  Form2.ShowModal;
  Form2.Free;
end;

Но можно вообще обойтись без переменной:

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TForm2.Create(nil) do
  begin
    Caption := 'Очень нужная форма';
    ShowModal;
    Free;
  end;
end;

По поводу использования оператора with есть различные мнения. Лично моё таково: в ряде случаев он сильно облегчает жизнь, надо только использовать его с умом и не злоупотреблять.
Однако и это ещё не предел совершенства. Лично я в таких случаях предпочитаю вместо begin-end в качестве скобок использовать блок try-finally. Особой необходимости в этом лично у меня нет, поскольку я стараюсь исключить возможность вылета необработанного исключения наружу, но благодаря добавлению всего одной строчки код приобретает дополнительную благообразность, кроме того, становится практически невозможно забыть вставить вызов Free.

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TForm2.Create(nil) do
  try
    Caption := 'Очень нужная форма';
    ShowModal;
  finally
    Free;
  end;
end;


Другим распространённым способом вызова модальных форм является использование отдельных процедур, где форма создаётся, вызывается и уничтожается. А в месте вызова вызывается только эта процедура одной строчкой:

unit Unit2;

interface

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

type
  TForm2 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure ShowForm2;

//var
//  Form2: TForm2;

implementation

{$R *.dfm}

procedure ShowForm2;
begin
  with TForm2.Create(nil) do
  try
    Caption := 'Очень нужная форма';
    ShowModal;
  finally
    Free;
  end;
end;

end.


procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowForm2;
end;

В большинстве случаев - это оптимальный вариант.
Лично я в таких случаях обычно использую не отдельную процедуру, а классовый метод. Пример такого использования можно посмотреть в сообщении от 20-05-2010 03:18.

Внимание, вопрос: и где при работе с модальными формами место глобальным переменным? Правильно, его там нет...
Но есть ещё немодальные формы. Если может существовать несколько равноправных экземпляров формы одного типа (например, текстовый редактор), то существование отдельной переменной только для одного из этих экземпляров является неоправданным.
Таким образом, мы приходим  к тому, что существование глобальной переменной для формы может быть оправдано только в каких-то редких частных случаях, например, если во время работы программы может существовать только один экземпляр немодальной формы определённого типа и при этом необходимо иметь возможность определять его существование в любой момент времени (при уничтожении - принудительно обнулять), либо к которой необходим доступ из других немодальных форм (в модальные при необходимости должна передаваться ссылка на эту форму). Во всех остальных случаях автососдаваемые объявления глобальных переменных для форм должны уничтожаться сразу после создания форм.

24-05-2010 15:25
Так как не могу сказать что я спец, поэтому буду признателен за более полное раскрытие темы или ссылку на тему глобальных переменных и в особенности на разъяснение нежелательности их применения. Ведь насколько я понимаю при закрытии основного приложения есть два пути:
1. Можно закрыть переменные вручную при помощи различных обработчиков.
2. Переменные сами должны закрываться автоматически при закрытии приложения. (по идее).


Начнём с того, что говорить о "закрытии переменных" - не совсем корректно. Работа идёт с объектом, который создаётся конструктором и существут где-то в памяти. Переменная классового типа - это всего лишь указатель на этот объект и она нужна только для того, чтобы знать где он находится и дать нам возможность к нему обратиться. На один и тот-же объект могут ссылаться сколько угодно переменных, но интересны не сами переменные как таковые, а именно объект. Так что при завершении программы речь должна идти не о "закрытии переменных", а об уничтожении объекта, в данном случае - формы.

Основные виды форм:
1. Модальная
2. Немодальные
  а) Обычная
  б) MDIChild

Модальная форма - самый простой вариант. Момент её закрытия точно известен - по выходу из ShowModal. Обычно модальные формы создают перед показом и уничтожают сразу или почти сразу после закрытия. И поэтому затруднений уничтожение модальных форм обычно не вызывает.
Немодальные формы открываются и отображаются неопределённое время, поэтому тут ситуация немного сложнее.

Варианты уничтожения форм:
1. Прямым вызовом Free.
2. Вызовом Relaese (прямым или косвенным). Форма самоуничтожается после выхода из обработчиков. Применяется в первую очередь для MDIChild путём установки Action := caFree в обработчике OnClose.
3. Уничтожение поручается владельцу. При вызове конструктора формы указывается владелец, т.е тот, кто будет уничтожать форму при своём уничтожении. Обычно это Application, т.е. форма создаётся так: TForm25.Create(Application). Тогда при закрытии приложения такая форма будет автоматически уничтожаться. Если предполагается уничтожать форму самостоятельно, владельца обычно не указывают: TForm25.Create(nil). Это характерно для работы с модальными формами. Владельцем можно назначить любую форму (и не только форму, а вообще любой компонент). Например, для какой-то формы могут открываться ещё несколько немодальных форм с дополнительной информацией. В этом случае логично назначать таким формам владельцем ту форму, для которой они открываются. Тогда при уничтожении (не закрытии) такой формы она будет уничтожать и все свои вспомогательные формы.

Если форма не уничтожена на момент закрытия приложения и ей не назначен владелец, то с точки зрения утечки памяти это не критично, т.к. после закрытия приложения вся память всё равно будет возвращена системе. Но тут есть два отрицательных момента:
1. Не будет выполнен деструктор формы, а там могут быть предусмотрены важные действия.
2. Если отслеживаются утечки памяти, то в лог попадёт и неуничтоженная форма и будет как минимум засорять лог, усложняя анализ остальной части. Формы, уничтожаемые Application как владельцем, в лог утечек не попадают.

Почему формы не должны быть автосоздаваемыми.
Проекты, содержащие 50 форм и более не являются чем-то необычным. Представьте, что все они висят в памяти, занимают место, отрабатывают свои обработчики, чутко прислушиваются к происходящему, иногда реагируют и весь этот зоопарк шевелится... Это напоминает банку с дождевыми червями... Брр... Вы будете смеяться, но закрытые формы реагируют на шорткаты. Чего стоят хотя бы вопросы вроде такого: "У меня в программе 5 автосоздаваемых форм. На одной из них на такое-то действие назначено такое-то сочетание клавиш. При старте я их не показываю, но если нажать клавишу такую-то, то у меня происходит то-то. Почему?". Блин, да потому, что не надо создавать форму, если не нужно, чтобы она работала... (Вопрос абсолютно реален). Кроме того, для работы конкретных форм требуются конкретные условия, при своём создании все они что-то делают, проверяют, что-то создают. Вот представьте: стоит задача вскипятить литр воды в электрочайнике и развести чашку растворимого кофе. Человек заходит на кухню и вместо того, чтобы налить в чайник воды и включить его, начинает включать свет, телевизор, приёмник, вентилятор, кондидионер, все кронфорки на плите, духовку, открывает кран с водой, заводит будильник, протирает пыль, ходит снимать показания электросчётчика, заполняет квитанцию и т.д. В жизни такое трудно представить. А почему такое можно делать в программе?

По поводу глобальных переменных.
При программировании решаются две основные задачи:
1. Решение целеывой задачи, для чего, собсвтвенно, и пишется программа.
2. Построение программы таким образом, чтобы:
  а) Минимизировать вероятность появления ошибок.
  б) Возникающие ошибки выявлялись максимально быстро.

Для достижения второй задачи, в частности, применяются следующие подходы:

1. Куски кода максимально изолируют от внешнего мира и минимизируют как их зависимость от чего-либо, так и их влияние на что-либо. Идеальный случай:
  а) Для отдельной продедуры или функции: все входные данные передаются через параметры, а выходные - либо как возвращаемое функцией значение, либо пишется в указанное через параметры место.
  б) Для метода: всё как для отдельной функции, плюс использование данных своего объекта.
И глобальным переменным в этом случае места нет. Только как редчайшее, обоснованное реальной необходимостью исключение. Зачем в процедуре или методе предусматривать обращеие к конкретной гловбальной переменной, если можно сделать универсальный вариант, передавая нужную переменную в качестве параметра?
В качестве примера могу привести »вопрос КС №62346« (сообщение от 26-05-2008 04:48)
2. Всем переменным, полям, методам, свойствам, подпрограммам обеспечивается минимально необходимая видимость.

Продолжение следует...

22-05-2010 02:30
Уважаемый Бел Амор! Прежде всего хочу выразить свою благодарность за терпеливое и обстоятельное разъяснение некоторых моментов. Благодаря Вашим советам удалось решить задачу. В частности:
1. Модальную форму создал не в проекте, а убрал ее создание в вызывающую форму, перед тем как вызвать .ShowModal.
2. Убрал из модальной формы принудительное объявление ModalResult.
3. Убрал из модальной формы Close.
4. В вызывающую MSIChild формы ввел конструкцию Try...Finally.
Сейчас пытаюсь проанализировать все изменения и понять почему мой код не работал, а с введенными поправками проблем, пока по крайней мере, не возникает. Скромными троеточиями я отбрасываю незнаковый код, который 100% проверен и не имеет отношения к проблеме, спасибо трассировке )) Хотел напоследок задать уточняющий вопрос, если можно конечно.

По возможности избегайте глобальных переменных.

Так как не могу сказать что я спец, поэтому буду признателен за более полное раскрытие темы или ссылку на тему глобальных переменных и в особенности на разъяснение нежелательности их применения. Ведь насколько я понимаю при закрытии основного приложения есть два пути:
1. Можно закрыть переменные вручную при помощи различных обработчиков.
2. Переменные сами должны закрываться автоматически при закрытии приложения. (по идее).
Заведомо СПАСИБО и низкий поклон Вашему терпению и Опыту. Если бы на сайте была возможность плюсовать "карму" - обязательно влепил бы плюсом))

21-05-2010 04:43
>>> Создал еще одну форму, обозвал ее ColumnsVisible, она автосоздаваемая

А зачем? Привыкайте к тому, что автосоздаваемой должна быть только главная форма и дата-модули. По возможности избегайте глобальных переменных. Что может быть проще?

  with TColumnsVisible.Create(nil) do
  try
    ...
    ShowModal;
  finally
    Free;
  end;


procedure TColumnsVisible.RzButton1Click(Sender: TObject);
begin
modalresult:=mrYes;
Close;
end;


1. Если форма показывается модально, то Close здесь не нужен. Присвоение ModalResult<>mrNone приводит к закрытию модального окна после выхода из обработчика.
2. В обсуждении по ранее приведенной ссылке я уже писал, что обычно не требуется писать обработчик, чтобы в нём явно присвоить ModalResult. Для этого достаточно присвоить в инспекторе ModalResult кнопки, и при начатии на кнопку свойству ModalResult формы будет присваиваться это значение. Так что весь приведённый выше обработчик излишен в таком виде.

>>> Не пойму что не так, насколько я понимаю форма закрывается по Close и никак не должна  вызывать ошибку при закрытии всего приложения.

Есть такое понятие: "наведённая ошибка". Вы можете что-то неправильно делать в другом месте, но это проходит без последствий в силу удачного стечения обстоятельств. Работа же с ещё одной формой эти обстоятельства изменяет и возникает ошибка...

>>> Вот ведь задом чувствую что что-то явное я не вижу, причем оно лежит где-то наверху, прямо перед глазами, а заметить не могу, или замечаю но не понимаю ...

В приведённом вами коде нет ничего, что вызывало бы подозрения. Разве что, Close, да то скромное троеточие перед ShowModal, где, видимо, происходит заполнение CheckListBox.
Проверьте, действительно ли форма автосоздаваемая. Это для выяснения причин, а для дальнейшей работы - сделайте её неавтосодаваемой и вообще удалите объявление глобальной переменной для неё.
Кстати, сделайте Find declaration для ColumnsVisible, ткнув в неё правой кнопкой и выбрав в меню. Деёствительно ли это та самая переменная, а не какая-то случайно где-то оставшаяся другая?
Включите Range checking в опциях проекта, перекомпилируйте, запустите и посмотрите - будет ли выход за границы индексов где-либо.
Если это весь код - то ошибка либо в несоздании формы, либо в обращении не к той переменной, либо не имеет прямого отношения к этой форме.
Если не весь - приведите весь код.

21-05-2010 03:39
По умолчанию в инспекторе объектов для формы стоит Visible=False
Когда вы перещёлкиваете FormStyle на fsMDIChild, Visible устанавливается в True. Когда же вы возвращаете FormStyle в fsNormal, то Visible остаётся в True. Это означает, что сразу после создания форма будет отображаться, что эквивалентно показу её в немодальном режиме через вызов Show. Попытка вызвать ShowModal для формы, которая уже отображается в немодальном режиме, вызовет ошибку. Верните в инспекторе объектов Visible в False.


На эти грабли я уже наступил, спасибо )) было не больно, разобрался... С остальным же полный затык, я чувствую что шестеренки в мозгах упорно отказываются поворачиваться. Короче суть. Создал еще одну форму, обозвал ее ColumnsVisible, она автосоздаваемая, вызываю ее из MDIChild-формы QWorkerForm


procedure TQWorkerForm.FieldVisibleMenuClick(Sender: TObject);
begin
...
ColumnsVisible.ShowModal;
end;



Внутри ColumnsVisible


procedure TColumnsVisible.FormClose(Sender: TObject; var Action: TCloseAction);
begin
MessageDlg('Закрываемся!', mtInformation, [mbOK], 0);
end;

procedure TColumnsVisible.RzButton1Click(Sender: TObject);
begin
modalresult:=mrYes;
Close;
end;



Не пойму что не так, насколько я понимаю форма закрывается по Close и никак не должна  вызывать ошибку при закрытии всего приложения. Вот ведь задом чувствую что что-то явное я не вижу, причем оно лежит где-то наверху, прямо перед глазами, а заметить не могу, или замечаю но не понимаю ...

21-05-2010 02:24
>>> теперь другие грабли, при закрытии приложения Access Violation at adress ...

Это код надо смотреть... Причин может быть много разных, например, связанных с порчей чужой памяти, попыткой уничтожить уже уничтоженный объект, попыткой доступа к объекту через неинициализированную переменную ( в т.ч. попытка доступа не через ту переменную) и т.д.

>>> причем только в том случае если вызывалась модальная форма.

Без кода трудно что-либо сказать.

>>> При закрытии основного приложения видимо не обрабатывается (не уничтожается) модальная форма.

Это не должно приводить к таким результатам. В большинстве случаев - только утечка тамяти.

>>> Как правильно это сделать?

Уничтожать самостоятельно через вызов Free.

>>> что-то не получается создать обычную форму из MDIChild

Кстати... Если ваша форма первоначально была MDIChild, то вы быстрее всего наступите на следующие грабли:
По умолчанию в инспекторе объектов для формы стоит Visible=False
Когда вы перещёлкиваете FormStyle на fsMDIChild, Visible устанавливается в True. Когда же вы возвращаете FormStyle в fsNormal, то Visible остаётся в True. Это означает, что сразу после создания форма будет отображаться, что эквивалентно показу её в немодальном режиме через вызов Show. Попытка вызвать ShowModal для формы, которая уже отображается в немодальном режиме, вызовет ошибку. Верните в инспекторе объектов Visible в False.
Если это не поможет, приводите код.

20-05-2010 22:51
с созданием вроде разобрался, теперь другие грабли, при закрытии приложения Access Violation at adress ... причем только в том случае если вызывалась модальная форма. При закрытии основного приложения видимо не обрабатывается (не уничтожается) модальная форма. Как правильно это сделать?

20-05-2010 22:21
что-то не получается создать обычную форму из MDIChild ... вываливает при попытке Create ошибку доступа к памяти по адресу тра-та-та ...

20-05-2010 03:18
В качестве копилки идей могу предложить кусок своей рабочей формы для редактирования видимости колонок. Она рассчитана на работу с DBGridEh, но принципиальных отличий от DBGrid нет, достаточно убрать "Eh". Как мог повырезал свою специфику и упоминания своих модулей, возможно, где-то что-то не совсем корректно (на самом деле и наследование - не от TForm). Добавил несколько комментариев.

unit ColumnsVis_Form;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ExtCtrls, CheckLst, DBGridEh, GridsEh;

type
  TColumnsVisibleForm = class(TForm)
    CheckListBox1: TCheckListBox;
    bbtnOk: TBitBtn;                // Назначить ModalResult = mrOk
    bbtnCancel: TBitBtn;            // Назначить ModalResult = mrCancel
    FormClose(Sender: TObject; var Action: TCloseAction);
  private
    procedure ReadColumnsEh(AGrid: TDBGridEh);
    procedure WriteColumnsEh(AGrid: TDBGridEh);
    function CheckValid: Boolean;
  public
    class function Execute_cm(AGrid: TCustomGridEh): Boolean;  // Классовый метод, можно вынести
  end;                                                        // из класса и сделать обычной функцией

implementation

{$R *.dfm}

{ TColumnsVisibleForm }

class function TColumnsVisibleForm.Execute_cm(AGrid: TCustomGridEh): Boolean;
begin
  with Create(nil) do  // В классовом методе Self - это класс, т.е. здесь
  try                  // Create(nil) эквиваленнтно TColumnsVisibleForm.Create(nil)
    ReadColumnsEh(AGrid as TDBGridEh);
    Left := Mouse.CursorPos.X + 45;
    Top := Mouse.CursorPos.Y + 35;
    Result := (ShowModal = mrOk);
    if Result then
      WriteColumnsEh(AGrid as TDBGridEh);
  finally
    Free;
  end;
end;

procedure TColumnsVisibleForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if ModalResult = mrOk then
    if not CheckValid then
      Action := caNone;
end;

function TColumnsVisibleForm.CheckValid: Boolean;
var
  i: Integer;
begin
  Result := True;
  for i:=0 to CheckListBox1.Count-1 do
    if CheckListBox1.Checked[i] then
      Exit;
  MsgBoxWarning('Должна быть видимой хотя бы одна колонка');
  Result := False;
end;

procedure TColumnsVisibleForm.ReadColumnsEh(AGrid: TDBGridEh);
var
  i: Integer;
begin
  CheckListBox1.Items.Clear;
  for i:=0 to AGrid.Columns.Count-1 do
  begin
    CheckListBox1.Items.Add(AGrid.Columns.Items[i].Title.Caption);
    CheckListBox1.Checked[i] := AGrid.Columns.Items[i].Visible;
    // Колонки с Tag <> 0 запрещено скрывать
    CheckListBox1.ItemEnabled[i] := (AGrid.Columns.Items[i].Tag = 0);
    if not CheckListBox1.ItemEnabled[i] then
      CheckListBox1.Checked[i] := True;       
  end;
end;

procedure TColumnsVisibleForm.WriteColumnsEh(AGrid: TDBGridEh);
var
  i: Integer;
begin
  for i:=0 to CheckListBox1.Count-1 do
    AGrid.Columns.Items[i].Visible := CheckListBox1.Checked[i];
end;

end.


В любой форме - подключить в uses и вызывать одной строчкой:

  TColumnsVisibleForm.Execute_cm(DBGridEh1);


20-05-2010 01:36
Если это настройка видимости колонок, то вы, прошу прощения, занимаетесь ерундой... Сделайте её  не MDIChild, а обычной, и вызывайте в модальном режиме через ShowModal без всяких выкрутасов...
А еще говорят что все экстрасенсы в отпуске )) фдисятку )). В разрезе моего вопроса это 100% решение, сейчас займусь переделкой, несмотря на то, что смутно пока представляю себе дальнейшее развитие. Поясню суть. Форма ColVisible одна для всех остальных форм, и отображает в CheckList поля, актуальные для вызвавшей ее формы. Я использовал две переменных типа TStringList, которые считывали значение всех полей формы и их состояние Visible: True/False, которые при открытии ColVisible передавались ей для дальнейших операций. Так как операции типовые для всех форм, то я постарался описать их максимально универсально. По логике вещей с модальной формой не должно быть проблем, хотя мой лоб чувствует что где-то возможны грабли. Ладно, сейчас перепишу код, посмотрю на его работу, как дойдет до реализации третьей формы и вызова из нее ColVisible - отпишу с чем столкнулся(если что-то пойдет не так), как решил или что решения не смог найти. Снимаю шляпу перед Бел Амор!

20-05-2010 00:50
Обратил внимание на название вашей формы: TColVisible
Если это настройка видимости колонок, то вы, прошу прощения, занимаетесь ерундой... Сделайте её  не MDIChild, а обычной, и вызывайте в модальном режиме через ShowModal без всяких выкрутасов...

Ссылка в помощь: »вопрос КС №61703«

19-05-2010 23:46
Скажу Вам только следующее: обо всех изменениях с MDIChild-формами знает главная форма (MDIForm). Вот в ней и перехватывайте  момент гибели MDIChild-формы.

Не вариант ибо необходимо чтобы именно дочерняя форма QWorkerForm знала о существовании ColVisible, причем знала что именно она создала ее. Пока я вышел из положения введением глобальной переменной в основной форме, которая меняет свое значение в зависимости от того кто создал форму и существует-ли она, но это очень неправильно, чувствую это всем мозгом.

Возможно, вас заинтересует »вопрос КС №75600«
Да, интересная тема, правда опять на уровне интуиции чувствую что не совсем то, в любом случае буду сейчас разбираться. С помощью API никак нельзя решить этот вопрос? Т.е. кто создал дочернее окно и существует-ли оно? Я находил где-то искомые функции, но не смог разобраться с их применением в моем случае, мой маленький мозг млекопитающего не способен пока разобраться без помощи Гуру:()

18-05-2010 10:26
Возможно, вас заинтересует »вопрос КС №75600«

18-05-2010 08:35
Скажу Вам только следующее: обо всех изменениях с MDIChild-формами знает главная форма (MDIForm). Вот в ней и перехватывайте момент гибели MDIChild-формы.

18-05-2010 07:46
Все созданные формы хранятся в Screen.Forms. Понятие открытое очень расплывчато, если имеется ввиду маячит в данный момент перед лицом, то это Activate. Т.е у то же Screen.Forms[i].Activate проверяете этот параметр. Если же просто создана то достаточно и Screen.Forms.

Ну а если вникнуть в вашу задачу, то по-моему можно просто на OnClose ColVisible повесить процедуру которая выполнит метод или сигнализирует QWorkerForm что она закрылась.

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
"Мы с тобой одной крови — ты и я!". Чьи это заветные слова?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования