Delphi 在Directdraw窗口上绘图

Delphi 在Directdraw窗口上绘图,delphi,assembly,directx,gdi,Delphi,Assembly,Directx,Gdi,我一直在做一个修复旧游戏的项目,并最终获得了新的想法,添加了一些关于游戏世界的酷额外信息,实时跟踪了一些重要信息,这些信息是游戏本身在没有实际原因的情况下对用户隐藏的,并遇到了这个问题: 当我试图在游戏上画图时,为了显示我想要的信息,游戏会更新自己的窗口并画图 我的第一个方法是使用HWND_TOPMOST的窗口位于游戏窗口的顶部,但它没有按预期工作,窗口无法越过游戏窗口,也无法显示信息 第二种方法是使用GDI函数,比如TextOut,文本在那里,但会闪烁很多,强迫它在短时间内绘制会占用太多内存

我一直在做一个修复旧游戏的项目,并最终获得了新的想法,添加了一些关于游戏世界的酷额外信息,实时跟踪了一些重要信息,这些信息是游戏本身在没有实际原因的情况下对用户隐藏的,并遇到了这个问题:

当我试图在游戏上画图时,为了显示我想要的信息,游戏会更新自己的窗口并画图

我的第一个方法是使用HWND_TOPMOST的窗口位于游戏窗口的顶部,但它没有按预期工作,窗口无法越过游戏窗口,也无法显示信息

第二种方法是使用GDI函数,比如TextOut,文本在那里,但会闪烁很多,强迫它在短时间内绘制会占用太多内存


我想知道如何做到这一点,而不实际挂钩DX函数或类似的东西,因为我知道很少的DX。有没有办法在这个窗口上画图来显示信息而不闪烁?

您可以使用unDelphiX获得一个执行DirectX的Delphi包。 您可以在此处下载该软件包:

它完全是最新的,使DirectX几乎像标准GDI一样工作

无闪烁绘图 消除闪烁的诀窍是绘制屏幕外表面,并在完成后翻转视图中的屏幕外表面。 翻转可以与垂直同步同步,因此也不会撕裂

演示 有一个演示以毫秒为单位显示当前时间,不闪烁

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Menus, DXClass, DXDraws;

type
  TMainForm = class(TDXForm)
    DXDraw: TDXDraw;
    DXTimer: TDXTimer;  //Precision timer. 
    procedure DXDrawFinalize(Sender: TObject);
    procedure DXDrawInitialize(Sender: TObject);
    procedure DXTimerTimer(Sender: TObject; LagCount: Integer);
  end;

var
  MainForm: TMainForm;

implementation

uses MMSystem;

{$R *.DFM}

procedure TMainForm.DXDrawInitialize(Sender: TObject);
begin
  DXTimer.Enabled := True;
end;

procedure TMainForm.DXDrawFinalize(Sender: TObject);
begin
  DXTimer.Enabled := False;
end;

procedure TMainForm.DXTimerTimer(Sender: TObject; LagCount: Integer);
var
  formattedDateTime: string;
begin
  if not DXDraw.CanDraw then exit;

  DXDraw.Surface.Fill(0);

  with DXDraw.Surface.Canvas do  //Draw to offscreen surface.
  begin
    Brush.Style := bsClear;
    Font.Color := clWhite;
    Font.Size := 30;
    DateTimeToString(formattedDateTime, 'hh:nn:ss.zzz', Now);
    Textout(30, 30, formattedDateTime);

    Release; {  Indispensability  }
  end;

  DXDraw.Flip;  //Flip the offscreen surface to screen, no flicker :=)
end;

end.
在XE2中安装unDelphiX 为了在DelphiXe2中安装软件包,我必须将DesignIDE添加到dpk的requires子句中。像这样:

这将修复DesignIntf.dcu未找到错误

全屏显示 如果要进行全屏显示,请在DXDraw的设置中启用,但请注意:

如果在未启用doSelectDriver的情况下启用doFullScreen,则会出现“接口不受支持”错误。两个都启用,一切都会很好。 见:‎


别忘了听按键,然后用ESC或其他方式退出应用程序,否则你会被困在全屏模式。

要在窗口游戏上画图而不闪烁,我建议你在临时位图上画图,然后在窗口游戏上画这个位图。你想让我们给你一些建议,如何破解一个我们对其实现细节一无所知的程序吗?我想Backbuffering不是问题所在,因为我只调用了一个TextOut,它仍然在闪烁。大卫,我很抱歉,但这不是真正的黑客游戏,我想更多的是在directdraw窗口上画画,但如果需要的话,我可以提供一些关于游戏本身的信息,如果你相信这会有所帮助的话。嗯,从某种意义上说,这肯定是黑客行为。不管怎么说,如果我们不知道游戏到底在做什么,很难知道该建议什么。上升的土地,1997年。游戏只在全屏上运行,因为它很旧,我想在Win7上运行它有很多问题,从内存管理到绘图,一切都不一样。可以在游戏结束后绕道绘制场景,但我用ASM编写游戏修复程序,用ASM做所有这些工作都会很痛苦。。。另一部分是delphi,实际上编写钩子之类的东西很糟糕。我以前做过,但是在新游戏中,HWNDN-TopMax应该把我的窗口放在游戏的上面,但是在这种情况下它不需要。现在就测试它,我甚至在C++中开始了一个WEMAP游戏,用游戏的DD对象来显示信息,但是这看起来简单和容易,试试看,谢谢你的建议。一旦我完成测试,如果有效,我就接受答案。很抱歉@Johan,这只利用表单本身,而不是预期的其他窗口:你看到这个问题了吗,它似乎解决了你的问题。事实上,我可以肯定地看一看,唯一的问题是C部分,但没有什么是我不能用delphi/C++编写的,我想也看到了:我记得delphi中有一个演示,在当前屏幕的顶部显示了bug,然后需要单击它才能离开,但我记不起它的名称。