delphi - 捕获任何 VCL 组件上的鼠标单击,并确定其 .Tag 值

标签 delphi

我正在使用自制的翻译工具。 (下次我将使用其中一个库,如下所述:delphi translation tool。)

我的翻译人员提示翻译一长串字符串很困难,因为他们没有在上下文中(在它们出现的屏幕上)看到它们。

一位翻译提出了一个很好的建议,他应该能够单击一个组件来更改其文本。我可以实现这个如果我可以找到一种方法来 Hook 程序范围内的事件,这样当用户在按住 CTRL 键的同时单击组件时,就会调用事件处理程序。事件处理程序将确定组件是否具有 .Caption 属性,如果有,则获取 Tag 组件的值(然后允许一些用户输入。)

(每个可翻译组件在其标签中都有唯一的整数,我用它来查找组件的 .Caption。)

关于如何解决这个问题有什么建议吗?这超出了我的能力范围。我需要类似表单的 KeyPreview 之类的东西,但是对于鼠标单击,它可以确定单击了哪个 VCL 组件,并确定它的 .Tag 值。

汤姆

编辑:

根据 David H. 的建议,我收到的唯一事件是应用程序获得焦点或失去焦点时。我做错了什么?

    function TForm1.AppHookFunc(var Message : TMessage) : Boolean;
    begin
      Result := FALSE;
      inc(i); outputdebugstring(Pchar(inttostr(i) + ': ' + IntTostr(Message.msg)));
      if Message.Msg = WM_MBUTTONDOWN then
        begin      Beep;
        //...DoSomething...
        //Result := True;
        end;
    end;

    procedure TForm1.FormCreate(  Sender: TObject);
    begin
      Application.HookMainWindow(AppHookFunc);
    end;

    procedure TForm1.FormDestroy(
      Sender: TObject);
    begin
      Application.UnHookMainWindow(AppHookFunc);
    end;

编辑2

我快到了!但 FindDragTarget 很少返回除 nil 之外的任何内容。如果我制作一个巨大的按钮覆盖大部分控件,有时我可以让它工作。收到的 tagMSG 中的 X、Y 坐标是相对于控件的。我本来希望它们与表格相关。我是否仍在使用与应有的不同的事件 Hook ?任何建议:

  procedure TForm1.ApplicationEvents1Message( var Msg: tagMSG;
                                              var Handled: Boolean);
  var
    Target: TControl;
    Point: TPoint;
  begin
    Handled := FALSE;
    if (Msg.Message = WM_LBUTTONDOWN) And isAltDown then
      begin
        Point.X := LongRec(Msg.lParam).Lo;
        Point.Y := LongRec(Msg.lParam).Hi;
        Target := FindDragTarget( Point, {AllowDisabled=}TRUE);
        if Assigned(Target) then
          begin
            if Target Is TButton then
              outputdebugString(Pchar(TButton(Target).Caption));
          end
        else
          outputdebugstring(Pchar(IntToStr(Point.X) + ', ' + IntToStr(Point.Y)));
      end;
  end;

最终编辑:

我更改了上面的代码以使用 GetCursorPos 而不是 Msg.lParam。现在正在工作。很酷!太棒了!

感谢你们的帮助!

最佳答案

我假设这是一个 VCL 应用程序。对于 FireMonkey 来说这是行不通的。

  1. 添加 Application.OnMessage 事件处理程序。
  2. 在事件处理程序中查找 WM_LBUTTONDOWNWM_LBUTTONUP 并检查修改键状态是否符合您的要求,例如CTRL 已按下。
  3. 调用 FindDragTarget传递与鼠标事件关联的位置。如果确实存在的话,这将为您提供鼠标控制(即检查 nil)。
  4. 对该控件执行您想要的任何操作。

关于delphi - 捕获任何 VCL 组件上的鼠标单击,并确定其 .Tag 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8083445/

相关文章:

delphi - 如何创建带有滚动条且支持子菜单的弹出菜单

Delphi 7 调用 DelphiXE2 dll 导致宽字符串损坏

ios - 如何在 IOS Delphi 上的 TWebbrowser 中设置用户代理

multithreading - 如何通过多线程绘画到 TBitmap

python - 如何使用 Python ctypes 表示打包的 Delphi 记录?

database - XE6 Datasnap 向导不可用

database - TParams.ParamRef 有什么用?

delphi - 最初为什么创建 TDataSource?

delphi - 如何使用 webCal 发布日历

.net - 在 Visual Studio 中进行调试和不进行调试时,.NET 程序的行为有何不同?