-
MTsv DN (04.12.09 09:45) [0]Всем привет...
В продолжении темы: http://pda.delphimaster.net/?id=1259759327&n=10
Появились некоторые вопросы по меню, видимо к Владимиру, хотя если у кого есть ответы, рад буду выслушать.
1. Почему Count считает всегда число элементов по всей глубине субменю?
З.Ы. Строчкаk := GetMenuItemCount(pm.Items[0].Parent.Handle);
возвращает правильный Count, т.ч. вопрос не актуален.
2. Почему при вызове RemoveSubMenu число Count не уменьшается. Вот это уже актуальный вопрос!!! -
MTsv DN (04.12.09 17:32) [1]3. Ошибка в функции InsertSubMenu. Причину не нашел...см. http://pda.delphimaster.net/?id=1259759327&n=10
Дополнительно:
По первому пункту пред. поста:
Думаю надо добавить в KOL.PAS функцию GetCountSubMenu, основной код выше.
Фикс для пункта 2 предыдущего поста:function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;
{$IFDEF DEBUG_MENU}var OK: Boolean; {$ENDIF}
begin
Result := Items[ ItemToRemove ];
if Result = nil then Exit;
if Result.FParentMenu <> nil then
begin
{$IFDEF DEBUG_MENU} OK := {$ENDIF}
RemoveMenu( Result.FParentMenu.FHandle, Result.FId, MF_BYCOMMAND );
Result.FParentMenu.FMenuItems.Remove( Result );
end
else
begin
{$IFDEF DEBUG_MENU} OK := {$ENDIF}
RemoveMenu( FHandle, Result.FId, MF_BYCOMMAND );
Self.FMenuItems.Remove( Result );
end; -
Пока скопировал. Динамические меню не юзаю обычно. Разбираться нет времени. Исправление очень похоже на верное. Можно чуть-чуть сэкономить код, выделить переменную под объект PMenu, для которого далее делаются обе операции. Вроде вот этого:function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;
{$IFDEF DEBUG_MENU}var OK: Boolean; {$ENDIF}
var M: PMenu;
begin
Result := Items[ ItemToRemove ];
if Result = nil then Exit;
M := Result.FParentMenu;
if M = nil then M := Self;
{$IFDEF DEBUG_MENU} OK := {$ENDIF}
RemoveMenu( M.FHandle, Result.FId, MF_BYCOMMAND );
M.FMenuItems.Remove( Result );
......... -
Только M := @Self, конечно.
-
MTsv DN (07.12.09 21:46) [4]Всем привет...
В продолжение темы. Та же самая функция RemoveSubMenu. Помимо Count'а также не уменьшался FDynamicMenuID. Исправил для своих нужд вот так:function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;
{$IFDEF DEBUG_MENU}var OK: Boolean; {$ENDIF}
begin
Result := Items[ ItemToRemove ];
if Result = nil then Exit;
Dec( FDynamicMenuID );
if Result.FParentMenu <> nil then
begin
{$IFDEF DEBUG_MENU} OK := {$ENDIF}
RemoveMenu( Result.FParentMenu.FHandle, Result.FId, MF_BYCOMMAND );
Result.FParentMenu.FMenuItems.Remove( Result );
end
else
begin
{$IFDEF DEBUG_MENU} OK := {$ENDIF}
RemoveMenu( FHandle, Result.FId, MF_BYCOMMAND );
Self.FMenuItems.Remove( Result );
end;
{$IFDEF DEBUG_MENU}
if not OK then
ShowMessage( 'Error removing menu: ' + Int2Str( GetLastError ) + ' - ' +
SysErrorMessage( GetLastError ) );
{$ENDIF}
if Count = 0 then
begin
FDynamicMenuID := $1000;
Result.Free;
Result := nil;
end;
RedrawFormMenuBar;
end;
ВНИМАНИЕ!!! Это НЕ 100% фикс для RemoveSubMenu!!!
Т.к. возможна такая ситуация:
Есть три элемента меню, ID у них соответственно 4096, 4097, 4098, FDynamicMenuID при этом равно 4098, при удалении, например, второго элемента FDynamicMenuID станет 4097, и после добавления 4098, однако ID у элементов станут 4096, 4098, 4098...
З.Ы. Меня этот фикс устраивает, т.к. мне нужно лишь полностью чистить меню...
З.З.Ы. Ошибок при работе с меню уйма (имеется ввиду динамическое использование) -
Нельзя уменьшать FdynamicMenuID - это может привести к неожиданным последствиям, если меню несколько, и меняется не последнее. Я вообще не люблю динамические меню из-за этой дурости в их системной организации. Они как бы не предназначены для того, чтобы их все время динамически модифицировать - в конце концов уникальные ID могут кончиться. Или надо таблицу флажков держать - какие ID заняты, какие свободны. Но никто же так не делает.