PDA

View Full Version : Rendering to an Existing Window



Max_Swell
09-27-2002, 09:05 PM
Hi everybody, I've been trying to learn how to direct rendering output to an existing window for more than a week now, and I'm still getting nowhere. In short, I'm looking for a way to direct my OpenGL rendering to an
existing, independent window (I'm using Windows 2000) that is already up and happily doing its thing. My goal is to write an in-game maping utility for the 3D game "Everquest" that would read in map data from a file, generate a vector-drawn map, and ideally render it to the Everquest window. In other words, the program I write wouldn't even have its own window, it would instead draw to Everquest's window.

So far I know how to get the EQ window's handle, class name, window name, and even
style, but I can't seem to figure out how to use that information to render to it. Any ideas?

vshader
09-27-2002, 10:11 PM
you can only set the pixel format for a window once. if you are trying to cal SetPixelFormat() on a window already set up for GL rendering, it will fail.

why do you want to hijack an existing window anyway?
why not create your own window?
if you hijack an existing window you will also have to hijack it's message loop or you will not know when to redraw the window.

Max_Swell
09-27-2002, 10:41 PM
Why do I need to call SetPixelFormat at all? I'm not creating a new window, I want to render to one that already exists. The window I want to write to is not an OpenGL application, however, but a DirectX one. I've heard conflicting reports on whether this matters or not... I found a post by one guy, for instance, who was able to render directly to the desktop window. If he can do that, why can't I do the same thing with a regular window?

[This message has been edited by Max_Swell (edited 09-27-2002).]

vshader
09-27-2002, 11:12 PM
i have no idea if you can draw to a window that is already "owned" by DirectX... and i really don't know why you would want to.

drawing to the desktop window is one thing -no other program is trying to draw to it at the same time for a start ... trying to synchronize drawing to a shared window with a whole other process is another thing altogether. have you ever written a multithreaded program drawing to a shared window? you want to do that, but have no way of sending or receiving synchronization information to/from the other process.
how do you ensure what you draw doesn't get overwritten?

as for SetPixelFormat() - you usually do that before you get an openGL RC for a window, and you need an openGL RC to make openGL calls. this is an openGL forum so i assume you want to use openGL to draw to the window ... i doubt windows will let you call SetPixelFormat() or wglCreateContext() on a window being rendered to by Direct3D, but i've never tried it, for obvious reasons.

edit: i'm not trying to flame you, just suggesting that what you are wanting to do may be a little more difficult than you have anticipated. if you are au-fait with inter-process synchronization issues and methods ... go ahead.

[This message has been edited by vshader (edited 09-28-2002).]

GeLeTo
09-28-2002, 12:46 AM
A crazy idea - you can use a modified gltrace to hijack all opengl calls and draw whatever you want from the glFinish() call. I am not aware of a gltrace equivalent for DX, but you can use one of the DX to GL wrappers, though I don't know how well these work with Everquest.
I think that the next version of WineX for Linux will support Everquest, and since the WineX sources are avaiable - you can do the same thing from there.

[This message has been edited by GeLeTo (edited 09-28-2002).]

knackered
09-28-2002, 02:06 AM
?

[This message has been edited by knackered (edited 09-28-2002).]

jwatte
09-28-2002, 09:52 AM
I understand why he wants to do this.

Verant (publishers of Everquest) has this asinine idea that they know better than the users what the users want. Thus, they don't support alt-tabbing out of the game. And they have no in-game maps. Thus, gamers have the three choices of:

1) use a second computer (my favourite :-)
2) use a printed map
3) memorizing all maps, and spend an hour on "corpse recovery" in-game if you ever forget and take a wrong turn

I applaud Max_Swell for trying to come up with choice 4): add the missing game feature of in-game maps.

This might even work under Windows 2000, where window handles are renderable from separate processes (using an undocumented hack, as far as I can tell).

I would suggest getting the DC, then trying to call SetPixelFormat, and if that fails, just keep on truckin' and try to create the GLRC. If that fails, your idea probably won't work, period. In that case, you might want to try rendering using GDI instead of OGL.

The problem is still knowing when to render. Unless you can get the program to load and execute some of your code in-process, I think you'll have to just accept the fact that your map will flicker on the screen while it's up, as some frames it'll be visible, and some frames it won't.

Good luck! You, and all poor EverQuest players, really need it :-)

Nakoruru
09-28-2002, 02:35 PM
I think you may be able to use DirectX 8.

The Present method of the DX83D device takes a handle to a window to copy the backbuffer to. The thing is, from my intrepretation of the interface, this can be any window at all! The only restriction is that it probably needs to be on the same adaptor. You would only be out of luck if it has to belong to the same thread or process.

