Форум: "KOL";
Текущий архив: 2005.01.30;
Скачать: [xml.tar.bz2];
ВнизНе происходит переключение между формами Найти похожие ветки
← →
Андрей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 вся ветка
Форум: "KOL";
Текущий архив: 2005.01.30;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.037 c