Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> События, Обработка событий в Delphi 
:(
    Опции темы
youri
Дата 21.4.2004, 20:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 740
Регистрация: 17.4.2004

Репутация: нет
Всего: 16



Люди! Кто-бы мне объяснил, такую штуку: что происходит, между вызовом метода формы Show и запуском обработчика события формы OnShow (и как я могу проследить цепочку вызовов в исходниках библиотек)
PM   Вверх
Cashey
Дата 21.4.2004, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бессмертный
****


Профиль
Группа: Завсегдатай
Сообщений: 3441
Регистрация: 13.11.2002
Где: в столице

Репутация: 2
Всего: 60



Метод Show всего лишь присваивает св-ву Visible значение true; а метод onShow позволяет произвести какие-то действия в этот момент (например: открыть таблицу или зделать неактивным какой-то компонент).
Отрабатывается между методами onCreate и onActivate

Это сообщение отредактировал(а) Cashey - 21.4.2004, 20:57


--------------------
библия учит любить ближнего, а камасутра обучает как именно
PM Jabber   Вверх
x77
Дата 21.4.2004, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1255
Регистрация: 25.3.2002

Репутация: 19
Всего: 22



ты можешь нажать Ctrl и левой кнопкой мыши щёлкнуть на нужный тебе метод, например, Show, и увидишь, как он работает. для Show ты увидишь:

Код

procedure TCustomForm.Show;
begin
 Visible := True;
 BringToFront;
end;


что делает BringToFront - очевидно из названия. следовательно, непосредственно показом занимается Visible := TRUE;

это возможно только при одном условии: установка свойства Visible происходит не напрямую, а через соотв. метод, типа SetVisible. так же щёлкаем, и смотрим:

Код

   property Visible write SetVisible default False;


идём в SetVisble. щёлканье здесь уже не поможет, так что проще сделать поиск. смотрим, где она объявлена - в TCustomForm. значит, Ctrl+F, TCustomForm.SetVisible. смотрим, что оно есть из себя:

Код

procedure TCustomForm.SetVisible(Value: Boolean);
begin
 if fsCreating in FFormState then
   if Value then
     Include(FFormState, fsVisible) else
     Exclude(FFormState, fsVisible)
 else
 begin
   if Value and (Visible <> Value) then SetWindowToMonitor;
   inherited Visible := Value;
 end;
end;

Первая половина занимается всякой сранью, вторая - связана с новомодной блудней: работой на нескольких мониторах. с версии 5.0 эта блудня поддерживается. остаётся что? inherited. очевидно, что видимой форму делает установка унаследованного свойства Visible. от чего унаследован TCustomForm? щёлкаем (всё также удерживая Ctrl) на ближайшее его упоминание, т.е. в заголовке процедуры, и видим:

Код

 TCustomForm = class(TScrollingWinControl)


ошень афигительно. Ctrl+F, TScrollingWinControl.SetVisible. и получаем балалайку. о чём это говорит? о том, что в TScrollingWinControl это свойство не менялось. значит, надо лезть к его предку, TWinControl. а там тож нифига нету. значит, TControl. делаем поиск и, наконец-то, получаем:
Код

procedure TControl.SetVisible(Value: Boolean);
begin
 if FVisible <> Value then
 begin
   VisibleChanging;
   FVisible := Value;
   Perform(CM_VISIBLECHANGED, Ord(Value), 0);
   RequestAlign;
 end;
end;

внимание привлекают две вещи: во-первых, VisibleChanging, во-вторых, Perform (..). смотрим по порядку.

VisibleChanging, объявленный как динамик, имеет очень умный код:
Код

procedure TControl.VisibleChanging;
begin
end;

о чём это говорит? о том, что на уровне контрола он нахрен не нужен, и объявлен динамическим для того, чтобы в методах потомков его можно было переопределить и выполнить в нём что-то осмысленное. значит, ищем его обратно по возрастающей. в TWinControl и TScrollingWinControl пусто. и только в TCustomForm находим:
Код

procedure TCustomForm.VisibleChanging;
begin
 if (FormStyle = fsMDIChild) and Visible then
   raise EInvalidOperation.Create(SMDIChildNotVisible);
end;

всё верно, для мди-окон видимость менять нельзя. значит, с эти разобрались, остаётся перформ. это функция, скармливающая окну сообщение api. ищем, где она объявлена, всё тем же кликаньем. находим в Controls.
Код

{ VCL control message IDs }
const
 ...
 CM_VISIBLECHANGED         = CM_BASE + 11;

т.е., это внутреннее сообщение дельфей, а не апишная функция. значит, надо выяснить, что предки формы делают, получая это сообщение. да здравствует поиск! имеем:
Код

procedure TControl.WndProc(var Message: TMessage);
var
 Form: TCustomForm;
begin
 if (csDesigning in ComponentState) then
 begin
   Form := GetParentForm(Self);
   if (Form <> nil) and (Form.Designer <> nil) and
     Form.Designer.IsDesignMsg(Self, Message) then Exit;
 end
 else if (Message.Msg >= WM_KEYFIRST) and (Message.Msg <= WM_KEYLAST) then
 begin
   Form := GetParentForm(Self);
   if (Form <> nil) and Form.WantChildKey(Self, Message) then Exit;
 end
 else if (Message.Msg >= WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) then
 begin
   if not (csDoubleClicks in ControlStyle) then
     case Message.Msg of
       WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK:
         Dec(Message.Msg, WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
     end;
   case Message.Msg of
     WM_MOUSEMOVE: Application.HintMouseMessage(Self, Message);
     WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
       begin
         if FDragMode = dmAutomatic then
         begin
           BeginAutoDrag;
           Exit;
         end;
         Include(FControlState, csLButtonDown);
       end;
     WM_LBUTTONUP:
       Exclude(FControlState, csLButtonDown);
   end;
 end
[b]  else if Message.Msg = CM_VISIBLECHANGED then[/b]
   with Message do
     SendDockNotification(Msg, WParam, LParam);
 Dispatch(Message);
end;
...
procedure TDockTree.WindowProc(var Message: TMessage);

 procedure CalcSplitterPos;
 var
   MinWidth,
   TestLimit: Integer;
 begin
   MinWidth := FGrabberSize;
   if (FSizingZone.FParentZone.FOrientation = doHorizontal) then
   begin
     TestLimit := FSizingZone.Top + MinWidth;
     if FSizePos.y <= TestLimit then FSizePos.y := TestLimit;
     TestLimit := GetNextLimit(FSizingZone) - MinWidth;
     if FSizePos.y >= TestLimit then FSizePos.y := TestLimit;
   end
   else begin
     TestLimit := FSizingZone.Left + MinWidth;
     if FSizePos.x <= TestLimit then FSizePos.x := TestLimit;
     TestLimit := GetNextLimit(FSizingZone) - MinWidth;
     if FSizePos.x >= TestLimit then FSizePos.x := TestLimit;
   end;
 end;

const
 SizeCursors: array[TDockOrientation] of TCursor = (crDefault, crVSplit, crHSplit);
var
 TempZone: TDockZone;
 Control: TControl;
 P: TPoint;
 R: TRect;
 HitTestValue: Integer;
 Msg: TMsg;
begin
 case Message.Msg of
   CM_DOCKNOTIFICATION:
     with TCMDockNotification(Message) do
[b]        if (NotifyRec.ClientMsg = CM_VISIBLECHANGED) then[/b]
         ControlVisibilityChanged(Client, Boolean(NotifyRec.MsgWParam));
   WM_MOUSEMOVE:
     if FSizingZone <> nil then
     begin
       DrawSizeSplitter;
       FSizePos := SmallPointToPoint(TWMMouse(Message).Pos);
       CalcSplitterPos;
       DrawSizeSplitter;
     end;
   WM_LBUTTONDBLCLK:
     begin
       TempZone := InternalHitTest(SmallPointToPoint(TWMMouse(Message).Pos),
         HitTestValue);
       if TempZone <> nil then
         with TempZone do
           if (FChildControl <> nil) and (HitTestValue = HTCAPTION) then
           begin
             CancelDrag;
             FChildControl.ManualDock(nil, nil, alTop);
           end;
     end;
   WM_LBUTTONDOWN:
     begin
       P := SmallPointToPoint(TWMMouse(Message).Pos);
       TempZone := InternalHitTest(P, HitTestValue);
       if (TempZone <> nil) then
       begin
         if HitTestValue = HTBORDER then
           SplitterMouseDown(TempZone, P)
         else if HitTestValue = HTCAPTION then
         begin
           if (not PeekMessage(Msg, FDockSite.Handle, WM_LBUTTONDBLCLK,
             WM_LBUTTONDBLCLK, PM_NOREMOVE)) and
             (TempZone.FChildControl is TWinControl) then
             TWinControl(TempZone.FChildControl).SetFocus;
    if (TempZone.FChildControl.DragKind = dkDock) and
             (TempZone.FChildControl.DragMode = dmAutomatic)then
               TempZone.FChildControl.BeginDrag(False);
    Exit;
         end;
       end;
     end;
   WM_LBUTTONUP:
     if FSizingZone = nil then
     begin
       P := SmallPointToPoint(TWMMouse(Message).Pos);
       TempZone := InternalHitTest(P, HitTestValue);
       if (TempZone <> nil) and (HitTestValue = HTCLOSE) then
       begin
         if TempZone.FChildControl is TCustomForm then
           TCustomForm(TempZone.FChildControl).Close
         else
           TempZone.FChildControl.Visible := False;
       end;
     end
     else
       SplitterMouseUp;
   WM_SETCURSOR:
     begin
       GetCursorPos(P);
       P := FDockSite.ScreenToClient(P);
       with TWMSetCursor(Message) do
         if (Smallint(HitTest) = HTCLIENT) and (CursorWnd = FDockSite.Handle)
           and (FDockSite.VisibleDockClientCount > 0) then
         begin
           TempZone := InternalHitTest(P, HitTestValue);
           if (TempZone <> nil) and (HitTestValue = HTBORDER) then
           begin
             Windows.SetCursor(Screen.Cursors[SizeCursors[TempZone.FParentZone.FOrientation]]);
             Result := 1;
             Exit;
           end;
         end;
     end;
   CM_HINTSHOW:
     with TCMHintShow(Message) do
     begin
       FOldWndProc(Message);
       if Result = 0 then
       begin
         Control := HitTest(HintInfo^.CursorPos, HitTestValue);
         if HitTestValue = HTBORDER then
           HintInfo^.HintStr := ''
         else if (Control <> nil) and (HitTestValue in [HTCAPTION, HTCLOSE]) then
         begin
           R := Control.BoundsRect;
           AdjustDockRect(Control, R);
           Dec(R.Left, 2 * (R.Left - Control.Left));
           Dec(R.Top, 2 * (R.Top - Control.Top));
           Dec(R.Right, 2 * (Control.Width - (R.Right - R.Left)));
           Dec(R.Bottom, 2 * (Control.Height - (R.Bottom - R.Top)));
           HintInfo^.HintStr := Control.Caption;
           HintInfo^.CursorRect := R;
         end;
       end;
       Exit;
     end;
 end;
 FOldWndProc(Message);
end;
...
procedure TCustomDockForm.CMDockNotification(var Message: TCMDockNotification);
var
 S: string;
 I: Integer;
begin
 inherited;
 case Message.NotifyRec^.ClientMsg of
[b]    CM_VISIBLECHANGED: Visible := Message.Client.Visible;[/b]
   WM_SETTEXT:
     begin
       SetString(S, nil, Message.Client.GetTextLen + 1);
       Message.Client.GetTextBuf(PChar(S), Length(S));
       { Search for first CR/LF and end string there }
       for I := 1 to Length(S) do
         if S[I] in [#13, #10] then
         begin
           SetLength(S, I - 1);
           Break;
         end;
       Caption := S;
     end;
 end;
end;
...


так, сорри, зовут на пьянку. в общем, смотришь обработчки в исходниках, и делаешь выводы.

альтернативный вариант: пляшешь от самого OnShow. там будет процедурина, типа DoShow, if Assigned (fOnShow) then OnShow (Self) ну и т.д.

третий вариант: вызываешь справку. иногда там написано, в какой последовательности происходят события. может быть полезно, чтобы сориентироваться.

если не разберёшься, я завтра конкретно отвечу.

а вообще - ты молодец. если бы местная братва почаще задавалась детским вопросом "а как оно, собственно, работает?", - половины дебильных вопросов на этом форуме бы не было. так что у тебя есть реальный шанс стать нормальным думающим программером ;)


--------------------
Я никогда не сопротивлялся искушению, поскольку узнал: что мне
не нравится, то меня не искушает.
© Джордж Бернард Шоу (Ирландия)
PM MAIL ICQ   Вверх
x77
Дата 21.4.2004, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1255
Регистрация: 25.3.2002

Репутация: 19
Всего: 22



Cashey, OnShow - это не метод ;)



--------------------
Я никогда не сопротивлялся искушению, поскольку узнал: что мне
не нравится, то меня не искушает.
© Джордж Бернард Шоу (Ирландия)
PM MAIL ICQ   Вверх
Cashey
Дата 21.4.2004, 21:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бессмертный
****


Профиль
Группа: Завсегдатай
Сообщений: 3441
Регистрация: 13.11.2002
Где: в столице

Репутация: 2
Всего: 60



Да, это событие. Да и ладно smile.gif Лишь бы форму открывал biggrin.gif


--------------------
библия учит любить ближнего, а камасутра обучает как именно
PM Jabber   Вверх
x77
Дата 21.4.2004, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1255
Регистрация: 25.3.2002

Репутация: 19
Всего: 22



это не событие. это свойство. процедурного типа tounge.gif


--------------------
Я никогда не сопротивлялся искушению, поскольку узнал: что мне
не нравится, то меня не искушает.
© Джордж Бернард Шоу (Ирландия)
PM MAIL ICQ   Вверх
youri
Дата 22.4.2004, 08:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 740
Регистрация: 17.4.2004

Репутация: нет
Всего: 16



Спасибо, x77. Было интересно почитать. smile.gif
Не мог оторваться: звали на пъянку - не пошел. (шутка)
Цитата
сорри, зовут на пьянку

Пока до конца не разобрался, так что может еще спрошу что-нибудь.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.2170 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.