我在Delphi中使用了多年的框架,它们是VCL最强大的功能之一,但它们的标准使用似乎有一些风险,例如:
很容易意外地移动或编辑框架主机窗体上的框架子组件,而没有意识到你正在"调整"框架 - 我知道这不会影响原始框架代码,但它通常不是你想要的.
使用框架时,您仍然可以使用其子组件进行可视化编辑,即使该框架已有数年之久且不应触及.
所以我开始思考......
是否有一种"分组"组件的方式,使他们的位置"锁定"?这对完成的表格和框架都很有用.通常其他开发人员将代码返回给我,其中只有表单边界发生了变化,甚至他们也不打算进行任何更改.
有没有办法将框架及其组件转换为单个Delphi组件?如果是这样,框架内部构件将完全隐藏,其可用性将进一步增加.
我对任何想法感兴趣......
布莱恩.
Delphi对象检查器不会按设计显示TFrame后代的其他属性.人们倾向于建议使用一种已知的技巧,这种技巧通常用于在对象检查器上显示TForm后代的属性.诀窍是:通过设计时包将注册TForm后代的自定义模块注册到Delphi IDE:
RegisterCustomModule(TMyFrame, TCustomModule);
Run Code Online (Sandbox Code Playgroud)
对象检查器可以通过这种方式显示TFrame Descendant实例的其他属性,但是当它嵌入到表单中时会丢失其框架行为.不可重新设计,不可能为其子组件实现事件,并且它接受子控件(它没有).但它在自己的设计领域表现正常.
看起来,Delphi IDE专门为TFrame提供的那些行为.它们可能不是通用设施.
有没有其他方法可以实现这一点而不会丢失框架行为?
我正在使用Delphi 2007
@Tondrej,
请提前阅读此问题的评论.
frameunit.dfm:
object MyFrame: TMyFrame
Left = 0
Top = 0
Width = 303
Height = 172
TabOrder = 0
object Edit1: TEdit
Left = 66
Top = 60
Width = 151
Height = 21
TabOrder = 0
Text = 'Edit1'
end
end
Run Code Online (Sandbox Code Playgroud)
unit frameunit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TBaseFrame = Class(TFrame)
protected
Fstr: string;
procedure Setstr(const Value: string);virtual; …Run Code Online (Sandbox Code Playgroud) 我正在尝试在Delphi中编写一个dll库,该函数创建一个TFrame后代的实例并返回它.但是当我在一个应用程序中导入这个函数时,每次调用它时我都会得到一个例外,例如"'xxx'控件没有父窗口".我不是百分百肯定,但是当访问任何GUI控件时,该类的构造函数中出现异常.
你能告诉我这种行为的原因是什么吗?我应该只使用TForm后代还是有更好的解决方案?
谢谢!
我的应用程序中有一些表单具有不同的"状态",具体取决于用户的操作; 例如,当通过他的文件列出时,表单会在网格中显示有关该文件的一些数据,但如果他点击某个按钮,则网格会被与其相关的图表替换.简单地说,表单中的控件取决于用户想要做什么.
当然,这样做的显而易见的方法是根据需要显示/隐藏控件,就像小数字的魅力一样,但是一旦你达到每个状态10/15 +控件(或者真的超过3个状态)它就无法使用.
我现在正在尝试使用TFrame:我为每个状态创建一个框架,然后在我的表单上创建每个框架的实例,然后我只使用Visible显示我想要的那个 - 同时对其进行一些控制最重要的是,因为他们都共享它们.
这是做我想要的正确方法,还是我错过了一些东西?我以为我只能创建一个tframe实例,然后选择在其中显示哪个实例,但它看起来并不那样.
谢谢
我正常地在SO周围散步并碰到一些框架讨论.
我主要是Delphi的爱好者,而不是专业人士,所以我必须学习如何以我自己的方式使用TFrame:
经过一番个人商议,这是我的做法.
还有哪些方法可以使用框架?
我刚刚开始大量使用TFrames(好吧,是的,我一直生活在摇滚......).我认为框架支持消息处理程序声明 - 我已经看到很多这样的例子.那么为什么这个用于TFrame的简单测试单元永远不会看到它发布给自己的消息?(当我发现在我的大型应用程序中没有调用消息处理程序时,我创建了测试.)
unit JunkFrame;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
const
DO_FORM_INITS = WM_USER + 99;
type
TFrame1 = class(TFrame)
Panel1: TPanel;
private
procedure DoFormInits(var Msg: TMessage); message DO_FORM_INITS;
public
constructor Create(AOwner: TComponent); override;
end;
implementation
{$R *.dfm}
constructor TFrame1.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
PostMessage(self.Handle, DO_FORM_INITS, 0, 0);
end;
procedure TFrame1.DoFormInits(var Msg: TMessage);
begin
ShowMessage('In DoFormInits!');
end;
end.
Run Code Online (Sandbox Code Playgroud)
此框架仅包含TPanel,框架用于仅包含框架和关闭按钮的简单主文件.
我错过了什么?
昨天我开始讨论"MDI vs tabbed interface".我已经问过我是否应该继续开发基于MDI的应用程序,或者我应该将子表单嵌入到标签页中.有人指出我应该使用TFrame代替......我的问题是:为什么?
在TFrame上嵌入表单时使用TFrame的优点是什么?到目前为止我不知道,切换只需要我重写代码的某些部分......
(无论如何,我不打算在设计时使用嵌入!)
提前致谢
我经常将一个TForm后代嵌入另一个TForm后代,如下所示:
var
Form1: TForm1;
Form2: TForm2;
begin
Form2.Parent := Form1;
Form2.BorderStyle := bsNone;
Form2.Align := alClient;
Form2.Show;
end;
Run Code Online (Sandbox Code Playgroud)
通常这很好用,但有时Form2中的控件没有正确对齐.这类问题有一般的解决方法吗?
有人知道造成这种"错位"的原因吗?
我知道我可以TFrame用于这种工作,但我有很多库代码,我必须重写,我没有看到任何理由为什么TFormin TForm方法不起作用?
编辑:我已将组件识别TcxListView为罪魁祸首,我已向组件供应商(DevExpress)提交了错误报告:
http://www.devexpress.com/issue=B194161
编辑2: DevExpress的开发人员已经分析了这个问题并说它实际上是TGridPanelEmbarcadero组件中的缺陷:
这似乎是一个非常简单的问题,但我无法使用滚动条来显示滚动条,这让我发疯.
情况就是这样.我需要在表单的一部分中显示可变数量的帧.可以通过TSplitter或通过调整表单大小来调整显示这些帧的区域.
我在创建表单时根据数据库中的记录动态生成帧.这些框架是FlowPanel的父级,它负责框架放置.FlowPanel位于ScrollBox中.
由于FlowPanel,当用户使用TSplitter或调整表单大小时,帧可能会重新对齐.如果任何框架重新定位在窗体的视图之外,我希望ScrollBox显示滚动条,以便用户可以向下滚动到那些不可访问的框架.这不会发生.位于滚动框尺寸之外的流动板区域中的那些框架是不可访问的.
我在滚动框中使用简单对象构建了一些测试,如果任何包含的对象出现在滚动框的维度之外,则滚动框会正确放置滚动条.
如果流动板与clClient(滚动框)对齐或锚定到滚动框的两侧,或者没有这些都没有关系.
我意识到我可以使用TPanel,并在面板的OnResize事件处理程序的代码中执行框架的放置和重新定位,但这就是FlowPanel的用途.
这里发生了什么?我已经摆弄了许多不同的滚动条属性,仍然无法让它工作.问题是什么,有解决方案吗?
好.我选择Ewe的答案是正确的,但是做这项工作的诀窍在于他的一个评论,我仍然没有对结果感到满意.
这是独家新闻.我确实按照Ewe建议的方式配置了我的ScrollBox和FlowPanel,但是使用了许多其他设置,因为该配置不起作用.我很确定这是由于表单的用户界面的复杂性,它在面板中有许多面板,许多分割器,并且表单本身是PageControl的TabSheet的父级(我省略了这个事实,因为测试表格作为一个立场单独形式产生相同的结果).
让它发挥作用的是Ewe建议将FlowPanel的AutoWrap关闭再打开,尽管它很笨重.我将以下代码添加到ScrollBox的OnResize事件处理程序:
procedure TCurrentJobsForm.ScrollBox1Resize(Sender: TObject);
begin
Flowpanel1.Autowrap := False;
FlowPanel1.AutoWrap := True;
end;
Run Code Online (Sandbox Code Playgroud)
调整大小时会有明显的闪烁,但我可以忍受,因为它会产生所需的结果.一旦用户调整表单大小,它将始终使用这些维度重新创建,因此调整大小是用户不经常进行的操作.
嗨,我有一个内部有几个框架的表格.
对于某些帧,我希望滚动内容(或至少处理鼠标轮事件).
我尝试过以下方法:
只需为每个帧分配一个OnMouseWheel事件处理程序
覆盖父窗体的MouseWheel事件:
procedure TFmReview.MouseWheelHandler(var Message: TMessage);
var Control: TControl;
begin
Control := ControlAtPos(ScreenToClient(SmallPointToPoint(TWMMouseWheel(Message).Pos)), False, True);
if Assigned(Control) and (Control <> ActiveControl) then
begin
ShowMessage(Control.Name);
Message.Result := Control.Perform(CM_MOUSEWHEEL, Message.WParam, Message.LParam);
if Message.Result = 0 then
Control.DefaultHandler(Message);
end else inherited MouseWheelHandler(Message);
end;
Run Code Online (Sandbox Code Playgroud)
不幸的是,两者似乎都没有用.
因此,简单地说,如何将鼠标滚轮事件指向鼠标光标所在的最顶层控件(无论光标位于哪个帧/父/窗体等)?
delphi ×10
tframe ×10
components ×1
delphi-2007 ×1
dll ×1
focus ×1
frames ×1
handler ×1
layout ×1
mdi ×1
message ×1
mousewheel ×1
postmessage ×1
tform ×1
tscrollbox ×1
vcl ×1