Drawing to a full screen DirectX application

Just starting out? Need help? Post your questions and find answers here.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Drawing to a full screen DirectX application

Post by SFSxOI »

I know this has been asked before, and i've searched the forums and looked at and tried various examples, so i'm just going to start over with what i need to do as i've gotten so off track and confused.

I have a directX based application which runs full screen and not in a window, the application was developed in house by a past contract programmer and the source is no longer available for me to look at and possibly re-compile with needed changes. I have a few background modifications of my own which affect this application and the way it runs, however, some of them are timed events. These work fine. But I need someway to notify the user when certain activity has been completed without having to alt-tab out of the full screen application (which causes it to crash sometimes anyway) to look at some message or another. I really wanted to do both words and graphics but i'll settle for either at this point. The graphics would not be a picture or anything, a simple circle (to form a dot) or a line or (hopefully wishing) a check mark, and possibly display some numbers. I wanted to draw or put this on top of the full screen application, or in front of it, without affecting the application and causing it to lose focus or affect its running properly.

All of the possible examples i've found and experimented with (read that as perverted and mangled) in the forum seem to cause the application to lose focus or affect its proper operation in some way. I thought I had it with one example, but what happened was that the text or circle would flicker so badly that it didn't even show most of the time then I discovered that i was actually drawing on the desktop instead of the application - DoH! so I scrapped that idea.

Anyone have any ideas or code that might help?

Thank You
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

There's an old thread in the German forums that shows how to create an Overlay with DirectDraw:

http://www.purebasic.fr/german/viewtopic.php?t=343

There's also an updated version by me. Though you must realize that the code has many disadvantages. You are forced to use DX7, no 64-bit, the game/desktop need to have the same resolution or the overlay is destroyed.

After an intense Google session I found a page which hosts working C++/C# code that demonstrates how to set up a Direct3D hook (also overlay).

So you may reconsider the idea of using an overlay and go the long route with the hook code:

http://nexe.gamedev.net/directKnowledge/

Enjoy! :P
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Thanks Fluid Byte :)

I had already tried that code over in the german forum and couldn't get it to work for this purpose.

I had not thought about a hook though. But...i'll check it out.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

OK, found something on the 'net that seems to work for overlays for Direct X 8 and 9 Direct3D applications. It can do text or graphics over full screen DirectX Direct3D apps > http://www.mikoweb.eu/index.php?node=28

Did a little searching on Google and found the guys over at http://www.autohotkey.com/forum/viewtop ... sc&start=0 are using it sucessfully, found a few more references to it on the 'net also.

Injected the 93d*.dll externally to the app, injected fine, says its working, opened up the gpcomms.dll library and called the functions, works great!

Source code is available for it > http://www.mikoweb.eu/index.php?node=28 , unfortunately my conversion skills are not that great, but i'm going to give it a try at converting it for PB.

Anyone ever seen this item before? Maybe someone has it converted already?
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

May I ask which file you downloaded? There's so much stuff I'm a little confused. It looks promising so I want to give it a try.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Fluid Byte > get the GPP 1.5 on the site
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Wow, this actually works! :o

I tested with COD2, COD4, Hitman: Blood Money and GTA: SA. The main reason I'm interested in this is because I want to display info text in steam games like CS, DOD, TF, etc. It's pretty messy to even figure out where to put the DLL. You have to place the "d3d9.dll" file in the corresponding "bin" folder for each game. Second, you can't start the game from your steam GUI games list but need to create a shortcut in the game folder with correct parameter like "-game dod".

But when I start that up I get:
Der Prozedureinsprungpunkt "D3DPERF_SetOptions" wurde in der DLL "d3d9.dll" nicht gefunden.
wich roughly translated means:
The procedure entry-point "D3DPERF_SetOptions" wasn't found in the DLL "d3d9.dll"
Maybe someone got an idea what to do? Reinstall DirectX perhaps?
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Fluid Byte wrote:Wow, this actually works! :o

I tested with COD2, COD4, Hitman: Blood Money and GTA: SA. The main reason I'm interested in this is because I want to display info text in steam games like CS, DOD, TF, etc. It's pretty messy to even figure out where to put the DLL. You have to place the "d3d9.dll" file in the corresponding "bin" folder for each game. Second, you can't start the game from your steam GUI games list but need to create a shortcut in the game folder with correct parameter like "-game dod".

But when I start that up I get:
Der Prozedureinsprungpunkt "D3DPERF_SetOptions" wurde in der DLL "d3d9.dll" nicht gefunden.
wich roughly translated means:
The procedure entry-point "D3DPERF_SetOptions" wasn't found in the DLL "d3d9.dll"
Maybe someone got an idea what to do? Reinstall DirectX perhaps?
Yeah, thats what your going to get. Inject it externally and dont put it in the game directory - its what I had to do. Heres some code for an injector. So try injecting it:

Code: Select all

Prototype.i PFNCreateToolhelp32Snapshot(dwFlags.i, th32ProcessID.i) ;
Prototype.b PFNProcess32First(hSnapshot.i, *lppe.PROCESSENTRY32) ;
Prototype.b PFNProcess32Next(hSnapshot.i, *lppe.PROCESSENTRY32) ;


