Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Gameoverlay mittels API (https://www.delphipraxis.net/152918-gameoverlay-mittels-api.html)

RedShakal 12. Jul 2010 21:19

Gameoverlay mittels API
 
Hallo zusammen, über einen Link vom SwissDelphiCenter habe ich einen Desktop Overlay gefunden, mit dem es mir nach sehr langer suche endlich möglich war einen Text in einem Fullscreen DDraw game zu zeichnen.Das ganze funktioniert auf XP Vista und 7. Das Problem könnt ihr euch sicher denken: der Text flimmert.

Meine Frage: ist es möglich die Framerate des Spiels auszulesen und den Overlay entsprechend zu syncronisieren, damit es nichtmehr flimmert? Gleich vorweg: Das Spiel hat keinen Online Modus kein Anticheat und der Overlay ist auch nicht fürs Cheaten gedacht:wink:

Hier mal der Code den ich mir zusammenkopiert hab:oops:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, tlhelp32, ShellAPI;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    procedure WriteText( TransText:string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GetProcessID(Exename: string): DWORD;
var
  hProcSnap: THandle;
  pe32: TProcessEntry32;
begin
  result := 0;
  hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);
  if hProcSnap <> INVALID_HANDLE_VALUE then
  begin
    pe32.dwSize := SizeOf(ProcessEntry32);
    if Process32First(hProcSnap, pe32) = true then
    begin
      while Process32Next(hProcSnap, pe32) = true do
      begin
        if pos(Exename, pe32.szExeFile) <> 0 then
          result := pe32.th32ProcessID;
      end;
    end;
    CloseHandle(hProcSnap);
  end;
end;


function GetProcessHandleFromID(ID: DWORD): THandle;
begin
  result := OpenProcess(SYNCHRONIZE, False, ID);
  CloseHandle(result);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  hProcess: THandle;
  wf: DWORD;
begin
  hProcess := GetProcessHandleFromID(GetProcessID('Kknd2.exe'));
  if hProcess <> 0 then WriteText('Overlay test');
end;

procedure TForm1.WriteText( TransText:string);
var
  MyHand:HWND;
  MyDc:HDC;
  MyCanvas:TCanvas;
begin
  MyHand:=GetDesktopWindow;
  MyDc:=GetWindowDC(MyHand);
  MyCanvas:=TCanvas.Create;
  MyCanvas.Handle:=MyDC;
  BeginPath( MyCanvas.Handle);
  MyCanvas.Font.Color:=clBlue;
  MyCanvas.Font.Name:='Arial';
  MyCanvas.Font.Size:=30;
  SetBkMode( MyCanvas.Handle,TRANSPARENT);
  EndPath( MyCanvas.Handle);
  MyCanvas.TextOut( 200,50,TransText);
end;


end.

Medium 12. Jul 2010 21:27

AW: Gameoverlay mittels API
 
Selbst synchron wird das flimmern, da (DirectX/OGL-)Overlays sich nicht ohne API-Hook daran hindern lassen, sich darzustellen. D.h. du wirst immer einen kleinen Moment haben, in dem dein Text nicht da steht, und so timing-genau wird man das nicht wirklich über die reine WinAPI schaffen, dass es nicht mehr auffällt. Diese bietet auch so keine Möglichkeit die FPS auszulesen - das bieten die Grafik-APIs ja nicht einmal selbst von Haus aus an, und wird immer von den Programmen/Spielen selbst errechnet. Fraps macht das auch nur über's Hooken der Present-Methoden. Wenn das anders ginge, wäre der ganze Aufwand über API-Hooks ja nie angestellt worden ;)
Fazit: Entweder ne Ecke mehr Arbeit aufwenden, oder mit dem Geflimmer Freundschaft schließen.

cookie22 12. Jul 2010 21:33

AW: Gameoverlay mittels API
 
soweit ich mich erinnere ist das ganze unter dx 10 ungleich komplizierter als unter dx 9, bei dx 10 hat sich eine menge geändert.

Medium 13. Jul 2010 02:11

AW: Gameoverlay mittels API
 
Oh stimmt, das gute alte Present() wird da ja zu einer SwapChain - da hab ich so noch gar nicht drüber nachgedacht :shock:
(Hab mich nur darüber geärgert, dass ich sehr viel Initialisierungszeugs, welches ich unter/für DX9 grad frisch gelernt hab, gleich mal wieder über Bord werfen konnte :evil:)

Aphton 13. Jul 2010 11:46

AW: Gameoverlay mittels API
 
Vergiss nicht, die temporäre Klasseninstanz "MyCanvas" in WriteText freizugeben.
Ansonsten wächst nämlich deine Application im Interval von Timer1.Interval...

himitsu 13. Jul 2010 12:04

AW: Gameoverlay mittels API
 
Zitat:

Zitat von Aphton (Beitrag 1035100)
Vergiss nicht, die temporäre Klasseninstanz "MyCanvas" in WriteText freizugeben.
Ansonsten wächst nämlich deine Application im Interval von Timer1.Interval...

Oder man erstellt das Canvas nur einmal.

Folgendes nach OnCreate der Form und das MyCanvas.Free nach OnDestroy.
Delphi-Quellcode:
MyCanvas := TCanvas.Create;
MyCanvas.Handle := GetWindowDC(GetDesktopWindow);

RedShakal 13. Jul 2010 17:14

AW: Gameoverlay mittels API
 
Der Code war eigentlich eher als temporärer test gedacht mit der absicht zu prüfen ob es überhaupt so klappt wie ich mir das vorstelle. Ich suche bereits seit einer ewigkeit nach einem funktionierendem flimmerfreien DDraw Overlay hook bisher leider erfolglos :(

MasterTobi 13. Jul 2010 22:26

AW: Gameoverlay mittels API
 
da bist du nicht allein, suche auch schon ewigkeiten -.-


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz