我需要运行一个附加到按钮(例如SQLBtn)的动作,该动作放在我的应用程序中的Frame1上,来自Form1。
我已经在Form1中使用了框架,但似乎无法以任何方式解决
我已经尝试过Frame1.SQLbtn TFrame1.SQLbtn TFrameSQLBtn等,但无法达到它。
我想得到类似于'SQLbtn.click'的东西来运行它背后的事件。
有没有人有任何想法如何解决?
答案 0 :(得分:5)
我不确定我是否理解你的问题。听起来你有一个带按钮的框架(按钮上有一个TAction或click事件处理程序),这个框架就坐在一个表格上。现在,您希望以编程方式模拟该按钮上的单击。
显然,您需要将帧单位添加到表单的uses子句中。您还需要表单上的框架实例,该实例应该导致框架类型的表单字段,例如
TForm1...
...
Frame1: TFrame1;
end;
然后,您可以从任何表单的方法中通过Frame1.SQLbtn.Click
执行该代码。更好的方法可能是在框架上提供可以从表单中使用的公共方法。然后你不需要直接访问该按钮(该按钮是框架的实现细节,框架私有可以这么说)。
澄清后编辑
我知道您有以下情况:
TFrameForm1...
...
Frame1: TFrame1;
end;
TForm1...
...
procedure something;
end;
procedure TForm1.something;
begin
// how to call a method on Frame1 which is on FrameForm1
end;
您最好的选择是将代码从框架按钮OnClick事件处理程序移动到一个单独的单元中。这可以是数据模块,也可以是具有独立过程的另一个单元。然后,您可以从Form1和Frame1按钮事件处理程序中调用该代码。这就是Vegar评论的内容。
如果不可能,例如因为处理需要访问Frame1上的其他控件,将代码移动到Frame1上的新程序(我的原始建议):
TFrame1...
...
public
procedure framestuff;
end;
procedure TFrame1.framestuff;
begin
...
end;
procedure TFrame1.SQLbtnClick(Sender...);
begin
framestuff;
end;
现在需要从Form1调用该方法。你需要一个对FrameForm1的引用。在创建TFrameForm1时需要手动初始化(!)。在此示例中,引用是字段FFrameForm:
TForm1...
...
FFrameForm: TFrameForm1;
procedure something;
end;
procedure TForm1.something;
begin
FrameForm.framestuff;
end;
或者,默认情况下,Delphi将所有表单的全局变量添加到表单单元(自动表单创建,检查项目选项/表单)。然后你这样做:
procedure TForm1.something;
begin
FrameForm1.framestuff; // if FrameForm1 is the name Delphi used for the global variable
end;
当然还有很多其他的变化......
答案 1 :(得分:1)
procedure TDiferentForm.DoSomething();
begin
Form1.YourFrame.ButtonClick(nil);
end;
答案 2 :(得分:0)
有一件事可能有助于您理解:当您创建表单(或框架)的实例时,delphi会遍历DFM并创建其中描述的所有对象的实例。
IF 您在表单的定义中有一个与DFM中对象名称匹配的变量,加载器将使变量指向该对象;如果您没有变量,则会创建该对象,但您必须遍历.Components或.Controls才能访问它。
如果表单有一个框架的实例变量(并且该变量是公共的),那么任何其他表单的代码都可以访问它(例如MainForm.Frame1 ...)并按照自己的意愿行事。
要封装框架,表单(毕竟只是一个类)可以具有公共属性,它们具有访问器和更改器,用于代理嵌入式帧的信息。封装是好的(恕我直言是OOP最重要的方面),因为它使调用者和框架之间的链接松散:你可以在不破坏任何东西的情况下改变任何一方。
干杯
答案 3 :(得分:0)
另一种解决方案是使用接口来避免循环引用问题并稍微简化代码。假设您要从系统中的任何位置调用名为 foo 的过程。此过程的实现在 tFooForm 中,它不是主要表单,而是主表单知道的表单。
首先创建一个新单位并将其命名为 Foo_Intf.pas
其内容如下:
unit Foo_Intf;
interface
type
IFoo = interface
['{4AC12AB9-557B-4E61-AB2D-8B10E591E33A}']
// CTRL-SHIFT-G to create a new guid
procedure Foo;
end;
implementation
end.
然后将方法添加到tFooForm类,并且还包括接口。不要忘记在interface uses子句中使用foo_intf.pas单元。实现foo类以执行您希望该过程执行的操作。
tFooForm = class(tForm,IFoo)
:
procedure Foo;
:
end;
还要将IFoo接口添加到主窗体,与上一步完全相同,但将实现更改为以下内容:
procedure tMainForm.Foo;
begin
if not Assigned(FooForm) then
FooForm := tFooForm.Create(Application); // for simplicity sake
FooForm.Foo;
end;
现在,您想要调用foo函数的任何地方,只需在uses子句中包含Foo_Intf单元并使用以下snippit:
var
FooIntf : IFoo;
begin
if Not Supports(Application.MainForm, IFoo, FooIntf) then
Raise Exception.create('Application.mainform does not implement IFoo');
FooIntf.Foo;
end;