Procedure.b CheckRunningExe(FileName.s) 
  Protected snap.i , Proc32.PROCESSENTRY32 , dll_kernel32.i 
  FileName = GetFilePart(FileName) 
  dll_kernel32 = OpenLibrary(#PB_Any, "kernel32.dll") 
  If dll_kernel32 
    snap = CallFunction(dll_kernel32, "CreateToolhelp32Snapshot",$2, 0) 
    If snap 
      Proc32\dwSize = SizeOf(PROCESSENTRY32) 
      If CallFunction(dll_kernel32, "Process32First", snap, @Proc32) 
        While CallFunction(dll_kernel32, "Process32Next", snap, @Proc32) 
          If PeekS(@Proc32\szExeFile)=FileName 
            CloseHandle_(snap) 
            CloseLibrary(dll_kernel32) 
            ProcedureReturn #True 
          EndIf 
        Wend 
      EndIf    
      CloseHandle_(snap) 
    EndIf 
    CloseLibrary(dll_kernel32) 
  EndIf 
  ProcedureReturn #False 
EndProcedure

Procedure Elevated_Cmd(app_dir.s, app_name.s)
AppVerb$ = "runas"
AppName$ = app_name
AppDir$ = app_dir

shExecInfo.SHELLEXECUTEINFO 
shExecInfo\cbSize=SizeOf(SHELLEXECUTEINFO) 
shExecInfo\fMask=#Null 
shExecInfo\hwnd=#Null 
shExecInfo\lpVerb=@AppVerb$
shExecInfo\lpFile=@AppName$ 
shExecInfo\lpDirectory=@AppDir$
shExecInfo\nShow=#SW_NORMAL

exe.i = ShellExecuteEx_(shExecInfo)
Delay(3000)

If CheckRunningExe(app_name) = #True
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf

EndProcedure

Procedure GetPidByName(p_name$) 
    Protected hDLL.i, process_name$ 
    Protected PEntry.PROCESSENTRY32, hTool32.i 
    Protected pCreateToolhelp32Snapshot.PFNCreateToolhelp32Snapshot 
    Protected pProcess32First.PFNProcess32First 
    Protected pProcess32Next.PFNProcess32Next 
    Protected pid.i 
    
    hDLL = OpenLibrary(#PB_Any,"kernel32.dll") 
    
    If hDLL 
        pCreateToolhelp32Snapshot = GetFunction(hDLL,"CreateToolhelp32Snapshot") 
        pProcess32First = GetFunction(hDLL,"Process32First") 
        pProcess32Next = GetFunction(hDLL,"Process32Next") 
    Else 
        ProcedureReturn 0 
    EndIf 
    
    PEntry\dwSize = SizeOf(PROCESSENTRY32) 
    hTool32 = pCreateToolhelp32Snapshot(#TH32CS_SNAPPROCESS, 0) 
    pProcess32First(hTool32, @PEntry) 
    process_name$ = Space(#MAX_PATH) 
    CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH) 
    
    If  UCase(process_name$) = UCase(p_name$) 
        ProcedureReturn PEntry\th32ProcessID 
    EndIf 
    
    While pProcess32Next(hTool32, @PEntry) > 0 
        process_name$ = Space(#MAX_PATH) 
        CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH) 
        
        If  UCase(process_name$) = UCase(p_name$) 
            ProcedureReturn PEntry\th32ProcessID 
        EndIf 
    
    Wend 
    
    CloseLibrary(hDLL) 
    
    ProcedureReturn 0 
EndProcedure

Procedure InjectLibA(dwProcessId.i, pszLibFile$) 
  hProcess.i 
  hThread.i 
  lzLibFileRemote.i 
  lSize.i 
  endSize.i 
  lsThreadRtn.i 
  
  hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId) 
  
  If hProcess = 0 : Goto ErrHandle : EndIf 
  lSize = 1 + Len(pszLibFile$) 
  endSize = lSize 
  
  lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT, #PAGE_READWRITE) 
  
  If lzLibFileRemote = 0 : Goto ErrHandle : EndIf 
  
  If (WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile$, endSize, #Null) = 0) : Goto ErrHandle : EndIf 
  
  OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryA") : CloseLibrary(0) 
  
  If lsThreadRtn = 0 : Goto ErrHandle : EndIf 
  
  hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #Null, #Null) 
  
  If (hThread = 0) : Goto ErrHandle : EndIf 
  
  WaitForSingleObject_(hThread, #INFINITE) 
  
  If lzLibFileRemote<>0 
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
    MessageRequester("Inject Status", "Injection Suceeded", 0)
    Else
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
    MessageRequester("Inject Status", "Injection Failed !!!", 0)
  EndIf 
  End 
  
  ErrHandle: 
      CloseHandle_(hThread) 
      CloseHandle_(hProcess)
      MessageRequester("Inject Status", "Injection Failed !!!", 0) 
EndProcedure

path_game$ = "C:\Program Files\SomeGame\MyGame"
file_game$ = "Game.exe"

; for Vista
apprun = Elevated_Cmd(path_game$, file_game$)

;(If on XP use RunProgram To start your game)

Delay(5000)

dll_dir$ = GetCurrentDirectory() + "d3d9.dll"

val_pid.i = GetPidByName(file_game$)
Delay(10)
InjectLibA(val_pid, dll_dir$)

Either compile the above code into an .exe and put the d3d9.dll in the same dir as the injector, or edit the above for a path to the 9d39.dll (not in the game directory) and just run the code from the PB IDE.

I had to borrow a game to test it out with, Warcraft, and it worked fine. But I had the same problem with putting the d3d9.dll in the game dir so I had to inject it and I used the above to do so.

I dont understand your shortcut thing? Is that just for steam?
Last edited by SFSxOI on Tue Aug 04, 2009 10:38 pm, edited 1 time in total.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

That looks pretty complicated but I will give it a shot tomorrow.

Thank you for taking the time. I will let you know if it worked out.
I dont understand your shortcut thing? Is that just for steam?
You don't need to. Steam's just being an ass :P
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Ah, now I see the dilemma. Unfortunately a steam game can't be executed directly. You have three options here:

1.) Double click the game in your games list within the steam desktop GUI
2.) Double click the shortcut on your desktop whose path looks like (this ones for Day Of Defeat):
C:\Games\Steam\Steam.exe -applaunch 300
3.) Go into the specific game folder which looks like:
C:\Games\Steam\steamapps\ACCOUNT-NAME\day of defeat source\
create a shortcut of "hl2.exe" and add a parameter to start the game:
hl2.exe -game dod
So I can't specify a valid filepath/filename for the injector to work with.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Fluid Byte wrote:Ah, now I see the dilemma. Unfortunately a steam game can't be executed directly. You have three options here:

1.) Double click the game in your games list within the steam desktop GUI
2.) Double click the shortcut on your desktop whose path looks like (this ones for Day Of Defeat):
C:\Games\Steam\Steam.exe -applaunch 300
3.) Go into the specific game folder which looks like:
C:\Games\Steam\steamapps\ACCOUNT-NAME\day of defeat source\
create a shortcut of "hl2.exe" and add a parameter to start the game:
hl2.exe -game dod
So I can't specify a valid filepath/filename for the injector to work with.
Nope, but you can specify a shortcut to launch and in the shortcut put the start up parameters. So in the injector you just change it a little and instead of starting up the program directly start the shortcut then delay a little then see if the .exe is running then inject into the game.exe. Or...do the same thing but with a batch file instead of a shortcut.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

