powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Закрытие MDIChild-формы
43 сообщений из 43, показаны все 2 страниц
Закрытие MDIChild-формы
    #39780290
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пишем MDI приложение.
В нем есть базовая форма для всех MDIChild-фор, пусть TMdiBaseForm, от которой наследуются все остальные дочерние формы;

При закрытии дочерних формы не сворачиваем их, а именно закрываем:

Код: pascal
1.
2.
3.
4.
procedure TMdiBaseForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;



Все формы создаются типовым способом:

Код: pascal
1.
2.
3.
  if Assigned(frmMdiChildren1) 
    then frmMdiChildren1.BringToFront
    else frmMdiChildren1 := TfrmMdiChildren1.CreateMDI(Application);



Все работает как надо, до момента закрытия формы.
После этого переменная frmMdiChildren1 остается ненулевая и форма повторно не создается.
Так вот вопрос: как занулить переменную формы после ее закрытия?
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780305
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
client6aac,

Код: pascal
1.
frmMdiChildren1:= nil;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780306
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
function TMainForm.CheckMDIChild(Sender: TForm): Boolean;
var
  i: Integer;
begin
  Result := False;
  for i := 0 to (MDIChildCount - 1) do
    if MDIChildren[i] = Sender then
    begin
      Result := True;
      exit;
    end
    else
      Result := False;
end;



Использование
Код: sql
1.
2.
3.
4.
  if CheckMDIChild(frmMdiChildren1) then
    frmMdiChildren1.Show
  else
    frmMdiChildren1 := TfrmMdiChildren.Create(Self);  
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780310
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacПосле этого переменная frmMdiChildren1 остается ненулевая и форма повторно не создается.

А где место в котором вы обнуляете переменную ? Зачем вообще существует переменная frmMdiChildren1 ?
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780322
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DimaBrА где место в котором вы обнуляете переменную?
Вот вопрос то и был об этом... может не совсем корректно выразил мысль... Если закрытие окна происходит в базовой форме, которая не знает ничего о переменных, то где и как правильно занулять переменную формы?

DimaBrЗачем вообще существует переменная frmMdiChildren1 ?
Для того, что бы понять создавалась форма ранее или нет. Если будет создано стопитцот разных окошек и искомое потеряется где-то в самом низу, то клацнув в главном меню на пунктик вызова этого окна мы или выведем его наверх (если оно было ранее создано), либо создадим.

В общем-то, нужное решение было дано в третьем посте, за что goldmi45 отдельное спасибо. Наверное тему можно закрывать
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780326
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
client6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;



Открываем

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
procedure TForm1.btnClick(Sender: TObject);
begin
  if Assigned(Form2) then
    Form2.Show
  else
  begin
    Application.CreateForm(TForm2, Form2);
    Form2.Show;
  end;
end;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780327
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Но это - корявый метод...

Лучше закрывать\открывать "Главной формой"
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780328
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacТак вот вопрос: как занулить переменную формы после ее закрытия?

Удалить эту переменную вообще.
Она не нужна.

Реестр существующих окон держать в другом виде, например

Код: pascal
1.
2.
 Type MyMDIClass = class of TMdiBaseForm;
Var   MyMDIForms: TDictionary<MyMDIClass, TMdiBaseForm>



Ну и не забывать оттуда удалять закрываемые формы.

P.S. именно такой реестр на самом деле редко практичен: он не позволяет открывать НЕСКОЛЬКО окон одного класса. Впрочем, как и переменная "frmMdiChildren1" не может содержать несколько указателей на несколько окон сразу.

А в реальности часто по другому. Например в браузере открыто несколько разных веб-страничек, в Excel открыто несколько разных файлов: класс один и тот же, а окон много: уникальный идентификатор окна состоит не только из класса, но и ещё каких-то данных.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780335
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
zinpubclient6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;


[/src]

Не годится... Action := caFree; делаем в базовой форме, которая ничего не знает про Form2

Arioch
В текущей логике приложения как раз и нужно открытие окошек в единственном экземпляре.
Но за наставление на путь истинный - спасибо!
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780338
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch,

Зачем создавать то, что уже есть?

MDIChildren и MDIChildCount
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780341
Фотография krapotkin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
список MDI окон у нас по факту есть
но держать ссылки на формы в своем ObjectList(OwnObjects=FALSE!!!) никто не мешает
при закрытии нужно пробегать по нему и удалять из него ссылку на удаляемую форму

вопрос именно - для чего нам этот список
более практичным выглядит вариант когда это список моих объектов, которые содержат всякие данные и В ТОМ ЧИСЛЕ ссылку на форму...
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780342
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arioch
Вот только что созрела мысль, что в Вашем варианте с Дикшионари я тоже не очень понимаю как удалять Айтем из словаря при закрытии формы при условии, что все это должно быть реализовано в базовой форме
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780343
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А две одинаковые формы (одного типа) не могут быть созданы ?
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780347
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DimaBrА две одинаковые формы (одного типа) не могут быть созданы ?
нет, при попытке создания второго экземпляра формы, нужно вывести наверх уже имеющийся
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780348
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
goldmi45client6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
function TMainForm.CheckMDIChild(Sender: TForm): Boolean;
var
  i: Integer;
begin
  Result := False;
  for i := 0 to (MDIChildCount - 1) do
    if MDIChildren[i] = Sender then
    begin
      Result := True;
      exit;
    end
    else
      Result := False;
end;



Или проще

Код: pascal
1.
2.
3.
4.
function TMainForm.CheckMDIChild(Sender: TForm): Boolean;
begin
  Result := MyFormsRegistry.Contains(Sender as TMdiBaseForm);
end;



http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Generics_Collections_TList_Contains.html

Но вообще привязывать реестр (реестры) открытых окон к TMainForm - стрёмная идея.
Потом если понадобиться распутать - то хрен распутаешь, спагетти зависимостей нарастёт.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
Type TMdiBaseForm = class
...
private
    FRegistry: TList<TMdiBaseForm>; 
   // может быть один синглтон на всю программу, или несколько (разные открытые проекты-странички-файлы)
....
public
  procedure BeforeDestruction; Override;
  property MDIRegistry: TList<TMdiBaseForm> write RegisterInNewRegistry;
....

procedure TMdiBaseForm.BeforeDestruction; 
begin
   MDIRegistry := nil;
   inherited;
end;

procedure TMdiBaseForm.RegisterInNewRegistry(const NewReg: TList<TMdiBaseForm>); 
begin
   if NewReg = FRegistry then exit;
   if nil <> FRegistry then FRegistry.Remove(Self);
   if nil <> NewReg then NewReg.Add(Self);   
   FRegistry := NewReg;
end;

.....

  LMyNewForm := TMyMDIxxxxForm.Create( ...... );
  LMyNewForm.XXX := yyy;
  LMyNewForm.AAA := bbb;
  LMyNewForm.MDIRegistry := MyProjectWindows;
  LMyNewForm.Show;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780349
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arioch,
я не пойму как это все делать из БАЗОВОЙ формы:)
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780350
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
goldmi45Arioch,

Зачем создавать то, что уже есть?

MDIChildren и MDIChildCount

1) лаконичнее. Одна строка - вызов стандартной функции TList<t>.Contains гораздо меньше, чем расписанный вами if с циклами. Следовательно, меньше шансов тупой ошибки.

2) гибче. Например, в дальнейшем нужно будет иметь несколько MDI-Parent окон. Или с MDI будет переход на что-то другое (табы, докающиеся плавающие окна, ...)
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780356
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
client6aaczinpubclient6aac,

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;


[/src]

Не годится... Action := caFree; делаем в базовой форме, которая ничего не знает про Form2


Ну
Код: pascal
1.
Sender:= nil;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780357
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacя не пойму как это все делать из БАЗОВОЙ формы:)

1) пробросить в базовую формы ссылку на содержащий её реестр
2) иметь один единственный реестр в приложении - глобальную переменную
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780358
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacНе годится... Action := caFree; делаем в базовой форме, которая ничего не знает про Form2

