Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.07.16;
Скачать: [xml.tar.bz2];

Вниз

MDI   Найти похожие ветки 

 
tio   (2006-06-03 15:29) [0]

Уважаемые, Мастера!
Я долго занимался проблемой MDI приложений, хочу Вам дать на общее
использование код, который пригодится всем, аналогов я не видел, по
крайней мере, на многих сайтах.
Этот код закрывает MDI окна - корректно и правильно.

//В главном MDI окне написать в public
public
procedure WMGetSysCommand(var message : TMessage); message WM_SYSCOMMAND;
end;

procedure TMain_f.WMGetSysCommand(var message : TMessage) ;
var
x:integer;
begin
  if (message.wParam = SC_CLOSE) then
     begin
        for x:=Application.MainForm.MDIChildCount-1 downto 0 do
        begin
           Application.MainForm.MDIChildren[x].Close;
           Application.ProcessMessages;
           Next;
        end;
     end;
   inherited;
end;

написать в MDIChild окне:

//Modify : boolean; //флаг изменения

procedure TChild_f.FormCloseQuery(Sender: TObject;  var CanClose: Boolean);
begin
  if Modify = false then
     begin
        case Application.MessageBox(PChar("Документ """ + Caption + """ был изменен! Сохранить изменения ?"),"Закрытие документа",MB_YESNOCANCEL + MB_DEFBUTTON3 + MB_ICONQUESTION) of
           ID_Yes:
              begin
try
                      CanClose:=true;
except
     MessageBox(0,"Ошибка сохранения документа","Сообщение",mb_ok+mb_iconStop);
                 end;
              end;
           ID_No:
              begin
                 CanClose:=true;
              end;
           ID_Cancel:
              begin
                 CanClose:=false;
              end;
        end; //закрытие case
     end; //закрытие begin
end; //закрытие процедуры

procedure TChild_f.FormClose(Sender: TObject;  var Action: TCloseAction);
begin
  Action:=cafree;
  Release;
end;

C уважением  Залозных Игорь.


 
Джо ©   (2006-06-03 15:31) [1]

Игорь, спасибо, конечно. Но с чего вы взяли, что "корректное и правильное" закрытие MDI-окон является "проблемой"? :)


 
tio   (2006-06-03 15:35) [2]

Исчезновение окон детей - вот проблема, когда спрашиваешь о их закрытии в главном окне, оне сразу не закрываются и видны, даже когда нажимаешь "Да" (диалоге о закрыии (CanClose:=true)).
В Microsoft Access такая же проблема, не учтенная разработчиками.


 
Джо ©   (2006-06-03 15:38) [3]

> [2] tio   (03.06.06 15:35)
> Исчезновение окон детей - вот проблема, когда спрашиваешь
> о их закрытии в главном окне,

А зачем об этом "спрашивать" в главном окне?


 
Юрий Зотов ©   (2006-06-03 15:56) [4]

> tio   (03.06.06 15:29)  

> Я долго занимался проблемой MDI приложений
Это делает Вам честь.

> хочу Вам дать на общее использование код, который пригодится всем,
Спасибо. Я уже скопировал к себе Ваш пример - он действительно может мне пригодиться.

> аналогов я не видел
Я тоже.


 
tio   (2006-06-03 17:13) [5]

Чуть не забыл, вставьте одну строчку в код:
//
ID_Cancel:
              begin
                 CanClose:=false;
Abort; // вот добавленная строка, на случай, когда пользователь нажал "Отмена".
              end;

А так, код работает на 100%.


 
sniknik ©   (2006-06-03 17:57) [6]

> А так, код работает на 100%.
много чего работает на 100%... но почему то не так как ожидается авторами.
....
try
 CanClose:=true;
except
 MessageBox(0,"Ошибка сохранения документа","Сообщение",mb_ok+mb_iconStop);
end;
....


ну очень серьезный код защищен блоком try except... и именно по нему определяется ошибка сохранения документа, а не ошибками диска, правими и т.д. (действительно сохранением)...

действительно надо взять на вооружение... как все упрощается... ;)

p.s. так понимаю в связи с недавно прошедшим днем открытых дверей во всем известном учреждении его питомцы начали нести свою культуру в массы, даже не ознакомившись с тем что есть в "большом мире". ;о))


 
Юрий Зотов ©   (2006-06-03 18:33) [7]

> tio   (03.06.06 17:13) [5]

> А так, код работает на 100%.

Даже на 120. Потому что Ваш код закрытия дочерних форм при закрытии главной (в TMain_f.WMGetSysCommand):
а). Содержит техническую ошибку.
б). Попросту не нужен, потому что это уже есть в VCL.

А еще потому, что код в TChild_f.FormCloseQuery содержит 2 логические ошибки. А еще потому, что код в TChild_f.FormClose содержит лишнюю строку (кстати, надо бы копнуть код VCL и  разобраться, не приведет ли эта лишняя строка к ошибке при попытке повторного закрытия формы).

В [4] я написал чистую правду - я действительно не видел аналогов такой, извините, белиберды, поэтому и сохранил Ваш пример. Он действительно может мне пригодиться. Чтобы показывать, как не нужно делать.


 
tio   (2006-06-03 18:51) [8]

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


 
Юрий Зотов ©   (2006-06-03 19:17) [9]

> tio   (03.06.06 18:51) [8]

Хорошо, раз Вы так уверены то скажите:

1. Почему в TMain_f.WMGetSysCommand проверка WParam выполняется без комбинирования с $FFF0 ?

2. Почему в TChild_f.FormCloseQuery появляется запрос на сохранение НЕизмененного документа, но НЕ появляется запроса на сохранение измененного документа?

3. Каким образом присвоение CanClose = True приводит к сохранению документа (в TChild_f.FormCloseQuery, оператор Case, ветка ID_YES)?

4. Какое исключение может возникнуть при присвоении CanClose = True (там же)?

5. Зачем в TChild_f.FormClose вызывается метод Release?

6. Какие конкретно глюки содержит код VCL?

7. Каким образом Ваш код эти глюки обходит?

8. В чем конкретно Вы вообще увидели какую-то проблему?


 
sniknik ©   (2006-06-03 19:19) [10]

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

> А в-третьих, лучше бы не обсуждали, а показали свои творческие подходы.
на творчество это не тянет, это банальщина, но могу поделится... "мудростью" ;)

procedure TChild_f.FormClose(Sender: TObject;  var Action: TCloseAction);
begin
 if Modify then begin
   case Application.MessageBox(PChar("Документ "#39+FileName+#39" был изменен! Сохранить изменения ?"), "Закрытие документа", MB_YESNOCANCEL OR MB_DEFBUTTON3 OR MB_ICONQUESTION) of
      ID_YES:
        try
          ... здесь должно быть именно сохранение  
          Action:= cafree;
        except
          on E: Exeption do
             MessageBox(Handle, "Ошибка сохранения документа : "+E.Message, "Сообщение", mb_ok OR mb_iconStop);
        end;
      ID_NN:
        Action:= cafree;
   end;
 end;
end;


ну это наверное все, что нужно. набивал сдесь так что могут быть огрехи (запятую/кавычку не там поставил)
Modify должен быть типа boolean и содержать признак редактируемости документа, FileName его имя (Caption не то место где его нужно хранить... имхо).


 
Юрий Зотов ©   (2006-06-03 19:19) [11]

Вдогонку:

9. Зачем в [5] вставлена строка Abort?


 
sniknik ©   (2006-06-03 19:21) [12]

> могут быть огрехи
ну так и есть -> ID_NN = ID_NO первая. ;о)


 
tio   (2006-06-03 19:44) [13]

Закрывать Child окно легко из него самого, а попробуйте из MDIMain, чтобы при нажатии на кнопку ID_Yes - оно исчезло сразу.
Что не исчезает ???
Не надо было осуждать код, не видя его в действии.
Ваши сохранения и всякая чепуха закрытия, мне уже приелась.
Все одинаково.
Все это я видел, все это очень давно знакомо.
Но это не корректно - окна будут висеть, потому что главный обработчик
срабатывает OnCloseQuery - сработает дважды.

А строка Abort вставлена верно, и правильно сделано.
Если ее бы не было сообщения отмены проскакивали бы несколько раз,
сколько окно - столько сообщений.
Надо было тестировать пример на всех кнопках.
И думать, что писать.
А то обсуждать многие умеют.
А на деле потом извиняются.» Palladin:» Попробуй-ка ответить на поставленные вопросы в [9],» Palladin:» Попробуй-ка ответить на поставленные вопросы в [9], а уже потом (если ответы будут что то смыслить) у тебя будет право иметь свое мнение относительно них.


 
sniknik ©   (2006-06-03 20:02) [14]

> Что не исчезает ???
очень хорошо исчезает...

для примера (при условии что на FormClose у "детки" стоит код из [10])
procedure TForm1.FormCreate(Sender: TObject);
begin
 Randomize;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 with TChild_f.Create(self) do //создаем
   Caption:= IntToStr(Random(1000));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 if MDIChildCount > 0 then ActiveMDIChild.Close; //закрываем из MDIMain заметь
end;


где проблема то? ;)

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


 
Юрий Зотов ©   (2006-06-03 20:31) [15]

> tio   (03.06.06 19:44) [13]

Увы, ни на один вопрос Вы так и не ответили. Только слова, слова... мол, и в VCL глюки, и в Вашем коде их нет... где доказательства? Я Вам вполне конкретно перечислил ошибки и недостатки Вашего кода - в ответ ничего, кроме общих фраз.

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

ОК. "Творческий подход" (LOL) показываю ниже, а пока сообщаю Вам следующее:
а). Никакой проблемы здесь нет, решать нечего. Нужно просто написать самый обыкновенный и очень простой обработчик OnCloseQuery. Это никакая не проблема, а очень простенькая задачка для начинающих программистов.
б). На "крутизну" этот обработчик никак не потянет, так что строить тут тоже нечего.

type
 TForm2 = class(TForm)
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
 public
   Modified: boolean;
   procedure SaveDoc;
 end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree
end;

procedure TForm2.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
 if Modified then
   case MessageBox(Handle, "Документ был изменен. Сохранить изменения?", "Закрытие документа",
     MB_YESNOCANCEL or MB_DEFBUTTON3 or MB_ICONQUESTION or MB_TASKMODAL) of
   ID_YES:
     try
       SaveDoc
     except
       CanClose := False;
       raise
     end;
   ID_CANCEL:
     CanClose := False
   end
end;

procedure TForm2.SaveDoc;
begin
 // Здесь код сохранения с с возбуждением исключения при ошибке.
 // Для тестирования мы заменяем его следующим кодом:
 if Random > 0.5 then
   raise Exception.Create("Ошибка сохранения документа")
end;

Этот код надо добавить к дочерней форме - и все. Главную форму трогать вообще не нужно. Все остальное сделает код VCL - причем, несмотря на свою глюкавость, сделает совершенно четко.

Если желаете в этом убедиться, то введите в главную форму следующий обработчик - и можно жать F9:

uses
 Unit2, TypInfo;

procedure TForm1.FormDblClick(Sender: TObject);
begin
 with TForm2.Create(Application) do
 begin
   Modified := Random > 0.5;
   Caption := "Modified = " + GetEnumName(TypeInfo(Boolean), Ord(Modified))
 end
end;

Надеюсь, после тестирования Вы убедитесь, что никакой проблемы нет, а код VCL работает очень даже нормально. А все, что Вы написали в [0], [5], [8] и [13] есть просто чушь. И что "крутого" строите из себя как раз Вы сами.

Потому что как еще назвать без году недельного программиста, на код которого трудно смотреть без слез и смеха, но который все же абсолютно уверен что код профессионалов из Borland"а более глюкавый, чем его собственный?


 
Eraser ©   (2006-06-03 22:36) [16]

<Offtop>
только у меня или у всех в конеце поста [13]
есть синие надписи?

» Palladin:
» Попробуй-ка ответить на поставленные вопросы в [9],
» Palladin:
» Попробуй-ка ответить на поставленные вопросы в [9], а уже потом (если ответы будут что то смыслить) у тебя будет право иметь свое мнение относительно них.
</Offtop>


 
DrPass ©   (2006-06-03 23:04) [17]

<Offtop>

> Eraser ©   (03.06.06 22:36) [16]

Не бойся, это была невидимая рука модератора. Белая горячка себя по-другому проявляет
</Offtop>


 
sniknik ©   (2006-06-03 23:09) [18]

Eraser ©   (03.06.06 22:36) [16]
есть, а что?

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


 
Джо ©   (2006-06-03 23:09) [19]

Дык, в "компонентах" давно такой эффект имеется :)


 
Eraser ©   (2006-06-03 23:10) [20]


> DrPass ©   (03.06.06 23:04) [17]

<Offtop>
Ну слава Всевышнему, а то я уже хотел бросать пить )
</Offtop>


 
Eraser ©   (2006-06-03 23:11) [21]


> Джо ©   (03.06.06 23:09) [19]

да редко туда заглядываю, а такую надпись вижу второй раз )



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2006.07.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.008 c
15-1150219382
dimodim-Furyz
2006-06-13 21:23
2006.07.16
Web-radio


2-1151304985
Neket
2006-06-26 10:56
2006.07.16
DBGrid


2-1151153327
K_Lock
2006-06-24 16:48
2006.07.16
QuickReport


2-1151385233
bajenovv
2006-06-27 09:13
2006.07.16
помогите плиз новичку!!!!


15-1150377136
syte_ser78
2006-06-15 17:12
2006.07.16
вдогонку о вопросе "как прогнать все переменные"





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский