Текущий архив: 2003.01.23;
Скачать: CL | DM;
Вниз
Не пойму в чем проблема Найти похожие ветки
← →
zxz (2003-01-12 13:23) [0]Привет всем.
добавил в наследника от TPanel события на отслеживание мышки
код:
TSGPanel = class(TPanel)
private
{ Private declarations }
FOnMouseEnter: TNotifyEvent;
FOnMouseLeave: TNotifyEvent;
procedure CMMouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
protected
{ Protected declarations }
procedure DoMouseEnter; dynamic;
procedure DoMouseLeave; dynamic;
public
{ Public declarations }
published
{ Published declarations }
property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter;
property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
end;
implementation
procedure TSGPanel.CMMouseEnter(var Msg: TMessage);
begin
inherited;
if FMouseReaction then DoMouseEnter;
end;
procedure TSGPanel.CMMouseLeave(var Msg: TMessage);
begin
inherited;
if FMouseReaction then DoMouseLeave;
end;
procedure TSGPanel.DoMouseEnter;
begin
if Assigned(FOnMouseEnter) then FOnMouseEnter(Self);
end;
procedure TSGPanel.DoMouseLeave;
begin
if Assigned(FOnMouseLeave) then FOnMouseLeave(Self);
end;
Тут вроде все нормально. В программе динамически создаю обыкновеные панели (TPanel) код:
...
const
MAX_CHANNELS = 24;
...
var
PanelList: array [0..MAX_CHANNELS] of TPanel;
...
for i := 0 to MAX_CHANNELS do
begin
PanelList[i] := TPanel.Create(Self);
PanelList[i].Parent := Self;
PanelList[i].Tag := i;
PanelList[i].OnDblClick := MyPanelDblClick;
PanelList[i].BevelInner := bvRaised;
PanelList[i].BevelOuter := bvLowered;
.... и т.д.
end;
Тут вроде бы тоже все нормально. Панели соответственно при необходимости прибиваю код:
for i := 0 to MAX_CHANNELS do
begin
if Assigned(PanelList[i]) then
begin
PanelList[i].Free;
PanelList[i] := nil;
end
else Break;
end;
Тут тоже как бы все нормально. При вызове процедур создания и удаления панелей из любого места программы все отрабатывает нормально (без ошибок), но как только я вызываю процедуру удаления панелей из события OnMouseLeave новой панели (TSGPanel) она отрабатывает нормально но затем возникает ошибка:
Exception EAccessViolation ...
Не могу понять в чем дело, помогите кто может!
← →
Юрий Зотов © (2003-01-12 13:31) [1]Похоже, ошибка возникает при обратной раскрутке стека вызовов. Попробуйте сделать отложенное удаление панели - процедура удаления через PostMessage (но не SendMessage) посылает форме сообщение WM_USER и в параметре передает индекс панели, а уже в обработчике этого сообщения панель убивается и очищается ссылка на нее.
← →
zxz (2003-01-12 14:28) [2]2 Юрий Зотов спасибо все заработало, сам бы я не справился!
Но с событиями OnMouseEnter и OnMouseLeave вот ведь еще какая штука: Если на панели TSGPanel расположены еще визуальные элементы (кнопки, метки и т.п.) то события OnMouseEnter и OnMouseLeave происходят когда мышь попадает и на них хотя визуально указатель мыши находится в пределах панели. Это конечно правильно так и должно быть, но хотелось бы каким-то образом отслеживать - мышь над панелью или нет. Я добавлял следующий код:
procedure TSGPanel.DoMouseLeave;
var
Point: TPoint;
Rect: TRect;
begin
GetCursorPos(Point);
Point := ScreenToClient(Point);
Rect := WideRect(Left+1, Top+1, Width-2, Height-2);
//Проверка принадлежит ли точка прямоугольной области
if not PointInRect (Point, Rect) then
if Assigned(FOnMouseLeave) then FOnMouseLeave(Self);
end;
Вроде бы работает (может есть способ по изящней???). Но если шелкнуть по кнопке расположенной на панели TSGPanel и вызвать например всплывающее меню, то событие OnMouseLeave происходит раньше чем вызывается обработчик OnMenuItemClic, так как окно меню выходит за пределы панели (панель узкая). Возможно ли изменить порядок вызовов обработчиков - сначала OnMenuItemClic, а затем OnMouseLeave ???
← →
Юрий Зотов © (2003-01-12 15:43) [3]В обработчике OnPopup можно выставить логический флаг, а в DoMouseLeave проверять его и если он выставлен, то ничего не делать - тогда при показанном меню OnMouseLeave не вызовется.
Соответственно, в обработчике клика по пункту меню надо этот флаг сбросить и вызвать DoMouseLeave вручную. Вот и получится - сначала OnMenuItemClick, а затем OnMouseLeave.
← →
zxz (2003-01-12 16:15) [4]2 Юрий Зотов насчет использования OnPopup спасибо (правда я уже сделал нечто аналогичное).
Возможно ли осушествить следующий механизм: если указатель мыши выходит за пределы панели и через небольшое время опять возвращается на панель (в пределах например 1с), то не выполнять обработчик OnMouseLeave???
и вдогонку панель (TSGPanel) по событию OnMouseLeave у меня как бы прячется (перемещается влево за пределы формы), на ее место соответственно растягивается другая панель (занимает всю клиентскую часть формы). На ней и распологаются как раз те панели которые я создаю динамически, причем они равномерно занимают всю область панели. Возникает вопрос как вернут панель TSGPanel обратно, так как события мыши перехватывают дочерние панельки, как грамотно вернуть панель обратно ??? (SetCapture или Hook или еще чего нибудь?)
← →
Юрий Зотов © (2003-01-12 17:24) [5]1. Дык... по уходу мыши включайте таймер. Обработчик OnLeave повесьте и на OnTimer, пусть выполняет двойную нагрузку. А в самом OnLeave и в OnEnter - выключайте таймер.
2. Прицепите возврат панели к чему угодно - кнопке, любому MouseMove и т.д. Или на WM_NCHITTEST формы (c HTLEFT).
Страницы: 1 вся ветка
Текущий архив: 2003.01.23;
Скачать: CL | DM;
Память: 0.48 MB
Время: 0.017 c