так From2 тут явно один из потомков базовой формы, то же самое, что frmMdiChildren1
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780359
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Но Arioch прав, гораздо лучше реестр окон, в который можно добавить собственные свойства\методы... итд
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780361
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zinpub
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;[/src[

Ну [SRC pascal]Sender:= nil;



Зачем? переменная Sender перестаёт существовать через мгновение, когда ты выходишь из процедуры!
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780363
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
procedure TMdiBaseForm.RegisterInNewRegistry(const NewReg: TList<TMdiBaseForm>); 
begin
   if NewReg = FRegistry then exit;
//   if nil <> FRegistry then FRegistry.Remove(Self);
   if nil <> FRegistry then begin
     FRegistry.Remove(Self);
     FRegistry := nil;
   end;
   if nil <> NewReg then NewReg.Add(Self);   
   FRegistry := NewReg;
end;



Вот так лучше.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780364
zinpub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ariochzinpub
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;

  Form2 := nil;
end;[/src[

Ну [SRC pascal]Sender:= nil;



Зачем? переменная Sender перестаёт существовать через мгновение, когда ты выходишь из процедуры!

Тьфу... Да! затупил...
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780366
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krapotkinболее практичным выглядит вариант когда это список моих объектов, которые содержат всякие данные и В ТОМ ЧИСЛЕ ссылку на форму.

после чего этот список начинает расти, а либо поиск, либо удаление объектов в массиве - операции дорогие

свалить ВСЕ объекты в одну кучу - спорное решение.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780369
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну так создавайте изначально так, чтобы такой формы небыло
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function CreateForm(FormClass: TMdiBaseFormClass): TMdiBaseForm;
var i: Integer;
begin
  for i := 0 to MDIChildCount - 1 do
    if MDIChildren[i].ClassType = FormClass then begin
      Result := MDIChildren[i] as TMdiBaseForm;
      Exit;
    end
  Result :=  FormClass.Create(Application);
end;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780370
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch2) иметь один единственный реестр в приложении - глобальную переменную

А ещё лучше не глобальную, а локальную для класса

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
Type TMdiBaseForm = class
...
private // или strict private или protected
   class var FRegistry: TList<TMdiBaseForm>; 
   class constructor CreateReg;
   class destructor FreeReg;

...

class constructor TMdiBaseFormCreateReg;
begin
   FRegistry := TList<TMdiBaseForm>.Create;
   FRegistry.Capacity := 32; 
   inherited;
end;

class destructor TMdiBaseForm.FreeReg;
begin
   FRegistry.Free; 
   inherited;
end;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780371
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ariochgoldmi45Arioch,

Зачем создавать то, что уже есть?

MDIChildren и MDIChildCount

1) лаконичнее. Одна строка - вызов стандартной функции TList<t>.Contains гораздо меньше, чем расписанный вами if с циклами. Следовательно, меньше шансов тупой ошибки.

Да, Contains лаконичнее. Но ошибка может вкрасться на другом этапе (к примеру, забыв добавить переменную в список). И кода будет ни сколько не меньше: необходимо создавать список, его удалять, добавлять в него переменную. Возможно, необходимы отдельные методы, как у вас.

Arioch2) гибче. Например, в дальнейшем нужно будет иметь несколько MDI-Parent окон. Или с MDI будет переход на что-то другое (табы, докающиеся плавающие окна, ...)
Согласен. Код имеет ограничения и вы предлагаете более гибкий подход.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780375
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimaBrНу так создавайте изначально так, чтобы такой формы небыло
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function CreateForm(FormClass: TMdiBaseFormClass): TMdiBaseForm;
var i: Integer; 
begin
  for i := 0 to MDIChildCount - 1 do 
    if MDIChildren[i].ClassType = FormClass then begin
      Result := MDIChildren[i] as TMdiBaseForm;
      Exit;
    end
  Result :=  FormClass.Create(Application);
end;



Дважды вызывать функцию MDIChildren[i] - долго и потенциально моежт привести к опискам (например - несколько циклом, или индексы более разнообразные и сложные)

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
{.$Define hackyhack} // :-D

function CreateForm1(const FormClass: TMdiBaseFormClass): TMdiBaseForm;
var i: Integer; F: TForm {$IfDef hackyhack} absolute Result {$EndIf};
begin
  for i := 0 to MDIChildCount - 1 do begin
    F := MDIChildren[i];
    if F.ClassType = FormClass then 
{$IfDef hackyhack}
      Exit;
{$Else}
      Exit( F as TMdiBaseForm );
  end;
  Result :=  FormClass.Create(Application);
end;

function CreateForm2(const FormClass: TMdiBaseFormClass): TMdiBaseForm;
begin
  if not MyDictionary.TryGetValue( FormClass, Result ) then
  begin
    Result :=  FormClass.Create(Application);
    MyDictionary.Add( FormClass, Reuslt );
  end;
end;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780383
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aacНо за наставление на путь истинный - спасибо!

в общем, несколько вариантов тебе накидали, плюсы-минусы упомянули, планировтаь будущее программы и оценивать их - дело уже твоё.

главное, не забывай, что "90% кода в интернете - говно" - https://www.gunsmoker.ru/2010/05/90.html
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780388
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ToAll
Я приятно удивлен, что вроде такой пустяковый вопросик вызвал такую достаточно бурную и конструктивную реакцию комьюнити.
Всем спасибо!
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780434
Фотография LocksmithPC
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А почему нельзя открыть (создать) дочернюю форму два раза?

У меня вообще все дочерние формы создаются TfrmMDIChild.Create(Self); Надо сотню открыть? На здоровье!
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780492
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Якобы, задача такая, что не надо.
Скрестим пальцы, чтобы он не ошибся.


Есть тезис "не изобретать велосипеды"

goldmi45Зачем создавать то, что уже есть?

MDIChildren и MDIChildCo

И есть тезис "писать программу так, как будто через год её будет дописывать маньяк-убийца, которому расскажут, где живёт твоя семья"

zinpubНо Arioch прав, гораздо лучше реестр окон, в который можно добавить собственные свойства\методы

При этом тезис
client6aacВ текущей логике приложения как раз и нужно открытие окошек в единственном экземпляре.

- это ставка в азартной игре "угадай, как дела обстоят не в реальности, а на самом деле".
Обычно мы угадываем, но иногда ошибаемся.
Очевидно, что заранее мы не знаем, где ошибёмся, иначе не ошиблись бы

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

Пример - да хотя бы вечный срач про контроль типов (строгий / не строгий / никакого и статический / динамический), например https://www.sql.ru/forum/1309685/incompatible-types.

Собираем мой бред в кучку.

goldmi45Зачем создавать то, что уже есть?

MDIChildren и MDIChildCo

"Бизюзловно" - прозюзюкала Зази.

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

Но! если "другая логика" всё же случится, то "в класс-реестр можно добавить собственные свойства\методы".
А это значит, что в само объявление этих методов (списки/типы параметров, названия) можно зашить "требования к реальному миру". И при нарушении этих требований - компиляция сломается. И это - хороший код

DimaBr
Код: pascal
1.
function CreateForm(FormClass: TMdiBaseFormClass): TMdiBaseForm;


Тут мы предполагаем, что "TMdiBaseFormClass" - полный и уникальный идентификатор формы.
ЕСЛИ потом у нас будут несколько форм одного класса, то будет что-то вроде

Код: pascal
1.
2.
3.
4.
5.
6.
7.
type RMDIFormID = record
  FormClass: TMdiBaseFormClass;
  ProjectPath: TFileName;
  DocumentNo: cardinal;
end;

function CreateForm(const FormClass: RMDIFormID): TMdiBaseForm;



После этого всё позабытые нами вызовы "CreateFrom( MySuperMDIClass )" просто не соберутся. Даже если мы захотим их пропустить - Delphi не даст.

Но это - объявление метода.
А вот сам цикл - все равно будет собираться.

DimaBr
Код: pascal
1.
2.
3.
4.
5.
6.
  for i := 0 to MDIChildCount - 1 do
    if MDIChildren[i].ClassType = FormClass then begin
      Result := MDIChildren[i] as TMdiBaseForm;
      Exit;
    end
  Result :=  FormClass.Create(Application);



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

Таким образом, использование этого "из коробки" функционала - это очень сильная ставка на YAGNI.

Ну и "охотничья байка".
Есть стандартный срач в БД - суррогатный или натуральный должен быть ключ таблиц.
Должен ли уникальный идентификатор строки в таблице иметь реальный смысл или быть полностью очищен от любых пересечений с реальностью.

Несколько лет назад мне надо было быстро сделать самописку для внутренних нужд компании.
Среди прочего там была таблицы контрагентов - юр/лиц.
В качестве Primary Key я там поставил ИНН. Сразу многие запросы стали проще, а при просмотре вторичных таблиц вместу асбтрактного случайного номера - был реальный и осмысленный ИНН. Удобно и быстро.

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

Прошло полгода. У самописки появились пользователи, у пользователей появились привычки, в БД появились данные.

И вдруг ко мне приходят и говорят, что программа остановила работу. Надо ввести контр-агента ,а не получается, ругается на повтор ИНН.

- значит, вы его уже раньше ввели в БД, берите готовый.
- нет, тот "Василёк", а нужен "Ромашка".
- значит "Василёк" переименовался в ромашку. Переименуйте в БД и используйте.
- нет, это разные юр-лица и нам нужны ОБА СРАЗУ
- если это разные юр-лица, то у них и ИНН разные, ищите опечатку.
- нет опечаток. Юр-лица разные, а ИНН общий
- ЧТО ????

...оказалось, что хотя вообще-то ИНН - "индивидуальный номер", но конкретно у филиалов банокв в разных городах ИНН был общий, а различались только КПП.

Но ИНН уже был PK, на него уже были построены многие Foreign Key, но это были завязаны запросы и куски кода. И всё это уже было полгода в реальной работе.

....а мне надо бросив все срочно вспомнить как та программа писалась, сделать ИНН неуникальным - в программе и БД, и при этом не потерять данные, ни в чём не изменить поведение программы, и чтобы никто из пользователей вообще не заметил обновления.

...но вообще конечно же, YAGNI и "В текущей логике приложения как раз и нужно"
Делайте ваши ставки, господа!
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780547
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AriochДелайте ваши ставки, господа!
а ты не мог бы сказать то же самое, но покороче?
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780552
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док,

- Долго ли умеючи?
- Умеючи-то долго!
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780554
client6aac
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
экак Вас поперло... пора уже выдыхать:D
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39780821
AJi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AJi
Гость
У меня обычно используется вот такой вариант:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
class function TMdiBaseFormClass.ExistForm: TMdiBaseFormClass;
var
  n: Integer;
begin
  Result := nil;
  for n := 0 to Screen.FormCount - 1 do
    if Screen.Forms[n].ClassName = Self.ClassName then begin
      Result := Screen.Forms[n] as TMdiBaseFormClass;
      Break;
    end;
end;



Туда же можно засунуть и создание формы, при желании.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39781070
maratvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
client6aac,

на дороге MDI вы еще не дошли до вопроса "Как сделать, чтобы при максимизации одного окна, другие оставались в нормальном состоянии?" и иже с ними. Может вам не надо MDI, а то придется велосипедить долго и упорно. :)
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39782394
Фотография Old Nick
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А зачем вообще переменная?

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TMainForm.OnClickButton1(Sender: TObject);
var frm: TMdiBaseForm;
begin
  frm := TMdiPriceSelectForm.Create(Application);
  frm.Show;
