![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа с меню...
MTsv DN © (2009-12-04 09:45:00)Всем привет...
В продолжении темы: http://delphimaster.ru/cgi-bin/forum.pl?id=1259759327&n=10
Появились некоторые вопросы по меню, видимо к Владимиру, хотя если у кого есть ответы, рад буду выслушать.
1. Почему Countсчитает всегда число элементов по всей глубине субменю?
З.Ы. Строчкаk := GetMenuItemCount(pm.Items[0].Parent.Handle);возвращает правильныйCount, т.ч. вопрос не актуален.
2. Почему при вызове RemoveSubMenuчисло Countне уменьшается. Вот это уже актуальный вопрос!!!
Vladimir Kladov (2009-12-07 21:54:00) [1]Нельзя уменьшать FdynamicMenuID - это может привести к неожиданным последствиям, если меню несколько, и меняется не последнее. Я вообще не люблю динамические меню из-за этой дурости в их системной организации. Они как бы не предназначены для того, чтобы их все время динамически модифицировать - в конце концов уникальные ID могут кончиться. Или надо таблицу флажков держать - какие ID заняты, какие свободны. Но никто же так не делает.
MTsv DN (2009-12-07 21:46:00) [2]Всем привет...
В продолжение темы. Та же самая функция 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...
З.Ы. Меня этот фикс устраивает, т.к. мне нужно лишь полностью чистить меню...
З.З.Ы. Ошибок при работе с меню уйма (имеется ввиду динамическое использование)
Vladimir Kladov (2009-12-05 08:03:00) [3]Только M := @Self, конечно.
Vladimir Kladov (2009-12-05 00:08:00) [4]Пока скопировал. Динамические меню не юзаю обычно. Разбираться нет времени. Исправление очень похоже на верное. Можно чуть-чуть сэкономить код, выделить переменную под объект 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 );
.........
MTsv DN (2009-12-04 17:32:00) [5]3. Ошибка в функции InsertSubMenu. Причину не нашел...см. http://delphimaster.ru/cgi-bin/forum.pl?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;