代码之家  ›  专栏  ›  技术社区  ›  Ian Boyd

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

  •  4
  • Ian Boyd  · 技术社区  · 15 年前

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

    当用户开始混合键时,做出适当的反应。你 知道 击键是为了 那个 集中控制,因为那是有焦点的控制。

    对于我的(window s)窗口,我必须知道我的无窗口子控件(让我们 假装 它是tgraphicControl的后代)获取键盘事件。所以在我的状态下 OnKeyDown , OnChar , OnKeyUp ,我需要假装他们要去我的无窗儿童控制中心。

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

    但是用户可能会想使用 标签 导航,我不得不截取delphi的正常tab控件顺序处理,然后自己说 这东西 是选项卡顺序中的下一个(和上一个)。

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

    然后是 ActiveControl ,除了 TWinControl 所以如果德尔菲试图找出谁是焦点人物,那就太疯狂了。所以我必须有一个activecontrol的替代实现。

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

    换句话说: 这是不是工作太多了? 我在和Delphi做斗争,所有这些都是为了让我可以通过键盘输入访问几十个无窗口控件?Delphi的设计者从未想过使用交互式的无窗口控件,如果我现在尝试使用它,我将只停留在 hurtlocker ?

    德尔菲给了我一个自愿帮助我的机会,但我选择了痛苦的方式。


    进一步解释 无窗口控件 是需要的。

    不是所有与之交互的控件都必须是windows控件。很有可能将焦点放在一个不是windows窗口的控件上,并将键盘输入发送到该控件。

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

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

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

    如果我按 空格键 Google Search 按钮有焦点,它会 按钮。之所以这样做是因为微软编写了一个完整的控件小部件库。这些控件的外观和感觉(几乎)与常规的公共控件完全相同——它们几乎完全是windows公共控件的克隆,一直到应用的主题。

    mozilla firefox和google chrome也使用控件的小部件库。他们不使用微软的内置窗口控件,而是使用一个图形化的、交互式的、无窗口的库 小部件

    如果您有一个合适的开发环境,那么无窗口小部件就像“普通”的窗口控件一样工作。gtk+是一个小部件库,glade是一个ide,允许您在该小部件库中布局控件。

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


    现在来问我的问题。

    除非我搞错了,在我看来,尽管delphi支持 TControl ,它不能接收键盘焦点。在我看来,Borland从未将Delphi的VCL设计为一个通用的小部件库。我唯一要支持的证据是 主动控制 是TwinControl:

    property ActiveControl: TWinControl;
    

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

    但也许 Delphi已经支持无窗口控件 ,我只是不知道?Delphi中是否已经建立了一个机制来支持 T控件 是吗?但我是一个相当聪明的人,我很确定delphi的vcl不能做其他widget库能做的事情。

    这就引出了另一个问题: 子类化表单和支持表单的子类需要做多少工作? 有没有其他人,也许是B组的人,比我聪明得多,已经试过了,然后得出结论 不可能的 ?

    我现在要问的是,在前面,如果试图添加无窗控制支持几乎是不可能的(即徒劳无功),这样我就不会白花几个星期。我试图利用delphi开发人员社区的知识。

    我在问一个问题。

    7 回复  |  直到 15 年前
        1
  •  4
  •   Rob Kennedy    15 年前

    建立无窗控制是徒劳的。 将它们放入Delphi的VCL框架中。

    以Internet Explorer为例。但在这种情况下,它完全负责它身上的一切。它对主动控制是什么有自己的内部概念,但从外部想想它是什么样子:它只是一个巨大的控制。当你问操作系统焦点是什么时,不管浏览器的哪个子角色,单个浏览器控件都有焦点。 出现 集中注意力。

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

    你在考虑用delphi的tform来做这一切。Delphi表单已经有了一个用于管理活动控件和处理击键的框架,您将不得不克服这一切。如果需要无窗口控件,请转到Internet Explorer路径并 建立自己的容器控件 持有它们,这样你就可以继续掌控里面发生的一切。

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

    这将是一个很大的工作,但接着,互联网浏览器也是。

        2
  •  4
  •   Francesca    15 年前

    是的,这是徒劳的。
    这不是德尔福的错,你只是在和windows打。
    如果需要行为类似于窗口控件的控件,请使用窗口控件。
    你说得对,从头开始重新创建窗口控件的整个api堆栈是件痛苦的事。

        3
  •  3
  •   Ignacio Vazquez-Abrams    15 年前

    是的,你已经弄清楚了。使用无窗口控件意味着您将失去windows所能为您提供的一切帮助。在一个实际的窗口上有多个窗口是痛苦的。

        4
  •  1
  •   skamradt    15 年前

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

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

        5
  •  1
  •   user282429    15 年前

    fpGUI Toolkit 是你想要的一个例子。源代码库中最新的fpgui代码基于多窗口设计。这个简单的方法意味着每个小部件/组件都有一个窗口句柄,但是windows或linux对这个窗口没有任何作用,除了基本的通知消息(mouseenter、mouseexit等)。fpgui仍然可以完全控制每个组件的去向,如果它们是可聚焦的,它们的外观等。fpgui中的一些小部件/组件也是非窗口组件。例如:tfpgscrollbar、tfpgmain菜单、组合框中的按钮等。

    如果您想要一个真正的无窗口版本,意味着只有一个顶级窗口有窗口句柄,该窗口中的所有其他小部件/组件实际上并不存在于操作系统中(它们没有窗口句柄),那么fpgui也可以提供帮助。fpgui工具包的初步设计就是基于这样的设计。再次,在源代码存储库中查找v0.4代码分支。在这个设计中,fpgui必须处理所有事情,创建mouseenter/mouseleave事件,转换容器组件的坐标系统,处理(假)组件焦点状态等等……是的,最初的设计是很多工作,但是你有一个非常可移植的框架,可以很容易地应用到其他操作系统。

    是的,fpgui完全是用对象pascal语言实现的,它使用免费的pascal编译器来提供跨平台支持。目前,fpgui运行在windows、linux(32&64位)、windows mobile和嵌入式linux(arm)设备上。

        6
  •  0
  •   Vegar    15 年前

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

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

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

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

    再说一遍-我不知道你到底想干什么。twincontrol是twincontrol的一个原因,但可能有一个解决方案,你想要什么,那将是什么…

        7
  •  0
  •   Yogi Yang 007    15 年前

    我想 fgGUI 也许能帮你。

    检查它的 Wiki 第一。

    我认为您可以在delphi中使用这个框架,因为它完全是用pascal编写的。实际上它是基于freepascal;)

    高温高压