Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.01.30;
Скачать: CL | DM;

Вниз

Не происходит переключение между формами   Найти похожие ветки 

 
Андрей2   (2004-06-12 23:19) [0]

Имеется три формы. После запуска они все отображаются (Visible = true). Но проблема не в этом - проблема с переключением между формами. Конкретно: при переключении между формами 2 и 3 всё происходит отлично - без глюков. Но вот при переключении на 1-ую форму спустя долю секунды фокус обратно возвращается на форму, с которой происходило переключение. Таким образом переключиться на фору 1 можно только после закрытия форм 2 и 3, хотя при двойном щелчке по заголовку 1-ой она успешно назворачивается, за заголовок успешно перемещается, но системные кнопки (свернуть, развернуть и закрыть) тоже не нажимаются. Как я понял - этот глюк происходит только с главными формами (в KOL по умолчанию 1-ая форма - главная, а остальные - её дочерние). Как исправить этот глюк? (где внести изменения в KOL.pas)


 
Dimaxx   (2004-06-13 00:02) [1]

Код приведи. Чем пользовался для открытия модальных форм?


 
SPeller ©   (2004-06-13 06:33) [2]

Есть такой глюк. Я его давно исправил, но Владимир пока не хочет вносить изменения в kol.pas. Часть внесены уже, но не полностью. Желающим могу выложить здесь все нужные изменения для тестов.


 
Vladimir Kladov   (2004-06-13 08:18) [3]

Нет такого глюка. Положить на главную форму KOLProject, закрыть проект, открыть его и сделать Project|Build.


 
Андрей2   (2004-06-13 09:37) [4]

Отвечаю Dimaxx. Формы - НЕ МОДАЛЬНЫЕ!!!


 
Андрей2   (2004-06-13 09:40) [5]

SPeller. А мне на e-mail: Andr@(собака)mail.ru прислать не можешь? (пишу "(собака)" для предотвращения действий спам-роботов по рассылке спама)


 
Андрей2   (2004-06-13 09:42) [6]

SPeller. Извини. Дал неправильный e-mail. Правильный - Andr-forum@(собака)mail.ru.


 
Андрей2   (2004-06-13 09:44) [7]

Vladimir Kladov. Я так и делаю - так написано в инструкции по использованию KOL, а инструкции я читаю. И данная проблема этим не решается.


 
Андрей2   (2004-06-13 09:44) [8]

Vladimir Kladov. Я так и делаю - так написано в инструкции по использованию KOL, а инструкции я читаю. И данная проблема этим не решается.


 
Vladimir Kladov   (2004-06-13 10:18) [9]

для немодальных не было проблем вообще: Form4.Form.Show; Если это не работает можно еще попробовать Form4.Form.BringToFront;


 
Андрей2   (2004-06-13 11:05) [10]

Vladimir Kladov. Форма отображается без проблем, но пока она отображается невозможно переключиться на главную форму - на Form1 - после кратковременной паузы фокус возвращается на форму, с которой производилось переключение - в вашем слечае на Form4. Вопрос: Как переключиться на Form1 без закрытия Form4.


 
Vladimir Kladov   (2004-06-13 11:48) [11]

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


 
Андрей2   (2004-06-13 12:15) [12]

Vladimir Kladov. Почему Вы меня не понимаете. У меня ПУСТОЙ проект, не ставлю обработчик ни на одно из событий - просто запускаю "три формы" и "наслаждаюсь глюками". Попробуйте сами: создаём проект, добавляем дополнительно ещё две формы (в итоге получается три формы). Переводим его в KOL (сохраняем проект, добавляем на Form1 компонент KOLProject, задаём значение свойства projectDest например Proba, далее на все без исключения формы кидаем кидаем компонент KOLForm, ещё раз сохраняем, из папки, в которую сохранили открываем файл Proba.dpr), делаем, чтобы после запуска были отображены все три формы (через Инспектор объектов или обработчик события OnCreate - не имеет значения), запускаем, пытаемся переключиться со второй или третьей формы на первую и терпим неудачу - фокус фозвращается обртно на вторую или третью (взависимости от того, с какой формы происходило переключение). После того как проделаете - поделитесь своими впечатлениями на форуме.


 
Vladimir Kladov   (2004-06-13 14:20) [13]

Не то написал я. TKOLApplet а не TKOLProject.


 
SPeller ©   (2004-06-13 14:37) [14]

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


 
Vladimir Kladov   (2004-06-13 15:21) [15]

Мне непонятно, зачем вносить массу изменений и провоцировать новые возможные глюки, которые обязательно появятся при этом, если есть решение, придуманное изначально: Applet для того и предназначался, чтобы играть роль менеджера форм, и я вляется в этом смысле полным аналогом TApplication в VCL.


 
SPeller ©   (2004-06-13 15:23) [16]

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