end;



После выхода из метода переменная сама обнулится.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39782761
fraks
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Old NickА зачем вообще переменная?

Код: pascal
1.
2.
3.
4.
5.
6.
procedure TMainForm.OnClickButton1(Sender: TObject);
var frm: TMdiBaseForm;
begin
  frm := TMdiPriceSelectForm.Create(Application);
  frm.Show;
end;



После выхода из метода переменная сама обнулится.

А зачем вообще переменная? Если она не нужна - так и не нужно ее делать.
Код: pascal
1.
2.
3.
4.
5.
6.
procedure TMainForm.OnClickButton1(Sender: TObject);
begin
  with TMdiPriceSelectForm.Create(Application) do begin
    Show;
  end;
end;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39782769
Фотография LocksmithPC
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fraks, зачем вообще Show?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
  with TOpenDialog.Create(Self) do
    try
      if Execute then
        TMdiPriceSelectForm.Create(Self, FileName);

    finally
      Free;

    end;
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39782787
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТСу необходимо создавать в единственном экземпляре дочерние окна. Последние три писателя - нечитатели.
...
Рейтинг: 0 / 0
Закрытие MDIChild-формы
    #39782793
Фотография LocksmithPC
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
goldmi45, ого, да ты гения!
...
Рейтинг: 0 / 0
43 сообщений из 43, показаны все 2 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Закрытие MDIChild-формы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]