Page 1 of 2
Drawing to a full screen DirectX application
Posted: Fri Jul 24, 2009 2:38 pm
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
Posted: Fri Jul 24, 2009 4:48 pm
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!

Posted: Fri Jul 24, 2009 5:49 pm
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.
Posted: Wed Jul 29, 2009 1:24 pm
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?
Posted: Tue Aug 04, 2009 12:38 pm
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.
Posted: Tue Aug 04, 2009 1:42 pm
by SFSxOI
Fluid Byte > get the GPP 1.5 on the site
Posted: Tue Aug 04, 2009 5:06 pm
by Fluid Byte
Wow, this actually works!
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?
Posted: Tue Aug 04, 2009 10:09 pm
by SFSxOI
Fluid Byte wrote:Wow, this actually works!
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?
Posted: Tue Aug 04, 2009 10:29 pm
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

Posted: Wed Aug 05, 2009 7:51 pm
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.
Posted: Wed Aug 05, 2009 8:00 pm
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.
Posted: Thu Aug 06, 2009 5:17 pm
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
Anyway, it was worth a try

Posted: Thu Aug 06, 2009 6:20 pm
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
Anyway, it was worth a try

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.
Re: Drawing to a full screen DirectX application
Posted: Thu Jul 22, 2010 7:59 am
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.
Re: Drawing to a full screen DirectX application
Posted: Wed Aug 25, 2010 12:47 pm
by Machiavelli
Code from
that thread works only with static sprites?