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

Вниз

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

 
Galkov ©   (2006-11-13 12:52) [0]

Вот вопрос(ы) задаю, потому-что простой поиск по фрагменту "TMenu" полезного ничего не принес
1) Мне понятно, почему ВСЕ менюхи, подчиненные данному контроллу увязываются в один список. Мне непонятно, почему критерием MainMenu является fMenuObj=nil, а не совпадение хэндлов в TMenu с полем fMenu контролла
2) Мне непонятно, почему НИКТО не ставит себе в труд обнулить поле fMenuObj. Даже после fMenuObj.free (например в TMenu.SetMenu)
3) Мне непонятно, на кой ляд TMenu.free уничтожает весь список после себя. И почему уничтожением всего списка не занимается только TControl.destroy - кому это нужно еще, кроме него.
4) Мне непонятно, почему в TMenu.destroy происходит отстегивание MainMenu формы не интересуясь, а что к этому времени осталось от формы. Судя по моим скудным поискам по форуму - крах задачи зависит от оси... Но по-любому: делать SetMenu(..., 0) из TControl.Destroy (через fMenuObj.free) - неприлично. Но безусловно необходимо, если это независимый вызов TMenu.free
5) Мне непонятно, почему в TMenu.Destroy есть вольности с выходом без inherrted (а, следовательно, и без вызова Final)

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

Безусловно, мог бы предложить свой комплексный фиксинг, но опять не понимаю (:)) как это удобней сделать


 
Vladimir Kladov   (2006-11-13 16:25) [1]

что за критерий MainMenu? Первый раз слышу. Если при создании, чтобы определить, главное это меню или нет, то как можно использовать совпадение хэндлов, когда их еще нет, и они не присвоены. Если про RedrawFormMenuBar, то потому сто так короче.

Поищите по тексту fMenuObj.free. Когда надо, оно обнуляется. Нет никакого смысла делать это в деструкторе непосредственно перед разрушением формы.

на кой ляд TMenu.free уничтожает весь список после себя
Так сделано. Чему это мешает? В KOL меню построены в список: первое - главное, прочие - pop up. Если нет главного, надо создать пустое первое. Так сделано изначально. Меню один раз сождаются, и один раз уничтожаются, вместе с формой.

Если про этот кусок (насчет выхода без inherited)
 if FParentMenu <> nil then
 begin
   Prnt := FParentMenu;
   Next := Prnt.RemoveSubMenu( FId );
   FParentMenu := nil;
   Prnt.FItems.Remove( @ Self );
   if Next = nil then  Exit;
 end;


То он никогда не срабатывает (по крайней мере у меня так получается). Надо бы вообще убрать, но сначала надо вспомнить, вообще откуда он взялся, и зачем был нужен.


 
Galkov ©   (2006-11-13 22:49) [2]


> что за критерий MainMenu? Первый раз слышу. Если при создании,
>  чтобы определить, главное это меню или нет, то как можно
> использовать совпадение хэндлов, когда их еще нет, и они
> не присвоены.
Ни в коем случае не имел в виду TControl.handle, но TMenu.handle и TControl.fMenu, которые создаются сразу, невзирая на создание окна windows. Мне так показалось. Про отложенные деструкторы мне, как бы, понятно ...
Но имелись в виду не технические детали, а постановочная часть. Мне понятно, что "так было сделано", и даже понятно как. Вопрос, по большому счету, что мешает сделать "по нормальному". И обсудить, конечно же, что есть нормально.


> Поищите по тексту fMenuObj.free. Когда надо, оно обнуляется

Дык поискал. Готов согласиться, что в TControl.destroy это не надо. Если считать, что TMenu.SetMenu может вызываться только из KOL, то это, по меньшей мере - странно. Св-во TMenu.Menu открыто на запись в разделе public.
Насколько я понимаю в кодах, после присваивания:
MainMenu.Menu :=0 MainForm.free обязан приводить к краху.


> Так сделано. Чему это мешает?

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


> То он никогда не срабатывает (по крайней мере, у меня так
> получается).

Здесь согласен, недосмотрел... Пожалуй, и
Prnt.FItems.Remove( @ Self ); - тоже излишество...

