views:

1385

answers:

8

We've got some in-house applications built in MFC, with OpenGL drawing routines. They all use the same code to draw on the screen and either print the screen or save it to a JPEG file. Everything's been working fine in Windows XP, and I need to find a way to make them work on Vista.

In three of our applications, everything works. In the remaining one, I can get the window border, title bar, menus, and task bar, but the interior never shows up. As I said, these applications use the exact same code to write to the screen and capture the window image, and the only difference I see that looks like it might be relevant is that the problem application uses the MFC multiple document interface, while the ones that work use the single document interface.

Either the answer isn't on the net, or I'm worse at Googling than I thought. I asked on the MSDN forums, and the only practical suggestion I got was to use GDI+ rather than GDI, and that did nothing different. I have tried different things with every part of the code that captures and prints or save, given a pointer to the window, so apparently it's a matter of the window itself. I haven't rebuilt the offending application using SDI yet, and I really don't have any other ideas.

Has anybody seen anything like this?

A: 

The contents of each window are directX surfaces and are only assembled by the window manager in the graphics card. You'd not be able to capture this unless you switch off the new interface (DWM) or code specifically for screen capture from the DWM.

Wikipedia has a good description of the Desktop Window Manager (DWM)

Ray Hayes
+1  A: 

Your question title mentions screen capture but your actual question doesn't. Please elaborate more clearly. Is the problem that you can do screen capture of three of your applications, but not the fourth one? You can use different screen capture software that can capture OpenGL/DirectX windows. Those surfaces are handled directly by the Window Manager and won't show up with a simple 'PrtScn'.

Switching to GDI+ won't solve it, nor will switching to SDI.

Roel
A: 

What I've got is four applications. They use a lot of common code, and share the actual .h and .cpp files, so I know the drawing and screen capture code is identical.

There is a WindowtoDIB() routine that takes a *pWnd, and a source rectangle and destination size. It looks like very slightly adapted Microsoft code, and I've found other functions in this file on the Microsoft website. Of my four applications, three handle this just fine, but one doesn't. The most obvious difference is that the problem one is MDI.

It looks to me like the *pWnd is the problem. I'm not a MFC guru by a long shot, and it seems to me that the problem may be that we've got one window setup in the SDIs, and more than one in the MDI. I may be passing the wrong *pWnd to the function.

In the meantime, it has started working properly on the 64-bit Vista test machine, although it still doesn't work on the 32-bit Vista machine. I have no idea why. I haven't changed anything since the last tests, and I didn't think anybody else had. (On the 32-bit version, the Print Screen key works as expected, but it does not save the screen as a JPEG.)

David Thornley
A: 

Sorry, I still don't understand. You're trying to get the Print Screen key to work on all four applications? Or you're trying to get the WindowtoDIB() function to work, which takes a 'screenshot' (from within your own application) of the application itself, so that it can be saved as an image file?

Also, what do you mean with 'he Print Screen key works as expected, but it does not save the screen as a JPEG.'? Print Screen only copies to the clipboard, what happens when you paste in Paint?

If your WindowtoDIB() function only 'captures' the window you pass to it, then yes, your MDI child windows are not going to show up.

Roel
A: 

My apologies for being unclear. I want to get WindowToDIB() to work. I don't really care about Print Screen. By "works as expected", I mean that alt-Print Screen and paste to Word (works, and handy to bring up) displays the window as I saw it.

Your comment on the child windows, Roel, looks like it might well be what I'm looking for. However, the calls are from the *View class, which is a subclass of CView, which is a subclass of cWnd. It therefore appears to me that I should already have the right cWnd.

David Thornley
+1  A: 

If it's the content of the CView that you want, then yes, that should be right one. If it's the content of the whole screen (at least the content, without the toolbar(s) and status bar), then you should pass it the CMainFrame (that's the default name which may have been changed, the one that is derived from CMDIFrameWnd).

Can you post the code of WindowToDIB()? I've just tried it and It Works For Me (TM), but without OpenGL code in the view. Try passing the following windows to your WindowToDIB() function:

CMainFrame* mainfrm = static_cast(::AfxGetMainWnd());

  • mainfrm

  • mainfrm->MDIGetActive()

  • mainfrm->MDIGetActive()->GetActiveView()

and see what you get.

Roel
You seem to be having a discussion using "answers" as posts. If for some reason someone votes for one of the answers this isn't going to make sense. That's what the comment sections are for!
Ray Hayes
300 characters isn't enough for a proper post. I'm figuring that these additional answers will help to narrow down the problem, then in the end the final solution will be voted up.
Roel
A: 

My current situation is that it started to work for no apparent reason. I don't trust this, but unless it stops working again I can't try any suggestions. I just hope it continues.

I'd like to thank everybody who contributed.

David Thornley
A: 

We eventually solved this by creating a different OpenGL context, and drawing everything to that. We gave up on the screen capture.

David Thornley