Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从窗体';外部访问delphi控件;什么单位?_Delphi_Pascal - Fatal编程技术网

如何从窗体';外部访问delphi控件;什么单位?

如何从窗体';外部访问delphi控件;什么单位?,delphi,pascal,Delphi,Pascal,我试图从这样定义的过程调用计时器的Enabled属性:procedure Slide(Form:TForm;Show:Boolean)而不是固定的表单名称(例如:Form2.Timer…) 将表单的单位放入uses列表后,此操作有效:Form2.Timer1.Enabled:=True 但以下内容不起作用:Form.Timer1.Enabled:=True(其中Form是作为参数传递给过程的表单 如何访问窗体上的计时器组件 提前感谢。在当前设备的使用列表中使用Form2的设备名称 供您编辑: 使

我试图从这样定义的过程调用计时器的Enabled属性:
procedure Slide(Form:TForm;Show:Boolean)而不是固定的表单名称(例如:
Form2.Timer…

将表单的单位放入uses列表后,此操作有效:
Form2.Timer1.Enabled:=True
但以下内容不起作用:
Form.Timer1.Enabled:=True(其中Form是作为参数传递给过程的表单

如何访问窗体上的计时器组件


提前感谢。

在当前设备的使用列表中使用Form2的设备名称

供您编辑:

使用
TForm
无法访问
TTimer
,因为
TForm
没有字段或属性作为TTimer。

因此,您需要使用
TForm1作为参数

如果您有一个表单,比如Form1,您正在为它创建多个实例并向用户显示,那么将您的过程语法更改为
过程幻灯片(form:TForm1;Show:Boolean);

但是,如果您有多个具有不同组件的表单,这将变得很困难。您需要使用不同的参数重载过程。下面的代码显示了该方法

表格1单位

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit3;

procedure TForm1.Button1Click(Sender: TObject);
begin
Slide(Form1, True)
end;
表格2单位

var
  Form2: TForm2;

implementation

{$R *.dfm}

uses Unit3;

procedure TForm2.Button1Click(Sender: TObject);
begin
Slide(Form2, True)
end;
您的程序所在的单元

unit Unit3;

interface

uses Forms, ExtCtrls, Unit1, Unit2;

procedure Slide(Form: TForm1; Show: Boolean) overload;
procedure Slide(Form: TForm2; Show: Boolean) overload;

implementation


procedure Slide(Form: TForm2; Show: Boolean);
begin
  Form.Timer1.Enabled := True;
end;


procedure Slide(Form: TForm1; Show: Boolean);
begin
  Form.Timer1.Enabled := True;
end;

end.

将该装置添加到“使用”列表中

...
implementation

uses Unit2;

{$R *.dfm}
...

只是补充一些信息

在Delphi项目中,代码被组织成多个单元。每个单元都是一个带有名称和.pas扩展名的文件

该单位的形式如下:

unit Name;

interface
uses
  // The definition of these units can be used both in the 
  // interface as in the implementation section.
  unit1, unit2;  

// Public interface, visible to other units that use this unit.

implementation
uses
  // The definition of these units can be used only in the 
  // implementation section.
  unit3, unit4;

// Private implementation, not visible outside.

initialization
  // code to initialize the unit, run only once
finalization
  // code to cleanup the unit, run only once
end.
一个单位可以使用该单位中定义的任何东西,只要它在使用前已经定义

如果名称相同,有时会导致混淆情况:

unit1;
interface
type
  TTest = Integer;
// ...

unit2;
interface
type
  TTest = Boolean;
// ...

unit3;
interface
uses
  unit1, unit2;
var
  a: TTest;  // Which TTest?
// ...
您可以通过了解评估顺序或使用单位前缀来解决此问题:

unit3;
interface
uses
  unit1, unit2;
var
  a: unit1.TTest;  // TTest from unit1
  b: unit2.TTest;  // TTest from unit2
// ...
在您的情况下,您需要使用定义Form2的单元

如果两个表单都需要计时器,那么您也可以使用datamodule(就像表单一样,您可以将不可见的组件拖到其中,但它们不可见)。然后两个表单都可以使用datamodule

编辑

您尝试使用:

procedure Slide(Form: TForm; Show: Boolean); 
TForm没有计时器1

您可以执行以下操作:

procedure Slide(Form: TForm2; Show: Boolean); 

如果TForm2是包含计时器的窗体。

您无法从过程访问计时器,因为您的参数是TForm,而TForm没有Timer1成员。您必须按如下方式调整过程:

uses
  Unit2; //unit with your form

procedure Slide(Form: TForm2; Show: Boolean); //change TForm2 to the classname you use
begin
  Form.Timer1.Enabled := True;
end;
Slide(Form2, Form2.Timer1, True);
Slide(AnotherForm, AnotherForm.SlideTimer, False);
编辑:

如果要通过任何表单,可以尝试以下操作:

procedure Slide(Form: TForm; const aTimerName: string; Show: Boolean);
var
  lComponent: TComponent;
begin
  lComponent := Form.FindComponent(aTimerName);
  if Assigned(lComponent) and (lComponent is TTimer) then
    TTimer(lComponent).Enabled := True;
end;
通过表单上的按钮进行如下调用:

procedure TForm2.Button1Click(Sender: TObject);
begin
  Slide(Self, 'Timer1', False);
end;

或者,您可以让表单继承一个接口,该接口带有打开计时器的方法。不过这有点复杂。

最简单的方法是在表单上找到它:

procedure Slide(Form: TForm; Show: Boolean);
var
  Timer: TTimer;
begin
  Timer := Form.FindComponent('Timer1');
  if Assigned(Timer) then
    Timer.Enabled := True;
end;
为了安抚David;-),这里有一个更“类型安全”的选择:

procedure Slide(Form: TForm; Show: Boolean);
var
  i:  Integer;
begin
  // Could use a TComponent and for..in instead. This works in
  // all Delphi versions, though.
  for i := 0 to Form.ComponentCount - 1 do
    if Form.Components[i] is TTimer then
      TTimer(Form.Components[i]).Enabled := True;
end;♦♠

如果要传递到函数中的每个表单都有一个名为“Timer1”的已发布字段,则可以使用该方法获取对它的引用:

procedure Slide(Form: TForm; Show: Boolean);
var
  TimerObj: TComponent;
  Timer: TTimer;
begin
  TimerObj := Form.FindComponent('Timer1');
  Assert(Assigned(TimerObj), 'Form has no Timer1');
  Assert(TimerObj is TTimer, 'Form.Timer1 is not a TTimer');
  Timer := TTimer(TimerObj);
  // Continue using Form and Timer
end;
不过,这是一个相当弱的编程接口。如果您无意中忽略了在窗体上放置计时器,或者给了它错误的名称,或者给了它不同的可见性,那么在运行时(断言失败时)之前,您不会发现错误。即使表单满足所需的接口,也不能保证它是故意的。可能有很多表单已经发布了名为
Timer1
TTimer
字段,但它们并不都用于此
幻灯片
功能。他们可能已经将计时器用于其他目的,因此对其调用
Slide
将破坏程序的其他部分,可能会以难以调试的方式

如果您给计时器一个更具描述性的名称,例如
SlideTimer
,那么它将是一个更强大的界面
Timer1
只是说它是您在该表单上创建的第一个
TTimer
,一旦您离开表单设计器,它就不再是一个有意义的名称。您不需要使用IDE的命名选项


另一个更好的选择是使所有可滑动表单都有一个公共基类,并将计时器放在该基类中。然后,将幻灯片中的参数类型更改为采用该表单类,而不仅仅是
t表单

type
  TSlidableForm = class(TForm)
    Timer1: TTimer;
  end;

procedure Slide(Form: TSlidableForm; Show: Boolean);
您似乎担心必须在
幻灯片
单元中包含对Form2单元的引用,这通常是一个值得关注的问题。您不希望代码耦合得太紧密,因为此
幻灯片
函数应该能够在一个项目中处理多个表单。但是如果它太松,那么你就会遇到我上面描述的问题。这个
TSlidableForm
类是一个折衷方案;您的
幻灯片
功能未直接绑定到
TForm2
或其单元。将
TForm2
更改为从
TSlidableForm
下降

type
  TSlidableForm = class(TForm)
    Timer1: TTimer;
  end;

procedure Slide(Form: TSlidableForm; Show: Boolean);

是我的第一个变体,但还有另一个变体。您可以传递对组件本身的引用,而不是传递计时器组件的名称:

procedure Slide(Form: TForm; Timer: TTimer; Show: Boolean);
现在您不需要使用
FindComponent
来搜索要使用的计时器;你提供了对它的直接引用。组件的名称甚至无关紧要,因此不同的表单可以使用不同的名称。你可以这样称呼它:

uses
  Unit2; //unit with your form

procedure Slide(Form: TForm2; Show: Boolean); //change TForm2 to the classname you use
begin
  Form.Timer1.Enabled := True;
end;
Slide(Form2, Form2.Timer1, True);
Slide(AnotherForm, AnotherForm.SlideTimer, False);

一旦你走到这一步,你可能会超越原来的问题,并意识到计时器甚至不需要再属于表单。您可以专门为调用
幻灯片
创建它,或者计时器可以完全属于其他东西(如数据模块)。但是,如果只为
幻灯片
调用创建计时器,那么可以使用David的建议,在例程本身中创建计时器,而不让调用方或表单处理它:

procedure Slide(Form: TForm; Show: Boolean);
var
  Timer: TTimer;
begin
  Timer := TTimer.Create(nil);
  try
    Timer.OnTimer := ...;
    Timer.Interval := 500;
    Timer.Enabled := True;

    // Put your normal Slide stuff here
  finally
    Timer.Free;
  end;
end;
一种实现thi的简单(面向对象)方法