DELPHI 10.3-循环,直到按下键时出现小问题

问题描述 投票:0回答:1

大家好,我编写了一个非常简单的应用程序,其中必须等待用户按下某个键(例如F2)才能继续进行处理。按下按钮的等待周期可以完美地工作,但是我需要帮助的问题是:如果在按下按钮的等待周期中,我单击了另一个应用程序,那么我的应用程序将失去焦点,并且我将无法重新获得控制权。即使单击应用程序的任何部分,窗体的标题也始终保持灰色,应用程序仍在等待按键的压力,如果我按所需的键,显然什么也没发生。如何重新获得对应用程序的控制权?我以为我会在while循环中放入诸如SetFocus,StayOnTop,SetForegroundWindow等的指令,以始终保持我的应用程序处于活动状态,但我无法合并任何内容……代码如下:

var

  Form2: TForm2;
  mkey: word; 

implementation

{$R *.dfm} 

procedure TForm2.FormActivate(Sender: TObject);

begin

  label1.Visible:= false;

  mkey:= 0;

  keyPreview:= true;

  while mkey <> VK_F2 do begin

    label1.Visible:= true;

    label1.Caption:= datetimetostr(now);   // for example

    application.ProcessMessages;

  end;

  label1.Visible:= false;

end; 

procedure TForm2.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);

begin

  mkey:= key;

end;

end.
loops delphi while-loop key keypress
1个回答
0
投票

我不想听起来刺耳,但不幸的是,您的设计存在根本缺陷。

如注释中所示,图形Windows应用程序-尤其是VCL应用程序-是事件驱动的。 (在幕后,这要归功于消息泵,但是VCL开发人员通常不需要关心这些细节。特别是,新的Delphi开发人员通常不了解底层消息泵,并且仍然可以编写高质量的GUI。如果小心的话。)

因此,例如,等待使用显式循环按下键几乎总是错误的。同样,必须调用Application.ProcessMessages是(主要)设计缺陷的明显信号(在许多情况下(但不是在此情况下,解决方案是添加新线程))。最后,如果看似基本的任务导致您需要添加代码来解决问题(例如SetFocus),则应始终问自己是否有更好的解决方案。

我不知道您要做什么,但是以下示例可能会有所帮助。

  1. 创建一个新的VCL应用程序。给主窗体起一个好名字,例如使用对象检查器frmMain。在代码编辑器中,将私有字段FStarted: Boolean添加到表单类。由于这是类中的字段,因此将对其进行初始化(因为它是BooleanFalse)。¹

      private
        FStarted: Boolean;
    
  2. 向表单添加TLabel控件。使用对象检查器将其名称设置为lblMainText。将其字体设置为外观令人愉悦的²,并将其标题设置为Press F2 to begin.

  3. 在表单的OnKeyDown事件处理程序中,添加以下代码³:

    procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if (Key = VK_F2) and not FStarted then
      begin
        MessageBeep(MB_ICONASTERISK);
        lblMainText.Caption := 'Let''s get to work!';
        FStarted := True;
      end;
    end;
    
  4. 运行应用程序。

Screenshot of the application immediately after startup.

按F2后:

Screenshot of the application after F2 has been pressed.

[注意,再次按F2键不会执行任何操作;您已经“启动”了系统。

显然,这个小答案不会教您编写VCL应用程序所需的全部知识。它只触及您需要知道的内容的0.1%。要了解更多信息,我强烈建议购买一本有关Delphi编程的书(特别是有关在Delphi中编写Win32应用程序的书)。

¹在Delphi中,全局变量和类成员被初始化(为00.0Falsenil等)。但是,局部变量永远不会初始化(除非它们属于托管类型)。

根据Segoe UI

²Microsoft Windows User Interface Guidelines是一个不错的选择。实际上,您可以为form本身使用此字体;然后所有子控件将自动继承此字体设置。

³仅在表单本身具有焦点(例如,没有子控件)的情况下才有效。即使儿童控件具有焦点,也要使其正常工作,我最好的建议是使用TActionList。它们真的很有用。

© www.soinside.com 2019 - 2024. All rights reserved.