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

Вниз

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 вся ветка

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

Наверх




Память: 0.52 MB
Время: 0.022 c
8-1160561120
zorgens
2006-10-11 14:05
2007.06.24
DSPack


15-1180106935
nomen
2007-05-25 19:28
2007.06.24
Вопрос электронщикам про ч/б ж/к дисплей


3-1175016877
Цукор5
2007-03-27 21:34
2007.06.24
DBase ( Win or DOS ???)


9-1154443127
RomanH
2006-08-01 18:38
2007.06.24
Пилотирование камеры в 3D


2-1180717499
Malik
2007-06-01 21:04
2007.06.24
Неразбериха с SavePictureDialog.