【问题标题】:Arrow key not working in component箭头键在组件中不起作用
【发布时间】:2011-04-12 08:30:23
【问题描述】:

我使用 Gecko SDK,这是一个允许您查看网页的组件。
我使用这个组件来创建一个 html 编辑器。

在停止编辑网页时会出现此问题。
问题是箭头键和选项卡不适用于我的组件。我试图找到这个问题的答案,但我没有找到答案。我找到了一个轨道here,但是这个功能不起作用。

函数Movement (dx, dy) 不存在。谢谢你帮我解决了这个问题。

Procedure Tform1.TraiteMessages(Var msg : TMsg; Var Handled: boolean);
var
  dx, dy : integer;
begin   dx: 0; dy := 0; 
  With msg do
  begin
    IF Message = WM_KEYDOWN then
    Case  wparam of
      VK_LEFT  : dx := -1;
      VK_RIGHT : dx :=  1;
      VK_UP    : dy := -1;
      VK_DOWN  : dy :=  1;
    end;
  end;
  IF (dy = 0) AND (Dx = 0) then Handled := false else
  begin
    handled := true;     // message traité
    Mouvement(dx, dy)    // exécution du tracé 
  end;
end;

【问题讨论】:

  • 不要关闭,这个问题很真实,只是有点太法语了,不适合 Stack Overflow。
  • 请稍等,让我在这里开始 Google 翻译,然后....瞧!
  • 恕我直言:考虑用英语提问以吸引更广泛的受众。
  • @Georg Fritzsche:如果你考虑标签cdelphivbpascal,它似乎是多语言的。
  • @phi: 好吧,那我们用 C 语言谈谈吧 ;)

标签: delphi pascal custom-component


【解决方案1】:

将此添加到组件的类中:

procedure HandleDlgCode(var Msg:TMessage); message WM_GETDLGCODE;

然后在实现部分:

procedure TComponentClass.HandleDlgCode(var Msg:TMessage);
var
  M: PMsg;
begin
  Msg.Result := DLGC_WANTALLKEYS or DLGC_WANTARROWS or DLGC_WANTCHARS or DLGC_HASSETSEL;
  if Msg.lParam <> 0 then
    begin
      M := PMsg(Msg.lParam);
      case M.message of
        WM_KEYDOWN, WM_KEYUP, WM_CHAR:
        begin
          Perform(M.message, M.wParam, M.lParam);
          Msg.Result := Msg.Result or DLGC_WANTMESSAGE;
        end;
      end;
    end
  else
    Msg.Result := Msg.Result or DLGC_WANTMESSAGE;
end;

我刚刚从我自己的数字编辑器中复制粘贴了这段代码,所以它可以工作。

【讨论】:

  • 你自己不要调用这个方法。当用户在您的文本编辑器中键入任何内容时,Windows 将首先将 WM_GETDLGCODE 发送到您的窗口,以查看它是否要处理它。通常控件不需要处理箭头键、tab 键、enter 和 escape,因此 Windows 可以将它们用于对话框导航。对于需要处理这些键的罕见控件,您需要提供 WM_GETDLGCODE 处理程序以让 Windows 知道您需要这些键。 "message WM_GETDLGCODE;" 告诉 Delphi 这是 WM_GETDLGCODE 的处理程序。
  • DLGC_WANTTAB 添加到程序开头的列表中。
【解决方案2】:

这不是它的完成方式!
这就是我们在 1996 年德尔福之前的做法。
不需要这种复杂的 Windows 东西。

您正在制作编辑器。
Delphi 已经内置了 2 个编辑器。

  1. TMemo
  2. TRichEdit.

从 TMemo 作为你的父母开始,你有一个现成的编辑器,不需要捕获光标键。

interface

type
  TMyComponent = class(TMemo)   
  //                   ^^^^^^^^^^^^^^^^^^^^<<- use this as your parent class

protected
    procedure KeyPress(var Key: Char); override 
  ...

 implementation

 procedure TMyComponent.KeyPress(var Key: Char);
 begin
   inherited;
   //it works just like this, TMemo does everything.
 end;

事实上,您可以忽略 KeyPress 并开始做其他事情。

无需使用低级代码。你这样做太复杂了

得到一本delphi组件设计的书。即使对于较旧的 Delphi,也没有太大变化。 每花一小时阅读一本书,就可以节省 20 小时的编码时间。

祝你好运。

【讨论】:

  • Johan,但我在一个不基于 TMemo 的组件上工作了几个月。实际上,这是一个让您可以轻松查看和编辑网页的组件
  • 基于哪个组件?请告诉我们名字。
  • GeckoSDK 使用 OLE、COM 和接口,代码非常复杂。阅读 David Box 的 Essential COM ISBN 0-201-63446-5
  • 投了反对票,因为这并不能真正帮助那些遇到同样问题的人,这确实是一个普遍的问题。
【解决方案3】:
Procedure Tform1.TraiteMessages(Var msg : TMsg; Var Handled: boolean);
var
  dx, dy : integer;
begin
  dx := 0;
  dy := 0; 
  With msg do
  begin
    IF Message = WM_KEYDOWN then
    begin
      Case  wparam of
        VK_LEFT  : dx := -1;
        VK_RIGHT : dx :=  1;
        VK_UP    : dy := -1;
        VK_DOWN  : dy :=  1;
      end;
    end;
  end;
  Mouvement(dx, dy);
  Handled := ((dy <> 0) or (dx <> 0));
end;

这清理了您的方法...现在,您应该在 IF 语句上放置一个断点,并在您的 Case 条件上放置另一个断点,以确定您的消息挂钩是否被触发,以及消息是否正在被处理是你所期望的。

您的组件是否正确捕获关键事件?您是否有另一个关注的视觉组件?您是否将表单的“KeyPreview”属性设置为 True?

您可能还想尝试使用 TApplicationEvents 控件来处理您的关键消息挂钩(如果您的组件是非可视的)。

查看我的 SVN 存储库中的 this unit(用户名和密码都是“anon”,不带引号),因为它演示了如何拦截和处理非可视组件上的关键输入。

希望这会有所帮助,祝你好运!

【讨论】:

  • 我猜你应该提供你自己的Mouvement;您所展示的是一种通过一个程序处理所有 4 个方向键的通用方法。声明你自己的带有 2 个整数参数的 Mouvement 过程 (procedure Mouvement(const dx, dy:Integer))
  • 网络浏览器听起来不像是非视觉事件。任何基于 TWinControl 的组件都将具有所有这些内置功能。
猜你喜欢
  • 2012-04-11
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-29
相关资源
最近更新 更多