ホーム
Top.Mail.Ru Yandeks.Metrika
フォーラム: "KOL";
現在のアーカイブ:2007.06.24;
ダウンロード:[xml.tar.bz2];

ダウン

TMenu in 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];

2階





メモリ:0.63 MB
時間:0.093 c
15-1180464954
イクシク
2007-05-29 22:55
2007.06.24
.NET 2.0 web.config


15-1180332884
サンドボックスボーイ
2007-05-28 10:14
2007.06.24
ヒューゴチャベスが大学の入学試験をキャンセル


2-1180570261
グリベラ
2007-05-31 04:11
2007.06.24
JvImageのクリーンアップ


15-1180074579
Jeer
2007-05-25 10:29
2007.06.24
熱が働いています。


2-1180639073
彼らの
2007-05-31 23:17
2007.06.24
検索アルゴリズムのヘルプ...





アフリカーンス語 アルバニア語 アラビア語 アルメニア語 アゼルバイジャン語 バスク ベラルーシ ブルガリア語 カタルーニャ語 中国語(簡体字) 中国語(繁体字) クロアチア語 チェコ語 デンマーク語 オランダ語 英語 エストニア語 フィリピン語 フィンランド語 フランス語
ガリシア語 ジョージアン ドイツ語 ギリシャ語 ハイチ語 ヘブライ語 ヒンディー語 ハンガリー語 アイスランド語 インドネシア語 アイリッシュ イタリア語 日本語 韓国語 ラトビア語 リトアニア マケドニア語 マレー語 マルタ語 ノルウェー語
ペルシア語 ポーランド語 ポルトガル語 ルーマニア語 ロシア語 セルビア スロバキア語 スロベニア語 スペイン語 スワヒリ語 スウェーデン語 タイ語 トルコ語 ウクライナ語 ウルドゥー語 ベトナム語 ウェールズ語 イディッシュ語 ベンガル語 ボスニア語
セブアノ語 エスペラント グジャラート語 ハウサ語 モン族 イボ ジャワ語 カンナダ語 クメール語 ラオ語 ラテン マオリ語 マラーティー語 モンゴル語 ネパール語 パンジャブ語 ソマリ タミル語 テルグ語 ヨルバ語
ズールー語
Английский Французский Немецкий Итальянский ポルトガル語 Русский Испанский