Всё началось с того, что когда мне понадобились модальные формы, то я столкнулся с рядом проблем, таких как "хитрые" вызов и скрытие модальной формы, описанный выше глюк с фокусом, и ещё пара попутных глюков. После некоторого времени поисков решения и оптимизации я это всё нашёл. Кроме того, моё решение меньше увеличивает размер конечного ЕХЕ.

Доказательство о меньшем размере:
Я сравнивал,  всё в pas-версии, так как моей функции в асм-версии нет, и размер её, естественно, будет больше исходного варианта. Для испытания использовал проект без аплета с тремя формами. На формах кроме стандартных кнопок ничего нет. Для испытаний я сделал следующее:
Разбил свои добавления в kol.pas на части. Условно обозначил их так:

Реализация ShowModalParented - "Parented";
Всё что относится к SetModalResult - "SetMR";
Мой вариант обработчика WM_CLOSE в TControl.WndProc - "WM_CLOSE";

оба куска такого кода в wndprocapp и wndprocform:
   if Self_.fModalForm <> nil then
     SetFocus( Self_.fModalForm.fHandle )
   else
   if (Self_.FCurrentControl <> nil) and not(Self_.fCurrentControl.IsForm xor Self_.fIsApplet) then

заменяющих в обычных условиях такую строку:
   if Self_.FCurrentControl <> nil then
я обозначил как "xor".

А исходный вариант ShowModal - так и оставил "ShowModal".

SetModalResult это write-метод свойства ModalResult и предназначен для гарантированного скрытия формы с экрана при установке ModalResult. Причина в том, что если ModalResult станет отличным от нуля, но при этом в очередь сообщений потока не придёт ниодного сообщения, то форма так и будет висеть на экране. SetmodalResult просто устанавливает нужное значение результата и отправляет окну нейтральное сообщение.

Ниже получил размеры ЕХЕ. Использовалось Delphi 6 + SysDcu. Запись +ХХХ означает подключение части ХХХ моего кода в ЕХЕ.

Что включено:           Размер ЕХЕ:
--------------------------------------------
[ничего]                     24064
+ShowModal                   25600  <---
+WM_CLOSE                    24064
+Parented                    24576
+SetMR                       24576
+xor                         24576
+WM_CLOSE+Parented           25088
+xor+WM_CLOSE+Parented       25088
+xor+WM_CLOSE+Parented+SetMR 25088  <---
 

Выводы делайте сами. Я так думаю, что можно переходить полностью на мой вариант. Для экономии кода я думаю отказаться от SetModalResult вовсе, либо заключить его в скобки вроде {USE_SETMODALRESULT}. Вот мои изменения
полностью:

function WndProcApp
...
 WM_SETFOCUS:
   {$IFDEF NEW_MODAL}
   if Self_.fModalForm <> nil then
     SetFocus( Self_.fModalForm.fHandle )
   else
   if (Self_.FCurrentControl <> nil) and not(Self_.fCurrentControl.IsForm xor Self_.fIsApplet) then
   {$ELSE not_NEW_MODAL}
   if Self_.FCurrentControl <> nil then
   {$ENDIF not_NEW_MODAL}
   begin
     Self_.FCurrentControl.CreateWindow; //virtual!!!
...
end;

function WndProcForm
...
 // with _Self^ do
 WM_SETFOCUS:
   begin
     {$IFDEF NEW_MODAL}
     if fModalForm <> nil then
       SetFocus( fModalForm.fHandle )
     else
     if (FCurrentControl <> nil) and not(fCurrentControl.IsForm xor fIsApplet) then
     {$ELSE not NEW_MODAL}
     if FCurrentControl <> nil then
     {$ENDIF}
     begin
       FCurrentControl.CreateWindow; //virtual!!!
...
end;

{$IFNDEF NEW_MODAL}
function TControl.ShowModalParented(const AParent: PControl): Integer;
begin
 Result := 0;
end;

{$ELSE NEW_MODAL defined}

function TControl.ShowModalParented(const AParent: PControl): Integer;
var FL: PList;
   OldMF,
   F: PControl;
   I: Integer;
begin
 Result := 0;
 if (AParent = nil) then Exit;

 Inc( fModal );
 FL := NewList;
 OldMF := AParent.fModalForm;
 AParent.fModalForm := @Self;

 if AParent.fIsApplet or (AParent.IsMainWindow and AParent.fIsForm) then
 begin
   for I := 0 to AParent.ChildCount - 1 do
   begin
     F := AParent.fChildren.Items[ I ];
     if (F <> @Self) and F.fIsForm and F.fEnabled and F.fVisible then
     begin
       FL.Add( F );
       F.Enabled := FALSE;
     end;
   end;
 end;

 if AParent.fIsForm and AParent.Enabled then
 begin
   FL.Add( AParent );
   AParent.Enabled := FALSE;
 end;

 ModalResult := 0;
 Show;
 while not AppletTerminated and (ModalResult = 0) do
 begin
   WaitMessage;
   AParent.ProcessMessages;
   {$IFNDEF NOT_USE_OnIdle}
   ProcessIdle( @Self );
   {$ENDIF}
 end;

 AParent.fModalForm := OldMF;
 Dec( fModal );
 for I := 0 to FL.Count - 1 do
   PControl( FL.Items[ I ] ).Enabled := True;
 FL.Free;
 Hide;
 Result := ModalResult;
