3

在我的 Delphi 2009 应用程序中,我有这个窗口:

在此处输入图像描述

它有一个 TPageControl,上面有一个 TTabSheet 以及底部的按钮,可以在所有工作表上操作。

TTabSheet 的左侧是一个 TElXTree(LMD 的树/网格组件),而 TTabSheet 的右侧是一个 TPanel,其中包含特定于此工作表的按钮。

当我在 TElXTree 中选择了一行并单击任一组按钮中的任何按钮时,这些按钮都可以正常工作。

现在在 TElXTree 中,标有“文本”的列可以使用 TElXtree 提供的 Inplace-Editor 进行编辑。当我单击文本时,它会进入编辑模式。

在编辑模式下,当我单击 TElXTree 中的任意位置(例如在复选框上)时,它将退出编辑器并处理命令(即选中或取消选中复选框)。但是,在编辑模式下,当我单击任一组按钮中的任何按钮时,它只会退出就地编辑器而不处理该按钮。然后我必须再次单击该按钮来处理该按钮。

是否有一些我在这里没有做或不理解的简单事情可以让我单击其中一个按钮并允许它退出我的就地编辑器并处理按钮?


跟进:

感谢@NGLN 的回答,我得到了解决方法。我使用了他的 Application.OnMessage 方法,我以前一直使用它来处理一些拖放代码。我不得不做一些改变,这就是我想出的:

procedure TMainForm.AppMessageHandler(var Msg: TMsg; var Handled: Boolean);
var
  P: TPoint;
begin
  if Msg.message = WM_LBUTTONDOWN then
    if Screen.ActiveControl <> nil then
      if Screen.ActiveControl.ClassNameIs('TElInpEdit') then
        begin
          GetCursorPos(P);

         { When in the inplace editor, I need to go to its parent ElXTree }
         { because the ElXTree does not have the problem. }
         { Only components outside the ElXTree do }
          with Screen.ActiveControl.Parent do
            if not PtInRect(ClientRect, ScreenToClient(P)) then begin

             { The WM_Killfocus didn't work for me, but it gave me this idea: }
             { 1. Complete the operation, and 2. Simulate the mouse click }
              InplaceEdit.CompleteOperation(true);
              Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
              Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

             { Then skip the regular handling of this WM_LBUTTONDOWN }
              Handled := true;
            end;
        end;
end;
4

2 回答 2

1

它确实看起来像一个错误。两种可能的(讨厌的)解决方法:

通过 Application.OnMessage:

procedure TMainForm.ApplicationEventsMessage(var Msg: tagMSG;
  var Handled: Boolean);
var
  P: TPoint;
begin
  if Msg.message = WM_LBUTTONDOWN then
    if Screen.ActiveControl <> nil then
      if Screen.ActiveControl.ClassNameIs('TElInpEdit') then
      begin
        GetCursorPos(P);
        with Screen.ActiveControl do
          if not PtInRect(ClientRect, ScreenToClient(P)) then
            Perform(WM_KILLFOCUS, 0, 0);
      end;
end;

或者子类化组件:

type
  TElXTree = class(ElXTree.TElXTree)
  private
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  end;

  TForm1 = class(TForm)
    ElXTree1: TElXTree;
    ...

procedure TElXTree.CMMouseLeave(var Message: TMessage);
var
  P: TPoint;
begin
  GetCursorPos(P);
  if not PtInRect(ClientRect, ScreenToClient(P)) then
    if Screen.ActiveControl <> nil then
      if Screen.ActiveControl.ClassNameIs('TElInpEdit') then
        Screen.ActiveControl.Perform(WM_KILLFOCUS, 0, 0);
  inherited;
end;

注意:这不是首选,因为它会改变组件的行为:只需将鼠标悬停在网格外即可关闭就地编辑器。但我添加它是因为它可能会将其他人带到其他解决方案。

于 2011-06-28T19:41:21.603 回答
0

这可能是一个焦点问题。查看您在表单的 OnExit OnEnter 方法中编写的代码。

于 2011-06-28T14:04:53.037 回答