Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 德尔福;而";当鼠标未移动到FireMonkey应用程序上时,性能会降低_Delphi_Opengl_Firemonkey_Onkeydown - Fatal编程技术网

Delphi 德尔福;而";当鼠标未移动到FireMonkey应用程序上时,性能会降低

Delphi 德尔福;而";当鼠标未移动到FireMonkey应用程序上时,性能会降低,delphi,opengl,firemonkey,onkeydown,Delphi,Opengl,Firemonkey,Onkeydown,我正在用Delphi+openGL玩一点。因为我很懒,所以我想用FireMonkey为我制作一个表单。 所以我制作了一个FireMonkeyHD应用程序,初始化了GL,渲染了一个基本的立方体。。。发现了一些奇怪的行为。当我不移动鼠标时,我的速度大约为10FPS。当我移动鼠标时,性能很容易提高到500FPS甚至更高。那会是什么? *注意:我在主线程中使用onKeyDown事件开始渲染… 为了更好地理解,请看两张图片: 一些代码: unit Unit1; interface uses { .

我正在用Delphi+openGL玩一点。因为我很懒,所以我想用FireMonkey为我制作一个表单。
所以我制作了一个FireMonkeyHD应用程序,初始化了GL,渲染了一个基本的立方体。。。发现了一些奇怪的行为。当我不移动鼠标时,我的速度大约为10FPS。当我移动鼠标时,性能很容易提高到500FPS甚至更高。那会是什么?
*注意:我在主线程中使用onKeyDown事件开始渲染…

为了更好地理解,请看两张图片:

一些代码:

unit Unit1;

interface

uses
{ ... }
;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
      Shift: TShiftState);
  private
    degen
    : IDeGEn;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.FormCreate(Sender: TObject);
var
  DeGEnFactory
  : TDeGEnFactory;
begin
  { ... }
  // Load DeGEn
  degen := DeGEnFactory.newDeGEn(WindowHandleToPlatform(Form1.Handle).Wnd);

  // Initialize
  degen.get3D.init(600, 800);
  degen.get3D.setOnRender(function : Boolean
  var
    v3d
    : R3DVector;
  begin
    Result := true;
    self.Caption := IntToStr(degen.get3D.getFPS);
    v3d.z := 0.01;
    degen.get3D.getCamera.move(v3d);
    degen.get3D.renderTest;
  end);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // Shut down DeGEn
  { ... }
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
  Shift: TShiftState);
begin
  // Start rendering
  degen.startRendering;
end;

end.

startRendering
看起来是这样的:

procedure TDeGEn.startRendering;
var
  msg
  : TMsg;
begin
  if isRendering then
  begin
    Exit;
  end;

  isRendering := true;
  while GetMessage(msg, 0, 0, 0) do
  begin
    TranslateMessage(msg);
    DispatchMessage(msg);

    if not degen3D.render then
    begin
      Break;
    end;
  end;

  isRendering := false;
end;


正如您可能很容易注意到的,摄影机只是以与FPS相关的速度离开立方体。我还将FPS显示为表单标题。

获取消息的
等待消息。
如果不移动鼠标,很少有消息进入消息队列,渲染速度会很慢,因为CPU一直在等待GetMessage返回

当您移动鼠标时,会创建大量消息;消息队列已满,GetMessage几乎立即返回

请注意,自Windows 3.1以来,没有必要这样做messageloop

还要注意,Microsoft警告不要像这样实现messageloop。
发件人:

因为返回值可以是非零、零或-1,所以请避免类似这样的代码 这:

while(GetMessage(lpMsg,hWnd,0,0))…

如果hWnd是一个 无效的参数(例如引用已被删除的窗口) 销毁)意味着此类代码可能导致致命的应用程序错误。 相反,请使用如下代码:

无论如何,没有必要这样做循环。
相反,在表单上放置计时器,并将代码放入
OnTimer
事件中

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  //DoRendering
end;
如果正常的计时器太慢,就会有很多高分辨率的计时器。JVCL完成了,unDelphiX也完成了。
请参见此处:
或在此:

在CPU密集型循环中处理Windows消息 我们不再使用messageloop了(从Delphi 1.0开始就没有了)。
如果发现由于循环占用所有CPU时间而导致应用程序无响应,请改用
Application.ProcessMessages

WM\U计时器消息的优先级较低
如果使用默认计时器,将遇到不可靠性问题。
这是因为Windows将
WM_TIMER
消息(TTimer查找的消息)视为低优先级。
如果Windows忙于其他任务,它会将多条等待的
WM_TIMER
消息压缩为一条消息,以避免造成计时器消息积压。
它对
WM_PAINT
消息执行相同的操作。
见:


避免这种情况的一个技巧是使用高分辨率计时器构造循环(这不取决于消息循环),或者使用带有
Application.ProcessMessages
sleep()
延迟的简单无止境循环

获取消息
等待消息。
如果不移动鼠标,很少有消息进入消息队列,渲染速度会很慢,因为CPU一直在等待GetMessage返回

当您移动鼠标时,会创建大量消息;消息队列已满,GetMessage几乎立即返回

请注意,自Windows 3.1以来,没有必要这样做messageloop

还要注意,Microsoft警告不要像这样实现messageloop。
发件人:

因为返回值可以是非零、零或-1,所以请避免类似这样的代码 这:

while(GetMessage(lpMsg,hWnd,0,0))…

如果hWnd是一个 无效的参数(例如引用已被删除的窗口) 销毁)意味着此类代码可能导致致命的应用程序错误。 相反,请使用如下代码:

无论如何,没有必要这样做循环。
相反,在表单上放置计时器,并将代码放入
OnTimer
事件中

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  //DoRendering
end;
如果正常的计时器太慢,就会有很多高分辨率的计时器。JVCL完成了,unDelphiX也完成了。
请参见此处:
或在此:

在CPU密集型循环中处理Windows消息 我们不再使用messageloop了(从Delphi 1.0开始就没有了)。
如果发现由于循环占用所有CPU时间而导致应用程序无响应,请改用
Application.ProcessMessages

WM\U计时器消息的优先级较低
如果使用默认计时器,将遇到不可靠性问题。
这是因为Windows将
WM_TIMER
消息(TTimer查找的消息)视为低优先级。
如果Windows忙于其他任务,它会将多条等待的
WM_TIMER
消息压缩为一条消息,以避免造成计时器消息积压。
它对
WM_PAINT
消息执行相同的操作。
见:


避免这种情况的一个技巧是使用高分辨率计时器构造循环(这不取决于消息循环),或者使用带有
Application.ProcessMessages
sleep()
延迟的简单无止境循环

这是非常旧的Windows应用程序中的常见行为。除非屏幕被标记为“脏”,否则他们不会重新绘制屏幕。将鼠标移到屏幕的某个部分是一种确定的方法,可以将控件标记为脏并强制重新绘制。在您的情况下,这可能不是罪魁祸首,但我怀疑它某种程度上与您的消息泵有关,移动光标会增加您的消息泵中出现绘图所需内容的频率