【问题标题】:How to set a variable if any action is done (in Delphi)?如果完成任何操作(在 Delphi 中),如何设置变量?
【发布时间】:2011-07-27 04:50:50
【问题描述】:

我需要在 Delphi 2009 中以某种方式实现这一点:

用户点击按钮 2。如果用户的最后一个操作是点击按钮 1,那么我想做一件事,但如果用户的最后一个操作是别的,我想做另一件事。

显然,我设置了一个布尔变量:UserClickedOnButton1,并在单击按钮 1 时将其设置为 true,然后在按钮 2 的 OnButtonClick 事件中测试该变量。

我的问题是,当用户在点击按钮 2 之前执行任何其他操作(例如,鼠标按下、按键、箭头键、切换到另一个程序或其他任何操作)时,如何将其设置为 false。

...或者有没有我忽略的更简单的方法。

【问题讨论】:

  • “其他任何东西”非常模糊。例如,切换到另一个程序,最小化主窗口,这一切看起来像是你试图完成的一件非常模糊(未定义)的事情。请尽可能准确地编辑您的问题。想想后来出现的穷人,想知道你所说的“其他”是什么意思......
  • @Warren:基本上,除了点击按钮 2 之外所做的任何事情都应该取消点击按钮 1 发起的特殊操作。
  • 因此,包含此控件的主窗口失去焦点,以及任何鼠标在窗口内任何其他控件上的任何位置...
  • 如果所有被禁止的动作都有一个Taction,那么你可以使用一个TA​​ctionList。在 TAc​​tionList.onExecute 中,您可以编写代码以遵循所需的行为。但 NGLN 似乎已经采取了另一种很好的方式来效仿。只是想补充一下,这看起来像是一个 EasterEgg 实现...... o.o''
  • @EMBarbosa:不,不是复活节彩蛋,但这是一个有趣的想法。实际上,这是一种情况,其中一个按钮通过执行第二个按钮的第一部分来完成。所以我不想重复“第一部分”两次。

标签: delphi


【解决方案1】:

下面的代码似乎可以工作 (D7),但请根据您的具体情况检查。

type
  TButton = class(StdCtrls.TButton)
  private
    FClickedLast: Boolean;
    FNextButton: TButton;
  protected
    procedure WndProc(var Message: TMessage); override;
  public
    procedure Click; override;
    property ClickedLast: Boolean read FClickedLast write FClickedLast;
    property NextButton: TButton write FNextButton;
  end;

  TForm1 = class(TForm)

...

procedure TForm1.FormCreate(Sender: TObject);
begin
  Button1.NextButton := Button2;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if Button1.ClickedLast then
    Caption := Caption + ' +'
  else
    Caption := Caption + ' -';
  Button1.ClickedLast := False;
end;

{ TButton }

procedure TButton.Click;
begin
  inherited Click;
  if (FNextButton <> nil) and Focused then
    FClickedLast := True;
end;

procedure TButton.WndProc(var Message: TMessage);
begin
  if (FNextButton <> nil) and not (csDestroying in ComponentState) then
    case Message.Msg of
      CM_CANCELMODE,
      WM_KEYFIRST..WM_KEYLAST:
        FClickedLast := False;
      WM_KILLFOCUS:
        if TWMKillFocus(Message).FocusedWnd <> FNextButton.Handle then
          FClickedLast := False;
    end;
  inherited WndProc(Message);
end;

解释:

  • CM_CANCELMODE 处理鼠标在任何地方的点击,不会导致焦点改变,
  • WM_KEY* 处理所有关键事件,但也切换到另一个应用程序(有一个 WM_SYSKEYDOWN,否则 WM_KILLFOCUS 负责),
  • WM_KILLFOCUS 处理其他所有事情。

【讨论】:

  • @NGLN:您的答案很有潜力,并且是我一直在寻找的那种东西(即包含对单个例程的所有变量重置)。今晚回家后,我会检查它是否对我有用。
  • 这对于 WndProc 来说似乎很有用,因为您可能想在一个地方处理大量不同的消息。
  • @NGLN:似乎工作得很好。非常感谢。 Delphi有什么不能做的吗?
  • @NGLN:事实证明,您的代码:“if TWMKillFocus(Message).FocusedWnd FNextButton.Handle”帮助我解决了我遇到的另一个问题 - 识别当从其他东西中删除焦点时,项目集中。非常感谢。
【解决方案2】:

根据我的想法;除非您愿意用逻辑去跟踪所有(或至少所有可能不需要的)事件,否则这实际上是不可能的。

按键(Tab?)仍然可以有效地移动到下一个按钮并单击它;一个鼠标按下事件,如果它在第二个按钮上显然是好的,否则不是。在执行一大堆逻辑以减慢应用程序中的每个 keypress/mousedown/lostfocus 事件之前,您可能需要检查“第一个按钮是否被单击”。

一个想法可能是使用计时器,但这并不妨碍用户“快速”做其他事情。

Edt1:如果所有其他“非法”操作实际上都在做某事,那么第一个按钮上的 lostfocus 事件可能是一个开始?

【讨论】:

  • 这会在按钮2的onclick被触发AFAIK之前首先将变量的值设置为false,所以它有点没用。
  • 是的,如果你将它设置为 false onMouseDown /没有任何逻辑/它会。
  • @PtPazuzu:感谢您的尝试。你完美地表达了我遇到的问题,我想知道是否有一个简单的解决方案。
猜你喜欢
  • 1970-01-01
  • 2021-01-07
  • 2022-11-24
  • 1970-01-01
  • 2011-11-06
  • 1970-01-01
  • 2022-01-04
  • 2011-01-16
  • 1970-01-01
相关资源
最近更新 更多