end;
{$ENDIF NEW_MODAL}


Изменения WM_CLOSE уже есть в kol.pas.

В пользу моего варианта есть ещё и тот момент, что в исходном баг: в модальной форме при закрытии никогда не вызывается обработчик OnClose.

Теперь вопрос, который наверняка возник: почему ShowModalParented? Потому что существуют ситуации, когда в приложении нужно показать модальную форму только относительно определенного окна, которое и станет недоступным, а не относительно всего проекта, когда недоступными становятся все окна программы. Запись ShowModalParented( Applet ) в таком случае будет эквивалентна нынешнему ShowModal.

Что конкретно дают мои зменения?
1) Алгоритм вызова модальной формы не зависит от наличия отдельного объекта Applet;
2) Вызов модальной формы производится единственной строкой
  Form.ShowModalParented( SomeFormOrApplet );
Больше не требуется обсолютно никаких действий чтобы вызов и завершение формы были правильными.
3) В модальной форме нет необходимости назначать обработчик OnClose для того чтобы предотвратить уничтожение объекта формы
4) Нет глюка с фокусом. В случае модальных форм — когда Аплет не используется, то при закрытии модальной формы главная никак не может получить фокус, точно так же как описывает здесь автор сабжа.


 
SPeller ©   (2004-06-13 15:28) [17]


> Vladimir Kladov   (13.06.04 15:21) [15]

Дык, можно ведь всё новое заключить в скобки условной компиляции и включать когда захочется. Да и откуда глюки, если программист может ошибиться только в написании строки Form.ShowModal или Form.ShowModalParented? Я ведь исправил два серьёзных глюка - с фокусом и с вызовом OnClose, в придачу уменьшил размер, занимаемый, кодом для модальности, а вы продолжаете говорить что надо использовать Аплет.


 
Андрей2   (2004-06-13 15:37) [18]

Глюки надо искать и исправлять, а не обходить. SPeller, спасибо за столь полный ответ, сейчас попробую его переварить, а об итогах потом сообщу.


 
Vladimir Kladov   (2004-06-13 18:56) [19]

добавление TKOLApplet увеличивает код на 300 байт, а всего этого - на 1К. Кроме того, нет асм-кода. Кто его будет писать? Замечу что переход от асм-кода к пас-коду добавляет весьма ощутимо - на пустом проекте.

И вообще KOL.TApplet - это не исправление глюка, а опциональная фича, ее использование изначально было запланировано. Отсутствие его предполагалось только для проектов простейших, из 1 формы.


 
SPeller ©   (2004-06-14 16:11) [20]


> Vladimir Kladov   (13.06.04 18:56) [19]

Неправду говорите. 1Кбайт - это вы преувеличили, потому что 1К - это код для обеспечения модальности. Ваш код ещё больше занимает. А вот та часть кода, которая исправляет глюк с фокусом, которую я обозначал "xor", НИЧЕГО не добавляет (по крайней мере ничтожно мало). И уж гораздо меньше чем Аплет.

-----------------
[ничего]    17920
+Applet     18432
+xor        17920


Ну и где же мой килобайт? А глюк исправлен.


 
Андрей2   (2004-06-30 22:08) [21]

SPeller. Попытался я разобрать ваш код, однако не всё в нём понял - понял только как исправить глюк с переключением на не главные формы. Но мне также хотелось бы и узнать как без глюков отображать модальные формы. Пожалуйста, можно по подробнее? - выложите на форум пояснения к вашему коду или вышлюте мне на e-mail: Andr-forum@(собака)mail.ru (пишу "(собака)" для предотвращения действий спам-роботов) Ваш исправленный вариант KOL.pas. Заранее спасибо.


 
Gandalf ©   (2004-07-02 19:17) [22]

Желательно бы окончательный вариант сюда бросить чтоб оно потом в FAQ ушло.



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

Текущий архив: 2005.01.30;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.035 c
3-1103728517
juice
2004-12-22 18:15
2005.01.30
Как вставить запись в таблицу , содержащую Blob-поле?


6-1100547605
Луарвик
2004-11-15 22:40
2005.01.30
Передача файлов через http прокси?


1-1105612715
WhiteGuy
2005-01-13 13:38
2005.01.30
Плюсовая округлялка


1-1105633489
The X
2005-01-13 19:24
2005.01.30
Как экспортировать данные в HTML?


8-1098038113
ZedeS
2004-10-17 22:35
2005.01.30
Заметки на рабочем столе