Delphi:如何使用无窗口控件?

时间:2010-02-23 03:24:58

标签: delphi windowless

我知道windowless controls are not magic。无窗口控件可以具有输入焦点(例如,Internet Explorer)。输入焦点只不过是绘制:

当用户开始捣碎键时,适当地做出反应。您知道按键用于 聚焦控件,因为控件具有焦点。

对于我的(Windows®)窗口,我必须知道我的无窗口子控件(让 假装 它是TGraphicControl的后代)获得键盘事件。因此,在我的表单OnKeyDownOnCharOnKeyUp期间,我需要假装他们将进入无窗的儿童控制。

我能做什么,但这很痛苦。

但是那时用户可能会想要使用 Tab 导航,而且我必须以某种方式拦截Delphi的正常制表控制命令处理,然后我自己说出这个东西< / strong>是Tab键顺序中的下一个(和上一个)。

我能做什么,但这很痛苦。

然后有ActiveControl,除了TWinControl之外什么都不懂。因此,如果德尔福曾试图找出谁有焦点,它将会疯狂。所以我必须有一个ActiveControl的替代实现。

我能做什么,但这很痛苦。

换句话说:这只是太多的工作吗?我正在与德尔福进行斗争,所以我可以通过键盘输入访问几十个无窗口控件? Delphi设计师从未考虑使用交互式无窗口控件,如果我现在尝试使用它,我只会卡在hurtlocker

德尔福让我有机会自愿帮助我,但我选择了痛苦的方式。


需要对无窗口控件进行进一步说明。

并非您与之交互的每个控件都必须是Windows控件。很可能将焦点放在并且将键盘输入发送到不是Windows窗口的控件上。

例如,您在Internet Explorer浏览器窗口中看到的几乎所有控件都是无窗口控件。在下面的屏幕截图中,您可以看到可以输入的编辑控件,以及一个(在此屏幕截图中)具有焦点的按钮:

alt text http://i49.tinypic.com/2d7d82e.jpg

你可以看到虚线的焦点矩形,按钮是蓝色的(在Windows上表示它有焦点)。

如果我在Google Search按钮有焦点时按空格键,则按钮。这样做的原因是因为Microsoft编写了一个完整的控件库。这些控件的外观和感觉(几乎)与常规常用控件完全相同 - 它们几乎都是Windows常用控件的克隆,直到所应用的主题。

Mozilla Firefox和Google Chrome也使用控件的小部件库。它们不使用Microsoft的内置窗口控件,而是使用图形化,交互式,无窗口小部件的库。

如果你有一个合适的开发环境,那么无窗口小部件就像“普通”窗口控件一样工作。 GTK +是一个小部件库,Glade是一个IDE,可以让您在该小部件库中布局控件。

我不知道Firefox,Chrome或Blender在哪个开发环境中创建,但他们的小部件支持无窗口控件。


现在问我的问题。

除非我弄错了,否则在我看来虽然Delphi支持基础TControl,(它有宽度,高度,并且可以自己绘制),但它无法接收键盘焦点。在我看来,Borland从未将Delphi的VCL设计为通用小部件库。我必须支持的唯一证据是表格的ActiveControl是TWinControl:

property ActiveControl: TWinControl;

这并不意味着Delphi可能或必须限于窗口控件。可以扩展VCL小部件库以支持将重点放在无窗口控件上。

但也许 Delphi已经支持无窗口控件,我只是没有意识到它?在Delphi中是否已经建立了一个机制来支持将注意力集中在TControl上?但我是一个相当聪明的人,我很确定Delphi的VCL不能做其他小部件库可以做的事情。

然后又引出了另一个问题:将子类表格做多少工作以支持它?那里有其他人,也许是TeamB上的某个人,他比我聪明得多,谁已经尝试过,并得出结论不可能

我现在正在问,如果试图添加无窗口控制支持几乎是不可能的(即徒劳无功) - 这样我就不会花费数周的时间。我正在努力利用Delphi开发人员社区的知识。

我正在问一个问题。

7 个答案:

答案 0 :(得分:4)

是的,这是徒劳的 而且这不是德尔福的错,你只是在打击Windows本身 如果您需要一个行为类似于窗口控件的控件,请使用窗口控件 你是对的,尝试从头开始重新创建窗口控件的整个API堆栈是一件痛苦的事。

答案 1 :(得分:4)

构建无窗口控件使它们适合Delphi的VCL框架是徒劳的。

您将Internet Explorer作为示例。但在这种情况下,它完全掌控着它上面的一切。它有自己的内部概念,主动控制是什么,但从外面思考它的样子:它只是一个巨大的控制。当你向操作系统询问什么是焦点时,单个浏览器控件就可以使用它,无论浏览器的哪个子控件出现都有焦点。

