Einzelnen Beitrag anzeigen

StefanG

Registriert seit: 23. Feb 2006
74 Beiträge
 
#1

Text in DirectX Spiel anzeigen

  Alt 28. Feb 2007, 08:27
Hallo zusammen,

ich habe folgendes Problem. Ich will in einem Spiel einen bestimmten Text anzeigen. Das Spiel nutzt DirectX und wenn ich einfach den Text mit GetDC und SetText setze, dann flackert die Schrift fürchterlich.

Wie man aber an Programmen wie Teamspeakoverlay oder Fraps sieht, geht das auch anders. Beim Nachforschen habe ich erfahren, dass man dafür API Hooks verwenden muss um über DirectX Methoden, den Text anzeigen zu lassen.

Weitere Suche führte mich zu der Funktion DrawText (in ID3DXFont). Die geeignete stelle, diesen Text zu setzen sollte wohl die DirectX-Funktion "Present" sein. Hier sage ich mal gleich, dass ich mich bis gestern noch garnicht mit DirectX oder OGL beschäftigt habe.

Nun denn, da Present keine Funktion ist, die aus der Dll exportiert wird, sondern ein Teil des IDirect3DDevice Interfaces ist, kann man die Adresse nicht einfach mit GetProcAddress bestimmen, man musste das Device haben. Also habe ich erst die Funktion Direct3DCreate9 gehookt um das IDirect3D9 Interface zu bekommen und damit CreateDevice9 hooken zu können.

Anschließend konnte ich mit dem erhaltenen IDirect3DDevice9 die Funktion Present hooken.
Soweit, so gut. Die Hooks scheinen soweit alle zu funktionieren. Zum Testen habe ich das Programm dxdiag verwendet.
Dass der Hook funktioniert merke ich daran, dass das Programm 1) nicht abstürzt, 2) keinen Bluescreen erzeugt und 3) von mir gesetzte MessageBoxen in den einzelnen Funktionen aufgerufen werden.

Das Problem liegt jetzt aber im Anzeigen von Text. Ich bin folgendermaßen vorgegangen :

In der Funktion CreateDevice9 erstelle ich den Font vom Typ ID3DXFont.

Delphi-Quellcode:
function CreateDevice9Callback(self, adapter, devType, wnd, flags, params, device: Pointer) : dword; stdcall;
begin
  font := nil;
  result := CreateDevice9Next(self, adapter, devType, wnd, flags, params, device);
  if font = nil then
  begin
    D3DXCreateFont(IDirect3DDevice9(device^),
                   20,
                   20,
                   0,
                   1,
                   false,
                   ANSI_CHARSET,
                   OUT_DEFAULT_PRECIS,
                   DEFAULT_QUALITY,
                   DEFAULT_PITCH,
                   'Arial',
                   font);
    myColor := D3DCOLOR_RGBA(255,0,0,255);
    font.PreloadCharacters(0,255);
  end;
  if result = 0 then begin
    if @PresentNext = nil then
    begin
      HookCode(GetInterfaceMethod(device^, 17), @PresentCallback, @PresentNext)
    end else
      RenewHook(@PresentNext);
  end;
end;
Die übergebene Farbe wird in einer Globalen Variable gespeichert....genauso wie eben der Font
Setzen will ich den Text jetzt in meiner Present Callback funktion :

Delphi-Quellcode:
function PresentCallback(self : Pointer; const SourceRect, DestRect : PRect; const DestWindowOverride : HWND; DirtyRegion : PRgnData) : HResult; stdcall;
begin
  messageBox(0,'Present','',MB_OK);
  result := PresentNext(self,SourceRect,DestRect,DestWindowOverride,DirtyRegion);
  ShowText(50,50,'test',myColor);
end;
die MessageBox wird ausgeführt. ShowText sieht folgendermaßen aus :

Delphi-Quellcode:
procedure ShowText(x,y: Integer; s: String; col: TD3DColor);
var
  rect : TRect;
begin
  messageBox(0,'ShowText','',MB_OK);
  rect.Top := y; rect.Left := x;
  rect.Bottom := y+1; rect.Right := x+1;
  if @font <> nil then
    font.DrawTextA(nil,PChar(s),Length(s),rect,DT_NOCLIP,myColor);
end;
Es gibt keinerlei Fehler und der Drehende Würfel (beim dxdiag test) wird angezeigt, aber ich sehe keinen Text
Ich habe jetzt schon viele Foren damit zur Verzweiflung getrieben, also hoffe ich einfach mal dass mir jemand von hier soweit folgen konnte und hoffentlich einen Rat hat, woran das liegen könnte.
  Mit Zitat antworten Zitat