================================================
Но больше меня интересует п.4, оставшийся без комментария. Попробую конкретизировать вопрос:
Если исходить из "так сделано", то единственная разумная возможность запустить TMenu.free - это уничтожить контролл, который, в свою очередь, сделает fMenuObj.free. Возможно, я не прав - тогда очень прошу разъяснить... Скажем, примером иной разумности.
Далее. КАКИЕ у нас гарантии, что, в процессе уничтожения контролла, строка из TMenu.Destroy:
Windows.SetMenu( FControl.fHandle, 0 ); не закончится крахом.
Вопрос задаю, потому что я это исключение - имею... Если MainMenu назначено не аплету. И для меня большой вопрос - почему это живет до сих пор :(
Естественно, прежде всего, я подозревал свою безграмотность. Но здоровье уже кончилось, разбираться, как правильно составить программу из 4-х строк: создал аплет, создал форму, назначил форме меню, Run(Applet) - исключение по выходу. Проверил: именно на вышеуказанной операции SetMenu.
Вот и вопрошаю....

================================================
В режиме вопрос/ответ как-то сумбурно получается....
А хотелось, в основном-то, решить вопросы на более высоком уровне абстракции:
1) От пользователя библиотеки KOL должны быть скрыты все подробности с fMenuObj и полем Next. И ему (пользователю) должно быть все равно, в каком порядке, какие менюхи созданы.
2) У него должна быть возможность создавать/уничтожать их динамически: понадобилось новое – пожалуйста, NewMenu; надоело – TMenu.free, и всего делов.
3) И никаких нравоучений от библиотеки быть не должно: это сейчас, а это после, а для этого создай фиктивный контролл... Не дело это, ИМХО

Вот именно из этих предпосылок и представляется мне, что следует (по большому счету, пропуская сейчас технические детали) делать так:
1) fMenuObj может указывать не обязательно на MainMenu, но и на PopUp
2) Критерий в NewMenu для создания MainMenu/PopUp должен измениться – соображения в этом посте выше. Грубо говоря, возражений я не понял, и хотелось бы дополнительных разъяснений. Но, в любом случае – чего-нибудь да придумается…
3) Деструктор TMenu должен уничтожать только одну менюху из Next-цепочки. А деструктор TControl – всю цепочку, перелистыванием.

И в свете вышесказанного, мне хотелось бы, чтобы основной вопрос этого топика звучал примерно так: ЧТО НАМ МЕШАЕТ СДЕЛАТЬ ИМЕННО ТАК :?:
Вроде бы - ничего военного...


 
Galkov ©   (2006-11-13 22:58) [3]


