4

我知道无窗口控件并不神奇。无窗口控件可以具有输入焦点(例如 Internet Explorer)。输入焦点无非就是绘制:

当用户开始捣碎键时,做出适当的反应。你知道击键是为了那个有焦点的控件,因为那个控件有焦点。

对于我的 (Windows®) 窗口,我必须知道我的无窗口子控件(假设它是 TGraphicControl 的后代)获取键盘事件。所以在我的表格OnKeyDownOnCharOnKeyUp我需要假装他们要去我的无窗儿童控制。

我可以做到,但这是一种痛苦。

但是随后用户可能会想要使用Tab导航,我将不得不以某种方式拦截 Delphi 的正常选项卡控制顺序处理,并让自己说这件事是选项卡顺序中的下一个(和上一个)。

我可以做到,但这是一种痛苦。

然后是,它除了'ActiveControl什么都不理解。TWinControl因此,如果 Delphi 试图弄清楚谁有焦点,那它会发疯的。所以我必须有一个 ActiveControl 的替代实现。

我可以做到,但这是一种痛苦。

换句话说:这是不是工作量太大了?我正在与 Delphi 的所有东西作斗争,所以我可以通过键盘输入访问几十个无窗口控件?Delphi 的设计者从来没有考虑过使用交互式无窗口控件,如果我现在尝试使用它,我会卡在伤害储物柜中吗?

Delphi给了我心甘情愿地帮助我的机会,但我选择了痛苦的方式。


需要对无窗口控件进行一些进一步的解释。

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

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

替代文字

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

如果我SpacebarGoogle Search按钮有焦点时按下,它会按下按钮。之所以可行,是因为 Microsoft 编写了一个完整的控件小部件库。这些控件的外观和感觉(几乎)与常规的常用控件完全一样——它们几乎是 Windows 常用控件的完全克隆,一直到应用的主题。

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

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

我不知道 Firefox、Chrome 或 Blender 是在什么开发环境中创建的,但它们的小​​部件支持无窗口控件。


所以现在开始我的问题。

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

property ActiveControl: TWinControl;

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

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

这又引出了另一个问题:子类化表单等支持它需要做多少工作?是否还有其他人,也许是 TeamB 中的某个人,比我聪明得多,已经尝试过,并得出结论认为这是不可能的?

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

我在问一个问题。

4

7 回答 7

4

是的,这是徒劳的。
这不是 Delphi 的错,你只是在与 Windows 本身作斗争。
如果您需要一个行为类似于窗口控件的控件,请使用窗口控件。
你是对的,试图从头开始重新创建窗口控件的整个 API 堆栈是一种痛苦。

于 2010-02-23T07:50:33.470 回答
4

构建无窗口控件并将它们装入 Delphi 的 VCL 框架是徒劳的。

您以 Internet Explorer 为例。但在这种情况下,它完全负责驻留在上面的一切。它对主动控件是什么有自己的内部概念,但想想它从外部看起来是什么样子:它只是一个巨大的控件。当您询问操作系统什么具有焦点时,单个浏览器控件具有它,无论浏览器的哪个子控件似乎具有焦点。

当你按下 Tab 键时,它看起来就像浏览器只是简单地使用了一个 tab 字符,就像编辑控件一样。编辑控件将光标移动到几个空格上并将制表符添加到其内部缓冲区;浏览器控件将光标移动到显示的另一个区域。

您正在考虑在 Delphi TForm 上执行所有这些操作。Delphi 表单已经有一个管理活动控件和处理击键的框架,您将不得不与这一切作斗争。如果您想要无窗口控件,请使用 Internet Explorer 路线并构建您自己的容器控件来保存它们,这样您就可以继续负责其中发生的所有事情。

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

这将是很多工作,但话又说回来,Internet Explorer 也是如此。

于 2010-02-23T15:49:55.717 回答
3

是的,你几乎已经想通了。使用无窗口控件意味着您失去了 Windows 可以帮助您的一切。在一个实际窗口上拥有超过一对是痛苦的。

于 2010-02-23T03:28:04.203 回答
1

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

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

于 2010-02-23T17:08:31.937 回答
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) 设备上运行。

于 2010-02-26T23:21:08.307 回答
0

我不知道你的问题到底是什么,但我认为这段小历史可能是相关的......

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

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

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

再说一遍 - 我不知道你真正想要管理什么。TWinControl 是一个 TWinControl 是有原因的,但可能有一个解决方案可以满足您的需求,无论是什么...

于 2010-02-23T12:39:16.623 回答
0

我认为fgGUI可以帮助你。

请先检查其Wiki

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

高温高压

于 2010-02-24T06:31:24.423 回答