I changed the code accordingly but it doesn't work. It does show the logo of the DLL (the little black box with the green border) and it says it has been injected successfully but when I start the demo app (gp_demo.exe) and try to activate the FPS counter or display text nothing happens.

Well, it does work with an injected DLL in other games like GTA:SA. In fact it doesn't seem to matter at which time the DLL is injected. Can be 2 seconds or 2 minutes. But with the the steam games, no luck :x

Anyway, it was worth a try :P
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Fluid Byte wrote:I changed the code accordingly but it doesn't work. It does show the logo of the DLL (the little black box with the green border) and it says it has been injected successfully but when I start the demo app (gp_demo.exe) and try to activate the FPS counter or display text nothing happens.

Well, it does work with an injected DLL in other games like GTA:SA. In fact it doesn't seem to matter at which time the DLL is injected. Can be 2 seconds or 2 minutes. But with the the steam games, no luck :x

Anyway, it was worth a try :P
No, it doesn't matter at which time the .dll is injected, or when the commands are called.

Just yesterday I discovered what you did. It doesn't work on DirectX apps and games that use MDI windows I don't think. It does work on warcraft (the only thing i tried it with until yesterday), and you found it does work on GTA. I tried it with a couple of directX based applications we have at work and it does work with those. It seems to work with BattleField someone told me. What these things have in common is they don't use MDI windows. I downloaded and installed that Americas Army 3.0 game yesterday and it does not work with that one despite it being DirectX but it uses MDI windows. It could be the situation with your Steam games or it could be Steam its self. Doesn't Steam wrap stuff? Maybe getting the handle and PID of the MDI window? How do you get the handle and PID of an MDI child window anyway? I don't even allow Steam on my computers so i can't realy test specifically for Steam, but the Americas Army game can be installed either via Steam or their "deploy client' but Steam is still affecting the game in some way because a Steam log is produced each run I noticed so maybe there is some Steam interaction going on that keeps it from happening.
Suirad
User
User
Posts: 42
Joined: Sun Sep 20, 2009 7:37 pm
Location: Melbourne, Florida, USA

Re: Drawing to a full screen DirectX application

Post by Suirad »

sorry for bumping such an old topic, but i didnt find enough info for a workable example. would anyone be able to define a working example of the above method. i cannot seem to find enough information to do so.
Machiavelli
User
User
Posts: 26
Joined: Sun May 24, 2009 2:38 pm

Re: Drawing to a full screen DirectX application

Post by Machiavelli »

Code from that thread works only with static sprites?
Post Reply