按Tab键时,它会向操作系统查看,就好像浏览器只使用了制表符一样,就像编辑控件一样。编辑控件将光标移动几个空格,并将制表符添加到其内部缓冲区;浏览器控件将光标移动到显示的另一个区域。

你想在Delphi TForm上做这一切。 Delphi表单已经有一个框架来管理主动控制和处理击键,你将不得不打击它。如果您想要无窗口控件,请转到Internet Explorer路径并构建您自己的容器控件来保留它们,以便您可以继续管理其中发生的所有事情。

您的容器可以是VCL控件,但您放在它上面的东西可能不会 - 他们仍然期望使用VCL焦点和键盘处理规则。请注意,您也不能将普通的Windows控件放在Internet Explorer中。你放在那里的任何东西都需要通过特定的ActiveX接口。也许你也需要接口,或者也许你可以创建自己的一组控件类,这些控件类来自你设计用于容器的一些特殊的祖先类。不要以TGraphicControl开头;它在VCL中根深蒂固,可以作为你的分支控制库的基础。

这将是很多工作,但是再次,Internet Explorer也是如此。

答案 2 :(得分:3)

是的,你几乎已经明白了。使用无窗口控件意味着您将失去Windows可以帮助您的所有操作。在一个实际的窗口上拥有多个人是痛苦的。

答案 3 :(得分:1)

这些程序中的大多数很可能最初不是使用RAD型工具开发的,因此别无选择,只能重新发明轮子。 Delphi最大的优势之一是深度VCL和第三方组件支持,以提供您想要的外观。

我已经非常成功地使用了一种技术来减少复杂(税务准备)表单应用程序中使用的窗口句柄数量,这是在画布上绘制文本,并将单个TCustomEdit后代移动到用户的位置正在编辑。捕获TAB /向上/向下键并将编辑移动到适当的位置是微不足道的。我们发现的挑战是在鼠标悬停场周围绘制一个热矩形。我们最终得到了一个TObject的网格数组,其中数组元素为nil(无字段),TLIst(网格包含多个字段)或包含字段描述符的类。这减少了我们必须执行的范围检查的数量,因为该框更可能只包含一个字段,或最多包含4个字段。

答案 4 :(得分:1)

fpGUI Toolkit就是你想要的一个例子。源代码存储库中的最新fpGUI代码基于多窗口设计。这很简单意味着每个窗口小部件/组件都有一个窗口句柄,但Windows或Linux对该窗口不执行任何操作,其他基本通知消息(mouseenter,mouseexit等)。 fpGUI仍然可以完全控制每个组件的位置,如果它们是可聚焦的,它们的外观等等.fpGUI中的一些小部件/组件也是非窗口组件。例如:TfpgScrollbar,TfpgMainMenu,ComboBox中的按钮等。

如果你想要一个真正的非窗口版本,意味着只有一个顶层窗口有一个窗口句柄,那个窗口内的所有其他窗口小部件/组件实际上并不存在于操作系统中(它们没有窗口句柄) ),那么fpGUI也可以提供帮助。 fpGUI Toolkit的初始设计基于这样的设计。再次,在源代码存储库中查找代码的v0.4分支。我的设计,fpGUI必须处理绝对一切,创建mouseenter / mouseleave事件,翻译容器组件的协调系统,处理(假)组件焦点状态等...是的初始设计是很多工作,但后来你有一个非常便携的框架,可以很容易地应用到其他操作系统。

是的,fpGUI完全用Object Pascal语言实现,使用Free Pascal编译器为我提供跨平台支持。目前fpGUI在Windows,Linux(32和64位),Windows Mobile和嵌入式Linux(ARM)设备上运行。

答案 5 :(得分:0)

我不知道你的问题究竟是什么,在这里,但我认为这个小历史可能是相关的......

我们有一个填写十几种表格的申请表。用户可以填写其他表单,还可以更改应用程序自己填写的值。

现在,在我们的第一个实现中,我们为每个输入字段使用了窗口化组件,以便字段可以获得焦点和输入。结果证明这是个大问题,因为所有这些窗口都占用了大量资源。

我们现在为每个输入字段都有无窗口控件。这意味着我们最终得到的是表单及其输入字段的组合绘图。当用户在绘图内部单击或使用一些按键来移动/设置焦点时,我们为单击的字段创建一个新的窗口控件。当用户移动到下一个输入字段时,我们销毁第一个窗口,并创建一个新窗口。这样我们只有一个窗口控制,这再次给了我们一个很好的速度提升。

再次 - 我不知道你真正想要管理什么。 TWinControl是一个TWinControl有一个原因,但可能有你想要的解决方案,这将是什么......

答案 6 :(得分:0)

我认为fgGUI可能会帮助你。

请先检查Wiki

我认为你可以在Delphi中使用这个框架,因为它完全用Pascal编写。实际上它基于FreePascal;)

HTH