![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Динамический OnClick [D6]
msguns © (2005-11-02 18:28:00)В рантайме создается TPopUpMenu с соответствующими итемами. Как назначить событию OnClick этих итемов ругулярные процедуры ?
Все происходит в библиотечном юните, где нет type
Спасибо за помощь
Экспериментатор (2005-11-05 12:20:00) [1]в догонку:
при создании Menu добавляется в PopupList
при уничтожении - удаляется,
И вот часть оконной процедуры объекта TPopupList
procedure TPopupList.WndProc(var Message: TMessage);
var
I, Item: Integer;
MenuItem: TMenuItem;
FindKind: TFindItemKind;
ContextID: Integer;
Canvas: TCanvas;
SaveIndex: Integer;
DC: HDC;
begin
case Message.Msg of
WM_COMMAND:
for I := 0 to Count - 1 do
if TPopupMenu(Items[I]).DispatchCommand(Message.wParam) then Exit;
WM_INITMENUPOPUP:
for I := 0 to Count - 1 do
with TWMInitMenuPopup(Message) do
if TPopupMenu(Items[I]).DispatchPopup(MenuPopup) then Exit;
WM_MENUSELECT:
with TWMMenuSelect(Message) do
begin
FindKind := fkCommand;
if MenuFlag and MF_POPUP <> 0 then FindKind := fkHandle;
for I := 0 to Count - 1 do
begin
if FindKind = fkHandle then
begin
if Menu <> 0 then
Item := GetSubMenu(Menu, IDItem) else
Item := -1;
end
else
Item := IDItem;
MenuItem := TPopupMenu(Items[I]).FindItem(Item, FindKind);
if MenuItem <> nil then
begin
Application.Hint := GetLongHint(MenuItem.Hint);
Exit;
end;
end;
Application.Hint := '';
end;
и т.д.
Делай выводы
Экспериментатор (2005-11-05 12:03:00) [2]Сделай в initialization модуля создание PopupMenu
в finalization - его Free
а в своих функциях используй его следующим образом:
сначала Очищай Items , потой его заполняй новыми пунктами и присваивай им обработчики, никаких Free после при вызова Popup нельзя делать.
Посмотри внимательно на procedure TPopupMenu.Popup(X, Y: Integer);
в нем вызывается
TrackPopupMenu(FItems.Handle, AFlags, X, Y, 0 { reserved }, PopupList.Window, nil);
как ты думаешь для чего?
Leonid Troyanovsky (2005-11-03 16:51:00) [3]
> Leonid Troyanovsky © (03.11.05 16:45) [29]
> Для этого упомянутый прообраз снабжается неким индексированным
> свойством (постой-ка, а почему это не TColumn.Visible?),
> которое
> устанавливается посредством некоего action, назначаемоего
А.. да. Еще необходимо сделать обработчик клика на заголовке.
Создание симбиоза с меню, которое будет всплывать при
клике на оном - факультативно.
Ну, и , конечно, свойство - ShowPopupMenuBelow(Above).
--
Regards, LVT.
jack128 (2005-11-03 16:51:00) [4]evvcom © (03.11.05 16:42) [28]
if Assigned(FOnClick) и посмотри, чему он там равен. Наверняка nil.
До туда код тоже не дойдет. Когда придет WM_COMMAND форма полезет искать меню с соответствующим ID'шником, чтобы вызвать его Click, но так как меню уже будет уничтожено, то форма ничего не найдет. На этом дело и заглохнет..
Leonid Troyanovsky (2005-11-03 16:45:00) [5]
> msguns © (03.11.05 16:34) [27]
> Это не обработчик меню, а набор функций (процедур) для манипулирования
> гридами и данными в этих гридах. В частности, процедуры
> удаления-добавления колонок в дбгрид, сохранения-восстановления
> текущей конфигурации грида, поиска-сортировки, вывода Excel
> содержимого отображенных полей датасета, подсчета сумм по
> колонке и т.д., т.п.
Все перечисленное свидельствует лишь в пользу создания некоего
прообраза, от которого и будут наследоваться все используемые гриды.
> В одной из процедур я хотел сделать "прятание"-показ колонок
> через меню непосредственно под/над "кликнутым" заголовком,
> с помощью которого юзер может либо спрятать текущую (кликнутую)
> колонку, либо добавить в этом месте одну из "спрятанных".
<нудно>
Для этого упомянутый прообраз снабжается неким индексированным
свойством (постой-ка, а почему это не TColumn.Visible?), которое
устанавливается посредством некоего action, назначаемоего некоему мню.
</нудно>
--
Regards, LVT.
evvcom (2005-11-03 16:42:00) [6]У тебя похоже где-то что-то перетирается или не туда записывается. Включи использование отладочных DCU, поставь бряк на if Assigned(FOnClick) и посмотри, чему он там равен. Наверняка nil.
msguns (2005-11-03 16:34:00) [7]>Leonid Troyanovsky © (03.11.05 15:08) [26]
>И где тут универсализация?
В данном случае ее сделать и не получилось
>А сделать универсальный обработчик меню на все случаи жизни,
все равно, особого смысла не имеет.
Это не обработчик меню, а набор функций (процедур) для манипулирования гридами и данными в этих гридах. В частности, процедуры удаления-добавления колонок в дбгрид, сохранения-восстановления текущей конфигурации грида, поиска-сортировки, вывода Excel содержимого отображенных полей датасета, подсчета сумм по колонке и т.д., т.п.
В одной из процедур я хотел сделать "прятание"-показ колонок через меню непосредственно под/над "кликнутым" заголовком, с помощью которого юзер может либо спрятать текущую (кликнутую) колонку, либо добавить в этом месте одну из "спрятанных".
Leonid Troyanovsky (2005-11-03 15:08:00) [8]
> msguns © (03.11.05 14:05) [25]
> Перенес процедуру
> в рабочий проект и решил проблему. Жаль, что не вышло с
> укиверсализацией, позже подумаю..
И где тут универсализация?
Если используемые гриды нуждаются в симбиозе с меню,
то, IMHO, следует сделать их наследниками одного прообраза.
А сделать универсальный обработчик меню на все случаи жизни,
все равно, особого смысла не имеет.
Во всяком случае, пользы от этого будет куда меньше,
чем, скажем, от механизма Actions.
--
Regards, LVT.
msguns (2005-11-03 14:05:00) [9]>jack128 © (03.11.05 13:52) [22]
>Приведи dfm и pas файлы с НЕрабочем вариантом.
Они шибко большие.
Ладно, спасибо всем за участие и сочувствие. Перенес процедуру в рабочий проект и решил проблему. Жаль, что не вышло с укиверсализацией, позже подумаю..
jack128 (2005-11-03 14:03:00) [10]Ты можешь сделать такой вариант, чтобы я всавил код, нажал f9 и выледз твой глюк ??
msguns © (03.11.05 13:54) [23]
то до AV меню раскроется и на клик реакции не будет
Естественно не будет. Меню то уже будет уничтожено.
msguns (2005-11-03 13:54:00) [11]Вот полный текст процедуры в варианте с визуальным меню:
procedure TfrmChild.ShowHideGridColumn(Grid: TDBGrid; TitleColumn: TColumn);
// Позволяет добавить или убрать колонку грида
// Вызов этой процедуры следует выполнять по событию OnTitleClick грида
var
pmi: TMenuItem;
X,Y: integer;
i: integer;
m: TMethod;
begin
// Определить текущую колонку грида
LoadHideColumns(Grid,ListColumns);
with pmnuGridCol do
begin
Items.Clear;
pmi := TMenuItem.Create(pmnuGridCol);
pmi.Caption := 'Убрать колонку';
pmi.OnClick := mniDelColClick;
Items.Add(pmi);
if ListColumns.Count>0 then
begin // Создать второй пункт меню
pmi := TMenuItem.Create(pmnuGridCol);
pmi.Caption := 'Добавить колонку';
Items.Add(pmi);
for i := 0 to ListColumns.Count-1 do
begin
pmi := TMenuItem.Create(pmnuGridCol);
pmi.Caption := PColDef(ListColumns[i])^.ColName;
pmi.OnClick := mniDelColClick;
Items[Items.Count-1].Add(pmi);
end;
end;
// Открыть меню под (над) заголовком колонки
with TDBGridCrack(Grid) do
Y := Grid.ClientOrigin.Y+CellRect(Col,Row).Bottom-CellRect(Col,Row).Top;
X := Grid.ClientOrigin.X;
for i := 0 to TitleColumn.Index-1 do
if Grid.Columns[i].Visible then
X := X+Grid.Columns[i].Width+1;
Popup(X,Y);
//Free;
end;
end;
СтрокаFreeкак ты понимаешь, осталась от варианта с динамическим меню. Если ее откомментарить, то до AV меню раскроется и на клик реакции не будет. В приведенном же виде реакция есть.
Это один из непонятных мне моментов. Другой заключался в отказе при замене обработчика на аналогичный. Все равно когда, в дизайне или в рантайме.
jack128 (2005-11-03 13:52:00) [12]Приведи dfm и pas файлы с НЕрабочем вариантом.
Игорь Шевченко (2005-11-03 13:47:00) [13]msguns © (03.11.05 13:35) [20]
Что в моем коде отличается от твоего ? Я создаю динамически элемент PopupMenu (MenuItem), динамически же присваиваю ему событие на свойство OnClick, все работает.
Может быть, ты по шагам будешь двигаться, так оно и выяснится, что и где ты делаешь не так.
msguns (2005-11-03 13:35:00) [14]>Игорь Шевченко © (03.11.05 13:20) [19]
>Если не трудно, тоже самое, но без слесарных терминов
Вот какие мы серьезные ;))
Дело в том, что все работает (имеется в виду то, что нажатие на левую кл.мыши благополучно попадает в обработчик OnClick пункта меню), если я сам это обработчик получил "даблкликом" в OI
При этом не играет роли, какойобъект TPopupMenu я задействую в своей процедуре: тот, который визуально "положен" на форму либо созданный динамически в самой процедуре.
Но как только я сменил обработчик (неважно как, то ли в OI, то ли в коде), обработчик на это событие не реагирует.
Игорь Шевченко (2005-11-03 13:20:00) [15]msguns © (03.11.05 13:14) [18]
Если не трудно, тоже самое, но без слесарных терминов
msguns (2005-11-03 13:14:00) [16]>Игорь Шевченко © (03.11.05 12:56) [17]
>И назначить его тому компоненту, при клике на который должно всплывать меню....
Все значительно интереснее...
Значицца такочки:
1. Кидаю на форму пупменю, определяю в ем один пункт и для это пункта в OI даблкликомопределяю обработчик Click1.
В процедуре чищу и заполняю это меню, назначая пунктам OnClick := Click1.
Запускаю - на ура !
2. В процедуре вместо "кинутого" пупменю создаю пупменю2, для него проделываю то же самое. Запускаю - лейся, песня !
Ага !, подумал Штирлиц, нащупав наган. Создаю ручками обработчик Click2, полностью идентичный Click1.
В проце заменяюOnClick := Click1наOnClick := Click2
Запускаю - болт ! Убираю пупап2, вставляю вместо него "кинутый" пупап.
Запускаю - БОЛТ !
В OI заменяю (выбором из списка) Click1 на Click2 - БОЛТ !В обоих вариантах !!!. Возвращаю Click1 - БОЛТ
Что ж это делается-то, люди добрые ? А ?
Игорь Шевченко (2005-11-03 12:56:00) [17]
> СтОит же мне попытаться создать попменю динамически
И назначить его тому компоненту, при клике на который должно всплывать меню....
msguns (2005-11-03 12:51:00) [18]Видимо все же дело в "перехватчике" сообщения клика. Стоп !!! Щас попробую...
msguns (2005-11-03 12:43:00) [19]В общем получается интересная весчь.
Если я кидаю на форму попменю, в нем определяю оно подменю и ему создаю OnClick, а затем в процедуре чищу, заполняю нужными итемами и назначаю им этот же обработчик, то все лихо пляшет !
СтОит же мне попытаться создать попменю динамически и проделать с ним то же самое, но с регулярной процедурой (или даже тем же самым обработчиком), как реакции на клик просто нетути.
Блин, явно не хватает понимания чего-то фундаментального ;))
msguns (2005-11-03 12:36:00) [20]>Игорь Шевченко © (03.11.05 11:30) [8]
Прошу прощения, невнимательно посмотрел (почта задрала !)
В твоем примере само TPopupMenu объявлено в интерфейсе, у меня же такого объявления быть не может ;(
Сейчас плюнул на универсальность и делаю все в самом приложении. И та же картина ! На клик реакции нету !
Уже пробовал в форме объявить обработчик клика на пункте меню и его назначить динамически созданным пунктам динамически созданного же попменю - реакции НОЛЬ ! При клике в меню просто оно закрывается, а до моего обработчика дело не доходит ;((