> Про отложенные деструкторы мне, как бы, понятно
Пардон, КОНСТРУКТОРЫ, конечно же... :(

btw: не пойму, как свой пост править... трудно ведь, сразу - и грамотно...


 
Vladimir Kladov   (2006-11-14 21:03) [4]

TMenu.handle и TControl.fMenu, которые создаются сразу, невзирая на
создание окна windows

Эту фразу я не понял. Надо создавать не сразу? А когда?

Св-во TMenu.Menu открыто на запись в разделе public
Мало ли что где в public. Destroy тоже в public, потому что иначе компилятору не нравится. Но вызывать надо Free или RefDec, а не Destroy.

Меню уже переделывалось. Можно и еще (немного) переделать. Проблема в сохранении какой-то совместимости. Я не совсем понимаю: есть сложностис уничтожением popup меню, созданного в run-time? По замыслу, не должно было быть, ведь оно последнее в цепочке. Вообще, идея цепочки устарела примерно с версии 2.40, когда прямой вызов Free для каждого объекта формы отменен и заменено все на это на более активное использование Add2AutoFree. Если только в этом дело, это можно (наверное) исправить. Для любого исправления хотелось бы, чтобы изменения были по возможности минимальны, и в коде, и в концепции. Революции никому не нужны, ни мне, ни вам.

Далее. КАКИЕ у нас гарантии, что, в процессе уничтожения контролла, строка из TMenu.Destroy:
Windows.SetMenu( FControl.fHandle, 0 ); не закончится крахом.

Не нужны здесь никакие гарантии. Пока еще работает деструктор (контрола), объект существует, и FControl на него показывает. fHandle в этот момент все еще жив должен быть.

Вопрос задаю, потому что я это исключение - имею... Если MainMenu назначено не аплету. И для меня большой вопрос -
почему это живет до сих пор

Вы наверное в своем коде что-то не так делаете? Простой пример со статическим меню работает корректно. Можно остановиться на этой строчке (Windows.SetMenu, и убедиться, поглядев стэк и переменные, что все в порядке и по-другому быть не может. У вас случайно не происходит повторного вызова деструктора уже разрушенного меню? (А что значит - меню назначено аплету? Ну, конечно, его можно назначить и отдельному контролу, и вообще любому TControl"у даже графическому, но кажется и так понятно, что так делать не надо).

составить программу из 4-х строк: создал аплет, создал форму, назначил форме меню, Run(Applet) - исключение по выходу.
Проверил: именно на вышеуказанной операции SetMenu

Я понимаю, что MCK становится все менее доступен из-за невозможности его использовать в BDS и Turbo-Delphi. Но может быть все-таки проблема в неправильном написании кода вручную? Простейший пример на MCK не падает, и работает корректно. Можно поставить себе какую-нибудь старенькую Delphi типа 5, чтобы хотя бы иногда сравнивать, что вы сами делаете с тем, как оно делается автоматом.

1) От пользователя библиотеки KOL должны быть скрыты все подробности с fMenuObj и полем Next. И ему (пользователю)
должно быть все равно, в каком порядке, какие менюхи созданы.
И так почти все равно. Кроме одной важной детали: главное меню создается первым.


Не дело это, ИМХО
Так сделайте дело. Моя задача минимальный код. Я ее сделал как сумел. Сумейте лучше.

1) fMenuObj может указывать не обязательно на MainMenu, но и на PopUp
Нет. В Windows MainMenu может быть только одно для формы, это вам не иксы. Поэтому и сделано так было. Цепочка была, чтобы минимизировать код, чтобы форма не хранила все свои меню в особом своем списке, и дополнительный код по удалению меню подключался только если есть хотя бы 1 меню. Сейчас можно в принципе перейти к авто-удалению, и убрать цепочки (но для каждого меню добавится еще 1 вызов Add2AutoFree). Но меню как объект нужно только для главного меню. И тогда уже не для удаления, а для перерисовки меню. (Для ссылок на popup меню механизм отдельный, и вообще этот автомат для удобства в простейшем случае - ручной обработчик может выбирать какие popup меню вызывать от обстоятельств).

хотелось бы дополнительных разъяснений Совместимость. Приходят разные революционеры, и давай все крушить. Вы где 8 лет назад были? (Я уже сыт по горло разбирательствами с GTK+, где даже не 50, а все 75% функций deprecated, потому что приходит некто и говорит: а вот так будет сделать лучше, давайте все переделаем, и каждая новая версия приводит к необходимости переделывать код для разработчиков. Или тот же DirectX в части directVideo/direct3D - после чего у разработчиков возникает естественное стремление больше никаких дел с этим directX не иметь вообще, благо есть альтернатива в лице OpenGL, примеры для которого написанные 10 лет назад, и сейчас для самых новых версий прекрасно компилируются без переделки кода).

Значит. 1) Сначала разберемся, что там у вас падает. Шлите мылом короткий пример, если никак не получается. Может, и правда, мне найдется что у себя поправить. 2) На отмену цепочек я и так собирался пойти, просто побоялся все исправления в 1 флакон засовывать.


 
Galkov ©   (2006-11-14 23:59) [5]

Тезисно:
1) Что  значит "шлите мылом"? Собственно, я с этого и начинал, и предполагаю, что это попало в спам. Какие магические слова, в связи с этим, следует прописать в <Теме> ???
Конечно же - вышлю, как только узнаю как и куда :)

2) Идею про ликвидацию цепочек до конца не понял. В смысле, не увидел из поста, чем будет заменено сегодняшнее "листание" списка при обработке WM_COMMAND в аттаче WndProcMenu (извините, что использую данный форум не только для фиксинга, но и для самообразования)