You may need to make sure you choose a compatible swap method.

Displaying a map seems really simple, so the choice of how to do it should be based purely on what will work, not on what you like, so who cares if its OpenGL or Direct3D ^_^

renaissanz
09-28-2002, 05:15 PM
OK, this is a problem that I have encountered a couple of times. What I did is not directly applicable to your problem, but it should work well enough.

Step 1: Create a small app with three features -
a. Uses ShellExecute or ShellExecuteEx to launch the Everquest app, this returns an HINSTANCE.
b. Uses that HINSTANCE to insert a hook into Everquest's windows messaging loop using SetWindowsHookEx.
c. Discovers the HWND of the Everquest app.

After launching the Everquest app using ShellExecute, you should scan thru all of the HWNDs on the system and discover the Everquest one (e-mail me if you need to know about that). From that HWND, create a compatible HDC and get it ready to draw to (bit-blitting would be ideal).

After this you're ready to insert a hook into Everquest's messaging loop using SetWindowsHook(Ex?). For your purposes, it's very important that you use WH_CALLWNDPROCRET as the type of hook.

During the process of setting the windows hook you will be able to specify a callback function. This callback function should focus specifically on the WM_PAINT message.

If you've used the WH_CALLWNDPROCRET type of hook, you'll be getting the WM_PAINT message after the window. At this point you will be able to paint to the window after DirectX has (this should eliminate any flickering problems unless your drawing code is painfully slow) using the HDC that you set up earlier.

Happy hunting! (BTW, according to my brother, Everquest is the end-all be-all of online RPG. Since when have you ever heard of an RPG that didn't obsess on maps???)

:-)

Matt

Max_Swell
09-28-2002, 09:08 PM
[QUOTE]Originally posted by jwatte:
[B]I understand why he wants to do this.

Verant (publishers of Everquest) has this asinine idea that they know better than the users what the users want. Thus, they don't support alt-tabbing out of the game. And they have no in-game maps. Thus, gamers have the three choices of:

1) use a second computer (my favourite :-)
2) use a printed map
3) memorizing all maps, and spend an hour on "corpse recovery" in-game if you ever forget and take a wrong turn

I applaud Max_Swell for trying to come up with choice 4): add the missing game feature of in-game maps.


Right you are! You nailed my intentions on the head, though I'll admit the idea isn't an origianl one. In fact, there already is fan-produced mapping software--called Xylotbot--as well as a complete libary of map files. The catch is that the current map software only works with the Everquest.exe, which as you noted, only works fullscreen and can't be alt-tabbed. However, there's another clever little app someone came up with called EQ Windows, which forces EQ to run in a window. It's to THIS window I want to direct my maps (Xylobot is not compatible with EQW). Unfortunately, I still fail to have any luck getting my output to appear in ANY other window, even with a very simple test app. Not quite ready to give up yet, though. =)

vshader
09-28-2002, 09:27 PM
after having hassled you 'cos i couldn't for the life of me work out why you wanted to do this (i don't play RPGs)- i find this kinda interesting...

first - i apologize if i was harsh.

anyway, my guess - use the exact technique in the post previous ( hooks into the EQ wndproc - so you get WM_PAINT just after the EQ wndproc gets them ), and start just trying really simple GDI calls - like filled rectangles or something.
surely if anything will work that will.

otherwise, you could always try this - if the program is running in a window, and you have its HWND or a hook into it's wndproc, you can easily track the window size and position, so why not attach your map window to the side/top/bottom of it? that will save a lot of tricky synchronization stuff...

Max_Swell
09-29-2002, 12:23 AM
Originally posted by vshader:

otherwise, you could always try this - if the program is running in a window, and you have its HWND or a hook into it's wndproc, you can easily track the window size and position, so why not attach your map window to the side/top/bottom of it? that will save a lot of tricky synchronization stuff...[/B]

That's a good tip, too. I'll probably go with that idea if I can't get this "hijacking" business to work, but it would be SO much cooler if the map could overlay right over EQ. =)

ToolChest
09-30-2002, 05:25 AM
Max,

Very cool idea, I’m an opengl guy, but I think directx is you best bet in this case. I don’t know if this will help you, but your can call ‘CreateRemoteThread’ in Win2k to inject a thread into another process. The only problem is that you will need your code loaded into EQ’s app space. If EQ supports plugins of any type you may be able to get EQ to load your hijack code.

Just a though… http://www.opengl.org/discussion_boards/ubb/smile.gif

John.