GUITesting.pas
上传用户:yjb1804
上传日期:2021-01-30
资源大小:3105k
文件大小:18k
源码类别:

Email服务器

开发平台:

Delphi

  1. { #(@)$Id: GUITesting.pas,v 1.36 2006/07/19 02:45:54 judc Exp $ }
  2. {: DUnit: An XTreme testing framework for Delphi programs.
  3.    @author  The DUnit Group.
  4.    @version $Revision: 1.36 $ 2001/03/08 uberto
  5. }
  6. (*
  7.  * The contents of this file are subject to the Mozilla Public
  8.  * License Version 1.1 (the "License"); you may not use this file
  9.  * except in compliance with the License. You may obtain a copy of
  10.  * the License at http://www.mozilla.org/MPL/
  11.  *
  12.  * Software distributed under the License is distributed on an "AS
  13.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  14.  * implied. See the License for the specific language governing
  15.  * rights and limitations under the License.
  16.  *
  17.  * The Original Code is DUnit.
  18.  *
  19.  * The Initial Developers of the Original Code are Serge Beaumont
  20.  * and Juancarlo A馿z.
  21.  * Portions created The Initial Developers are Copyright (C) 1999-2000.
  22.  * Portions created by The DUnit Group are Copyright (C) 2000-2004.
  23.  * All rights reserved.
  24.  *
  25.  * Contributor(s):
  26.  * Serge Beaumont <beaumose@iquip.nl>
  27.  * Juanco A馿z <juanco@users.sourceforge.net>
  28.  * Uberto Barbini <uberto@usa.net>
  29.  * Kris Golko <neuromancer@users.sourceforge.net>
  30.  * Jon Bertrand <jonbsfnet@users.sourceforge.net>
  31.  * The DUnit group at SourceForge <http://dunit.sourceforge.net>
  32.  *
  33.  *)
  34. {$IFDEF LINUX}
  35. {$DEFINE DUNIT_CLX}
  36. {$ENDIF}
  37. unit GUITesting;
  38. interface
  39. uses
  40.   TestFramework,
  41. {$IFDEF LINUX}
  42.   Types,
  43. {$ELSE}
  44.   Windows,
  45.   Messages,
  46. {$ENDIF}
  47. {$IFDEF DUNIT_CLX}
  48.   Qt,
  49.   QControls,
  50.   QForms,
  51. {$ELSE}
  52.   Controls,
  53.   Forms,
  54. {$ENDIF}
  55.   SysUtils,
  56.   Classes;
  57. const
  58.   rcs_id: string = '#(@)$Id: GUITesting.pas,v 1.36 2006/07/19 02:45:54 judc Exp $';
  59. {$IFDEF DUNIT_CLX}
  60. const
  61.   VK_F8 = Key_F8;
  62.   VK_F9 = Key_F9;
  63.   VK_END = Key_End;
  64.   VK_TAB = KEY_TAB;
  65.   VK_BACK = Key_Backspace;
  66. {$ENDIF}
  67. type
  68.   TGUITestCase = class(TTestCase)
  69.   public
  70.     constructor Create(MethodName :string); override;
  71.     destructor  Destroy; override;
  72.     procedure TearDown; override;
  73.   protected
  74.     FGUI         :TControl; // this is the control we're testing
  75.     FActionDelay :Integer;
  76.     function  FindControl(Comp: TComponent; const CtlName: string; Addrs :Pointer = nil): TControl; overload;
  77.     function  FindControl(const AName: string; Addrs :Pointer = nil): TControl;                      overload;
  78.     function  FindParentWinControl(Control :TControl):TWinControl;
  79. {$IFNDEF DUNIT_CLX}
  80.     { Windows specific keyboard state code }
  81.     procedure SetKeyboardStateDown(pControl : TWinControl; pShiftState: TShiftState);
  82.     procedure SetKeyboardStateUp(pControl: TWinControl; pShiftState: TShiftState);
  83. {$ENDIF}
  84.     procedure ClickLeftMouseButtonOn(Control: TControl);
  85.     procedure Click;                      overload;
  86.     procedure Click(ControlName :string); overload;
  87.     procedure Click(control :TControl);   overload;
  88.     procedure EnterKey(Key :Word; const ShiftState :TShiftState = []); overload;
  89.     procedure EnterKeyInto(Control :TControl;   Key :Word; const ShiftState :TShiftState = []); overload;
  90.     procedure EnterKeyInto(ControlName :string; Key :Word; const ShiftState :TShiftState = []); overload;
  91.     procedure EnterKey(Key :Char; const ShiftState :TShiftState = []); overload;
  92.     procedure EnterKeyInto(Control :TControl;   Key :Char; const ShiftState :TShiftState = []); overload;
  93.     procedure EnterKeyInto(ControlName :string; Key :Char; const ShiftState :TShiftState = []); overload;
  94.     procedure EnterText(Text :string);
  95.     procedure EnterTextInto(Control :TControl;   Text :string); overload;
  96.     procedure EnterTextInto(ControlName :string; Text :string); overload;
  97.     procedure Show(OnOff :boolean = true);                      overload;
  98.     procedure Show(Control :TControl; OnOff :boolean = true);   overload;
  99.     procedure Show(ControlName :string; OnOff :boolean = true); overload;
  100.     procedure Hide;                      overload;
  101.     procedure Hide(Control :TControl);   overload;
  102.     procedure Hide(ControlName :string); overload;
  103.     procedure Tab(n :Integer =1);
  104.     procedure CheckTabTo(Control :TControl; Addrs :Pointer = nil); overload;
  105.     procedure CheckTabTo(ControlName :string);                    overload;
  106.     function  GetFocused :TControl;
  107.     function  IsFocused(Control : TControl) : boolean;
  108.     procedure SetFocus(Control :TControl; Addrs :Pointer = nil); overload;
  109.     procedure SetFocus(ControlName :string);                    overload;
  110.     procedure CheckFocused(Control :TControl; Addrs :Pointer = nil); overload;
  111.     procedure CheckFocused(ControlName :string);                    overload;
  112.     procedure CheckEnabled(Control :TControl; Addrs :Pointer = nil);  overload;
  113.     procedure CheckEnabled(ControlName :string);                     overload;
  114.     procedure CheckVisible(Control :TControl; Addrs :Pointer = nil);  overload;
  115.     procedure CheckVisible(ControlName :string);                     overload;
  116.     procedure CheckVisible;                                          overload;
  117.     property GUI :TControl read FGUI write FGUI;
  118.     property ActionDelay :Integer  read FActionDelay write FActionDelay;
  119.   end;
  120. implementation
  121. // assertions are always on so we can check for own consistency
  122. {$ASSERTIONS ON}
  123. // need stack frames to use CallerAddr
  124. {$STACKFRAMES ON}
  125. { TGUITestCase }
  126. constructor TGUITestCase.Create(MethodName :string);
  127. begin
  128.   inherited Create(MethodName);
  129.   FActionDelay := 100;
  130. end;
  131. destructor TGUITestCase.Destroy;
  132. begin
  133.   FGUI.Free;
  134.   inherited Destroy;
  135. end;
  136. procedure TGUITestCase.TearDown;
  137. begin
  138.   inherited TearDown;
  139.   FGUI.Free;
  140.   FGUI := nil;
  141. end;
  142. function TGUITestCase.FindControl(Comp: TComponent; const CtlName: string; Addrs :Pointer): TControl;
  143.   function DoFind(C :TComponent; const CName :string) :TControl;
  144.   var
  145.     i: Integer;
  146.   begin
  147.     Result := nil;
  148.     i := 0;
  149.     while (Result = nil) and (i < C.ComponentCount) do
  150.     begin
  151.       with C do
  152.       begin
  153.         if (Components[i] is TControl)
  154.         and (UpperCase(Components[i].Name) = CName) then
  155.           Result := Components[I] as TControl
  156.         else
  157.           Result := DoFind(Components[I], CName);
  158.       end;
  159.       Inc(i);
  160.     end;
  161.   end;
  162. begin
  163.   if Addrs = nil then
  164.     Addrs := CallerAddr;
  165.   if Trim(CtlName) = '' then
  166.     Fail('No control name', Addrs);
  167.   Result := DoFind(Comp, UpperCase(CtlName));
  168.   if Result = nil then
  169.     Fail( Format('Control named "%s" not found in %s',
  170.                   [CtlName, Screen.ActiveForm.Name])
  171.     );
  172. end;
  173. procedure TGUITestCase.ClickLeftMouseButtonOn(Control: TControl);
  174. var
  175. {$IFDEF DUNIT_CLX}
  176.   P: TPoint;
  177.   evMouse: QMouseEventH;
  178. {$ELSE}
  179.   P: TSmallPoint;
  180. {$ENDIF}
  181. begin
  182.   Assert(Control <> nil, 'No control');
  183.   Control := FindParentWinControl(Control);
  184.   if Control <> nil then
  185.   begin
  186.     {:@ todo consider if this method should have X,Y parameters.
  187.       @todo This doesn't work if the original control is not a TWinControl and is not in
  188.        the middle of its parent. }
  189. {$IFDEF DUNIT_CLX}
  190.     P := Point(Control.Width  div 2, Control.Height div 2);
  191.     evMouse := QMouseEvent_create(QEventType_MouseButtonPress, @P, Integer(ButtonState_LeftButton), Integer(ButtonState_LeftButton));
  192.     QApplication_sendEvent(TWidgetControl(Control).Handle, evMouse);
  193.     evMouse := QMouseEvent_create(QEventType_MouseButtonRelease, @P, Integer(ButtonState_LeftButton), Integer(ButtonState_LeftButton));
  194.     QApplication_sendEvent(TWidgetControl(Control).Handle, evMouse);
  195. {$ELSE}
  196.     P := SmallPoint(Control.Width  div 2, Control.Height div 2);
  197.     PostMessage(TWinControl(Control).Handle, WM_LBUTTONDOWN, 0, Longint(P));
  198.     PostMessage(TWinControl(Control).Handle, WM_LBUTTONUP, 0,   Longint(P));
  199. {$ENDIF}
  200.     Sleep(ActionDelay);
  201.   end;
  202.   Application.ProcessMessages;
  203. end;
  204. function TGUITestCase.FindControl(const AName: string; Addrs :Pointer): TControl;
  205. begin
  206.   Result := FindControl(Screen.ActiveForm, AName, Addrs);
  207. end;
  208. function TGUITestCase.FindParentWinControl(Control: TControl): TWinControl;
  209. begin
  210.   while (Control <> nil) and not (Control is TWinControl) do
  211.     Control := Control.Parent;
  212.   Result := TWinControl(Control);
  213. end;
  214. {$ifndef DUNIT_CLX}
  215. { Windows specific keyboard state code }
  216. procedure TGUITestCase.SetKeyboardStateDown(pControl : TWinControl; pShiftState: TShiftState);
  217. var KeyboardState : TKeyboardState;
  218. begin
  219.   GetKeyboardState(KeyboardState);
  220.   if ( ssAlt in pShiftState ) then
  221.   begin
  222.     KeyboardState[VK_MENU] := $80;
  223.     SetKeyboardState(KeyboardState);
  224.   end;
  225.   if ( ssShift in pShiftState ) then
  226.   begin
  227.     KeyboardState[VK_SHIFT] := $80;
  228.     SetKeyboardState(KeyboardState);
  229.   end;
  230.   if ( ssCtrl in pShiftState ) then
  231.   begin
  232.     KeyboardState[VK_CONTROL] := $80;
  233.     SetKeyboardState( KeyboardState );
  234.   end;
  235. end;
  236. { Windows specific keyboard state code }
  237. procedure TGUITestCase.SetKeyboardStateUp(pControl: TWinControl; pShiftState: TShiftState);
  238. var KeyboardState : TKeyboardState;
  239. begin
  240.   { Get the current keyboard state. }
  241.   GetKeyboardState( KeyboardState );
  242.   if ( ssAlt in pShiftState ) then
  243.   begin
  244.     KeyboardState[VK_MENU] := $00;
  245.     SetKeyboardState(KeyboardState);
  246.   end;
  247.   if ( ssShift in pShiftState ) then
  248.   begin
  249.     { Modify the keyboard state. }
  250.     KeyboardState[VK_SHIFT] := $00;
  251.     SetKeyboardState(KeyboardState);
  252.   end;
  253.   if ( ssCtrl in pShiftState ) then
  254.   begin
  255.     { Modify the keyboard state. }
  256.     KeyboardState[VK_CONTROL] := $00;
  257.     SetKeyboardState(KeyboardState);
  258.   end;
  259. end;
  260. {$endif}
  261. procedure TGUITestCase.Click;
  262. begin
  263.   Click(Screen.ActiveControl);
  264. end;
  265. procedure TGUITestCase.Click(ControlName: string);
  266. begin
  267.   Click(FindControl(ControlName, CallerAddr));
  268. end;
  269. procedure TGUITestCase.Click(Control: TControl);
  270. begin
  271.   Assert(Control <> nil, 'No control');
  272.   ClickLeftMouseButtonOn(Control);
  273. end;
  274. procedure TGUITestCase.EnterKey(Key: Word; const ShiftState: TShiftState);
  275. begin
  276.   //  EnterKeyInto(Screen.ActiveForm, Key, ShiftState);
  277.   EnterKeyInto(GetFocused, Key, ShiftState);
  278. end;
  279. procedure TGUITestCase.EnterKeyInto(Control: TControl; Key: Word; const ShiftState: TShiftState);
  280. {$IFDEF DUNIT_CLX}
  281. var
  282.   E: QKeyEventH;
  283.   Ch: char;
  284.   S: WideString;
  285.   state: integer;
  286.   function KeyChar(Key: word; Shift: boolean): char;
  287.   begin
  288.     Result := Char(Key);
  289.     if Shift then
  290.       Result := UpCase(Result)
  291.     else
  292.       Result := LowerCase(Result)[1];
  293.   end;
  294. {$ENDIF}
  295. begin
  296.   Assert(Control <> nil, 'No control');
  297.   Control := FindParentWinControl(Control);
  298.   if Control <> nil then
  299.   begin
  300. {$IFDEF DUNIT_CLX}
  301.     if Key <= 255 then
  302.     begin
  303.       Ch := KeyChar(Key, ssShift in ShiftState);
  304.       S := Ch;
  305.     end
  306.     else
  307.     begin
  308.       Ch := #0;
  309.       S := '';
  310.     end;
  311.     State := 0;
  312.     if ssAlt in ShiftState then
  313.       State := integer(ButtonState_AltButton);
  314.     if ssCtrl in ShiftState then
  315.       State := State or Integer(ButtonState_ControlButton);
  316.     if ssShift in ShiftState then
  317.       State := State or Integer(ButtonState_ShiftButton);
  318.     E := QKeyEvent_create(QEventType_KeyPress, Key, Ord(Ch), State, @S, false, 1);
  319.     try
  320.       QApplication_sendEvent(TWidgetControl(Control).Handle, E);
  321.     finally
  322.       QKeyEvent_destroy(E);
  323.     end;
  324. {$ELSE}
  325.     SetKeyboardStateDown(TWinControl(Control), ShiftState);
  326.     if ssAlt in ShiftState then
  327.     begin
  328.       PostMessage(TWinControl(Control).Handle, WM_SYSKEYDOWN, Key, integer($20000000));
  329.     end
  330.     else
  331.     begin
  332.       PostMessage(TWinControl(Control).Handle, WM_KEYDOWN, Key, 0);
  333.     end;
  334.     Application.ProcessMessages;
  335. {$ENDIF}
  336.     Sleep(ActionDelay);
  337. {$IFDEF DUNIT_CLX}
  338.     E := QKeyEvent_create(QEventType_KeyRelease, Key, Ord(Ch), State, @S, false, 1);
  339.     try
  340.       QApplication_sendEvent(TWidgetControl(Control).Handle, E);
  341.     finally
  342.       QKeyEvent_destroy(E);
  343.     end;
  344. {$ELSE}
  345.     if ssAlt in ShiftState then
  346.     begin
  347.       PostMessage(TWinControl(Control).Handle, WM_SYSKEYUP, Key, integer($E0000000));
  348.     end
  349.     else
  350.     begin
  351.       PostMessage(TWinControl(Control).Handle, WM_KEYUP, Key, integer($C0000000));
  352.     end;
  353.     SetKeyboardStateUp( TWinControl(Control), ShiftState );
  354. {$ENDIF}
  355.     Sleep(ActionDelay);
  356.     Application.ProcessMessages;
  357.   end;
  358. end;
  359. procedure TGUITestCase.EnterKeyInto(ControlName: string; Key: Word; const ShiftState: TShiftState);
  360. begin
  361.   EnterKeyInto(FindControl(ControlName, CallerAddr), Key, ShiftState);
  362. end;
  363. procedure TGUITestCase.EnterKey(Key: Char; const ShiftState: TShiftState);
  364. begin
  365.   EnterKey(Ord(Key), ShiftState);
  366. end;
  367. procedure TGUITestCase.EnterKeyInto(Control: TControl; Key: Char; const ShiftState: TShiftState);
  368. begin
  369.   EnterKeyInto(Control, Ord(Key), ShiftState);
  370. end;
  371. procedure TGUITestCase.EnterKeyInto(ControlName: string; Key: Char; const ShiftState: TShiftState);
  372. begin
  373.   EnterKeyInto(ControlName, Ord(Key), ShiftState);
  374. end;
  375. procedure TGUITestCase.EnterText(Text: string);
  376. begin
  377.   EnterTextInto(GetFocused, Text);
  378. end;
  379. procedure TGUITestCase.EnterTextInto(ControlName, Text: string);
  380. begin
  381.   EnterTextInto(FindControl(ControlName, CallerAddr), Text);
  382. end;
  383. procedure TGUITestCase.EnterTextInto(Control: TControl; Text: string);
  384. var
  385.   i :Integer;
  386. {$IFDEF DUNIT_CLX}
  387.   E: QKeyEventH;
  388.   S: WideString;
  389. {$ENDIF}
  390. begin
  391.   Assert(Control <> nil, 'No control');
  392.   Control := FindParentWinControl(Control);
  393.   if Control <> nil then
  394.   begin
  395.     for i := 1 to Length(Text) do
  396.     begin
  397. {$IFDEF DUNIT_CLX}
  398.     S := Text[i];
  399.     E := QKeyEvent_create(QEventType_KeyPress, Ord(Text[i]), Ord(Text[i]), 0, @S, false, 1);
  400.     QApplication_sendEvent(TWidgetControl(Control).Handle, E);
  401.     QKeyEvent_destroy(E);
  402. {$ELSE}
  403.       PostMessage(TWinControl(Control).Handle, WM_CHAR, Ord(Text[i]), 0);
  404. {$ENDIF}
  405.       Application.ProcessMessages;
  406.       Sleep(ActionDelay);
  407.     end;
  408.   end;
  409. end;
  410. procedure TGUITestCase.Show(OnOff: boolean);
  411. begin
  412.   Show(GUI, OnOff);
  413. end;
  414. procedure TGUITestCase.Show(ControlName: string; OnOff: boolean);
  415. begin
  416.   Show(FindControl(ControlName, CallerAddr), OnOff);
  417. end;
  418. procedure TGUITestCase.Show(Control: TControl; OnOff: boolean);
  419. begin
  420.   Assert(Control <> nil);
  421.   Control.Visible := OnOff;
  422.   Assert(Control.Visible = OnOff);
  423.   Application.ProcessMessages;
  424.   Sleep(ActionDelay);
  425. end;
  426. procedure TGUITestCase.Hide;
  427. begin
  428.   Screen.ActiveForm.Visible := false;
  429. end;
  430. procedure TGUITestCase.Hide(ControlName: string);
  431. begin
  432.   Show(ControlName, false);
  433. end;
  434. procedure TGUITestCase.Hide(Control: TControl);
  435. begin
  436.   Show(Control, false);
  437. end;
  438. procedure TGUITestCase.Tab(n: Integer);
  439. var
  440.   i :Integer;
  441.   s :TShiftState;
  442. begin
  443.   s := [];
  444.   if n < 0 then
  445.   begin
  446.     s := [ssShift];
  447.     n := -n;
  448.   end;
  449.   for i := 1 to n do
  450.     EnterKey(VK_TAB, s);
  451.   Application.ProcessMessages;
  452.   Sleep(ActionDelay);
  453. end;
  454. function TGUITestCase.GetFocused: TControl;
  455. begin
  456.   Result := Screen.ActiveControl;
  457. end;
  458. function TGUITestCase.IsFocused(Control : TControl) : boolean;
  459. begin
  460.   Result := GetFocused = Control;
  461. end;
  462. procedure TGUITestCase.CheckTabTo(Control: TControl; Addrs :Pointer = nil);
  463. var
  464.   i :Integer;
  465. begin
  466.   if Addrs = nil then
  467.     Addrs := CallerAddr;
  468.   if not (Control is TWinControl) then
  469.      Fail(
  470.         Format('Expected a TWinControl, but %s is a %s',
  471.                [Control.Name, Control.ClassName]),
  472.                Addrs
  473.         );
  474.   if not TWinControl(Control).CanFocus then
  475.       Fail(
  476.         Format('Control %s:%s cannot focus', [Control.Name, Control.ClassName]),
  477.         Addrs
  478.         );
  479.   for i := 1 to Screen.ActiveForm.ComponentCount do
  480.   begin
  481.      if GetFocused = Control then
  482.        EXIT;
  483.      Tab;
  484.   end;
  485.   Fail(Format('Could not Tab to control "%s"', [Control.Name]), Addrs);
  486. end;
  487. procedure TGUITestCase.CheckFocused(Control: TControl; Addrs :Pointer);
  488. var
  489.   F :TControl;
  490. begin
  491.   Assert(Control <> nil, 'No control');
  492.   if Addrs = nil then
  493.     Addrs := CallerAddr;
  494.   if not (Control is TWinControl) then
  495.     Fail(
  496.         Format('Expected a TWinControl, but %s is a %s',
  497.                [Control.Name, Control.ClassName]),
  498.         Addrs
  499.         );
  500.   if not TWinControl(Control).CanFocus then
  501.      Fail(
  502.         Format('Control %s cannot focus', [Control.ClassName]),
  503.         Addrs
  504.         );
  505.   if (Control.Owner <> nil) and (Control.Owner is TCustomForm) then
  506.     F := (Control.Owner as TCustomForm).ActiveControl
  507.   else
  508.     F := GetFocused;
  509.   if  F <> Control then
  510.   begin
  511.     if F <> nil then
  512.       Fail(Format('Expected control %s to have focus, but %s had it.', [Control.Name, F.Name]), Addrs)
  513.     else
  514.       Fail(Format('Expected control %s to have focus', [Control.Name]), Addrs);
  515.   end
  516. end;
  517. procedure TGUITestCase.CheckFocused(ControlName: string);
  518. begin
  519.   CheckFocused(FindControl(ControlName, CallerAddr), CallerAddr);
  520. end;
  521. procedure TGUITestCase.CheckTabTo(ControlName: string);
  522. begin
  523.   CheckTabTo(FindControl(ControlName, CallerAddr), CallerAddr);
  524. end;
  525. procedure TGUITestCase.CheckEnabled(Control: TControl; Addrs :Pointer = nil);
  526. begin
  527.   if not Control.Enabled then
  528.     Fail(Format('Expected control %s to be enabled', [Control.Name]), CallerAddr);
  529. end;
  530. procedure TGUITestCase.CheckEnabled(ControlName: string);
  531. begin
  532.   CheckEnabled(FindControl(ControlName, CallerAddr), CallerAddr);
  533. end;
  534. procedure TGUITestCase.SetFocus(Control: TControl; Addrs: Pointer);
  535. begin
  536.   if Addrs = nil then
  537.     Addrs := CallerAddr;
  538.   if not (Control is TWinControl) then
  539.      Fail(
  540.         Format('Expected a TWinControl, but %s is a %s',
  541.                [Control.Name, Control.ClassName]),
  542.                Addrs
  543.         );
  544.   if not TWinControl(Control).CanFocus then
  545.       Fail(
  546.         Format('Control %s:%s cannot focus', [Control.Name, Control.ClassName]),
  547.         Addrs
  548.         );
  549.   TWinControl(Control).SetFocus;
  550. end;
  551. procedure TGUITestCase.SetFocus(ControlName: string);
  552. begin
  553.   SetFocus(FindControl(ControlName, CallerAddr), CallerAddr);
  554. end;
  555. procedure TGUITestCase.CheckVisible(Control: TControl; Addrs: Pointer);
  556. begin
  557.   if not Control.Visible then
  558.     Fail(Format('Expected control %s to be visible', [Control.Name]), CallerAddr);
  559. end;
  560. procedure TGUITestCase.CheckVisible(ControlName: string);
  561. begin
  562.   CheckVisible(FindControl(ControlName, CallerAddr), CallerAddr);
  563. end;
  564. procedure TGUITestCase.CheckVisible;
  565. begin
  566.   CheckVisible(GUI, CallerAddr);
  567. end;
  568. end.