3) Про совместимость мне понятно, и я тоже против диктата пользователю КАК он должен делать, и ЧТО. Даже еще больше против, чем Вы излагаете. Если присмотреться, то предложения заключались в расширение возможности работы, при полной работоспособности старого. Сегодня: это можно, а это нельзя. Предлагается сделать, чтобы можно было и это, и то. И я категорически против того, чтобы нельзя было то, что сегодня можно, но ЗА ТО...

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

5) Это D4, и исключительно command line. Возможно, необходимы некоторые пояснения. Есть некий проект визуального программирования, функционирование которого состоит в том, что на основании графической информации (напоминающей эл.схему) генерируется код для некого компилятора, который честно и запускается в последствии.
Автор - не я, но за паскалевские коды необходимых для этой среды юнитов (KOL - не считается :)), как и за процесс кодогенерации отвечать могу.
Другими словами, существуют и иные причины не использования MCK, кроме невозможности его использовать в BDS и Turbo-Delphi :)

==================================
Мораль: для реализации Вашего предложения 1, беру маленький тайм-аут. Поскольку есть причина для поисков - будет и результат. Похоже на такое: кто-то думал, что в KOL так можно, ан фигушки :) Ибо версию с повторным проходов деструкторами я с негодованием отметаю: на контроллах честно перехвачено их уничтожение через onDestroy, как раз для предотвращения такого безобразия.
Надежность диагноза про SetMenu ??? Банальные вставки ДО и ПОСЛЕ этой строки. Скажем:
Beep(1000,300) ;
Windows.SetMenu( FControl.fHandle, 0 );
Beep(2000,300);

Первый - есть, а вместо второго - Run Time Error


 
Galkov ©   (2006-11-15 13:28) [6]

Нашел...

В сухом остатке:
1) Run Time Error происходит в "моих" кодах, а не в кодах KOL
2) Вопрос N1 для меня закрыт, по большому счету. Но демонстрация баги может иметь методологическое значение и для KOL. Догадаться, что после OnDestroy может происходить вызов назначенных событий - было очень непросто. Поэтому демонстрирую...
Почему именно так (хотя исходное не совсем так :)) - это тема отдельного обсуждения. Сейчас, наверное, достаточно того, что это редукция более значительного кода, полученного неким ИИ, чтоб ему пусто было :)

Program test;
uses  windows,messages,kol;

type
 TMainForm = class
  public
   Control:PControl;
   constructor Create(Parent:PControl);
   destructor Destroy; override;
   function _OnMes(var Msg: tagMSG; var Rslt: Integer ): Boolean;
   procedure _OnDestroy(Sender:PObj);
 end;

constructor TMainForm.Create;
begin
 Control := NewForm(Parent,"MainMenuTest");
 Control.OnDestroy := _OnDestroy;
 Control.OnMessage := _OnMes;
end;

procedure TMainForm._OnDestroy;
begin
 Control := nil;
end;

destructor TMainForm.Destroy;
begin
 Control.free;
 inherited;
end;

function TMainForm._OnMes;
begin
 Result := False;
 //if Control=nil then exit; {!!! Это мой вынужденный фиксинг(и)}
 {Это BUG_DEMO, поэтому не очень важно содержание - важно использование поля Control}
 if (Msg.message = WM_MOVE) or (Msg.message = WM_SIZE) then
   Applet.BoundsRect := Control.BoundsRect;
end;

var MainForm:TMainForm;

begin
 Applet := NewApplet("Хи-Хи-Хи");
 MainForm := TMainForm.Create(Applet);
 NewMenu(MainForm.Control,0,
 ["File",
  "(",
    "New",
    "Open",
    "Save As..",
    "-",
    "&Exit",
  ")"],nil);
 Run(Applet);
 MainForm.Destroy;
end.



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

Форум: "KOL";
Текущий архив: 2007.06.24;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.036 c
15-1180183362
boriskb
2007-05-26 16:42
2007.06.24
Поносов обвинил прокуратуру в пиратстве


15-1180334920
tesseract
2007-05-28 10:48
2007.06.24
Получи 5*10^3 уе от Sun


2-1180861988
Delf_
2007-06-03 13:13
2007.06.24
2 вопроса


15-1180511542
antonn
2007-05-30 11:52
2007.06.24
запуск процесса с языковыми настройками


3-1175246867
Slava
2007-03-30 13:27
2007.06.24
DESCRIBE в FibPlus Script





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский