【问题标题】:Drawing over Directdraw window在 Directdraw 窗口上绘图
【发布时间】:2013-10-14 08:16:00
【问题描述】:

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

当我尝试在游戏上绘制以显示我想要的信息时,游戏会更新自己的窗口并进行绘制。

我的第一种方法是使用带有 HWND_TOPMOST 的窗口位于游戏窗口的顶部,但它没有按预期工作,窗口只是不会越过游戏窗口并且不会显示信息。

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

我想要一些关于如何在不实际挂钩 DX 功能或类似的东西的情况下做到这一点的想法(因为我对 DX 知之甚少)。有什么方法可以在这个窗口上实际绘制以显示信息而不闪烁?

【问题讨论】:

  • 要在窗口游戏上绘制而不闪烁,建议您在临时位图上绘制文本,然后在窗口游戏上绘制此位图。
  • 您希望我们就如何破解我们一无所知的实现细节的程序提供建议?
  • 我想后缓冲不是这里的问题,因为我只调用了一个 TextOut 并且仍然闪烁。大卫,我很抱歉,但这不是关于实际破解游戏,我猜更多的是关于在 directdraw 窗口上绘图,但如果需要,我可以提供一些关于游戏本身的信息,如果你相信它会有所帮助。
  • 嗯,这在某种意义上肯定是黑客行为。无论如何,如果我们不知道游戏实际在做什么,就很难知道该建议什么。
  • Rising lands, 1997。游戏只能全屏运行,因为它很旧,我想在 win 7 上运行它会有很多问题(从内存管理到绘图,一切都不同)。可以在游戏绘制场景后绕道而行,但是我在 ASM 中编写游戏修复程序,并且使用 asm 完成所有这些工作会很痛苦......另一部分是 delphi,实际上写钩子和东西很糟糕像那样。我以前这样做过,但在较新的游戏中,HWND_TOPMOST 应该将我的窗口放在游戏上,但在这种情况下它不会。

标签: delphi assembly directx gdi


【解决方案1】:

您可以使用 unDelphiX 来获取执行 DirectX 的 Delphi 包。
你可以在这里下载包:http://www.micrel.cz/Dx/

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

绘图时不闪烁
消除闪烁的技巧是绘制到屏幕外表面,并在完成后“翻转”屏幕外表面。
翻转可以与 VerticalSync 同步,因此也没有撕裂。

演示
有一个演示,以毫秒为单位显示当前时间,没有任何闪烁。

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
为了在 Delphi XE2 中安装软件包,我必须将 DesignIDE 添加到 dpk 的 requires 子句中。像这样:

这将修复DesignIntf.dcu not found 错误。

全屏显示
如果你想做全屏,你可以在 DXDraw 的设置中启用它,但是注意:

如果您启用doFullScreen 而不启用doSelectDriver,您将收到interface not supported 错误。启用它们,一切都会好起来的。
请参阅:http://www.micrel.cz/Dx/history.rtf

不要忘记监听按键并在 ESC 上退出应用程序,否则你会卡在全屏模式。

【讨论】:

  • 现在正在测试,我什至在C++中启动了一个weapper来使用游戏的DD对象来显示信息,但这似乎更容易(和简单),会试一试,谢谢你的建议.一旦我完成测试,如果可行,我接受答案。
  • 对不起@Johan,但这只是利用表单本身,而不是预期的其他窗口:(
  • 你见过这个问题吗,它似乎解决了你的问题。 stackoverflow.com/questions/148275/…
  • 确实,一定会看一看,唯一的问题是 C# 部分,但我想没有什么我无法解决在 delphi/c++ 中编码
  • 另见:stackoverflow.com/questions/18279272/…code.google.com/p/transparent-canvas 我记得在 Delphi 中有一个演示,它在当前屏幕顶部显示错误,然后需要单击才能消失(不记得它叫什么)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
相关资源
最近更新 更多