|
-
July 30th, 2003, 02:03 PM
#1
Efficient way to grab the screen
Hi all ! I ve searched the forums for screen capture posts and found one where galathea says the CreateWindowDC API function should do the job given the desktop window handle f.e. This makes perfect sense yes (thanks galathea).
But will it properly capture the AVI overlays and some other funky effects ? I need an exact whole image of the screen (portion of it) because i am implementing a remote control service.... For this reason i am willing to go to any depth of the WinAPI just to get the image a) fast and b) without holes. DirectX, whatever - i will eat it !
Am I dreaming ? :-)
-
July 31st, 2003, 04:13 AM
#2
getPixel
You can get the color of a pixel by
Code:
static HDC hdcScreen ;
POINT pt ;
static COLORREF cr;
hdcScreen = CreateDC (string_specifying_driver_name, NULL, NULL, NULL) ;
cr = GetPixel (hdcScreen, pt.x, pt.y) ;
So... you do do that for every pixel...
Last edited by Fresny; July 31st, 2003 at 04:16 AM.
-
July 31st, 2003, 09:43 AM
#3
Yes, thanks. But that would be like the slowest of all the slow ways to do it
-
July 31st, 2003, 04:40 PM
#4
Did you try BitBlt() function? I think it will be much faster.
-
July 31st, 2003, 04:45 PM
#5
Efficient way to grab the screen
BitBlt is the fastest way you could grab a screen, unless i guess you try writing code at the framebuffer level.
Regards,
Preetham.
"All you touch and all you see is all you'll ever be"
-
August 1st, 2003, 02:44 AM
#6
Good input
Yes looks like BitBlt is fastest. However I will need to access the ARGB data directly, because the image will be coded with a custom PNG encoder, and with BitBlt this will involve one more copying - using the GetDIBits to access the bitmap. Not a crisis but:
1. Blit bitmaps from display DC to memory DC - BitBlt
2. Copy memory DC selected bitmap into user supplied buffer - GetDIBits
---looks like a lot of copying. I need at least 5 frames per second 
I was thinking to do it the DirectDrawSurface7 way - you can lock the screen pixel data directly without any copying. Do you guys think it is a way to do it ?
THanks for a lot of good input anyway !!!
-
August 1st, 2003, 12:11 PM
#7
I think DirectDraw is probably the nicest solution for this. You DirectDrawCreateEx your IDirectDraw7 interface, set it up to support your primary surface (SetCooperativeLevel, etc.), and then you can use one of the many ways to actually create your IDirectDrawSurface7 object. The trick here is that you want to have your primary surface represent the one that GDI uses, and there are two commands that allow you access to the GDI primary surface (GetGDISurface and FlipToGDISurface), or if there is a specific DC you know you want access to, use that (unfortunately, I don't have experience with this yet, so I can't give much details). You should then create a back buffer surface as well. Then, you can BltFast from the primary surface to the buffer any time you want to capture the screen and Lock the buffer surface to give you memory access to the actual bitmap bits (which will be in a device dependent format, which you need to parse using the information from the DDSURFACEDESC2 structure returned to you when you lock the surface).
There was an interesting post in this forum a couple of weeks back by LearnMFC, with several people (including myself) trying to help with a problem very similar. Its title mentioned getting access to a bitmap's bits a particular Hz, so if you find that, maybe it can give some more ideas!
*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
"It's hard to believe in something you don't understand." -- the sidhi X-files episode
galathaea: prankster, fablist, magician, liar
-
August 1st, 2003, 12:18 PM
#8
Originally posted by galathaea
I think DirectDraw is probably the nicest solution for this. You DirectDrawCreateEx your IDirectDraw7 interface, set it up to support your primary surface (SetCooperativeLevel, etc.), and then you can use one of the many ways to actually create your IDirectDrawSurface7 object. The trick here is that you want to have your primary surface represent the one that GDI uses, and there are two commands that allow you access to the GDI primary surface (GetGDISurface and FlipToGDISurface), or if there is a specific DC you know you want access to, use that (unfortunately, I don't have experience with this yet, so I can't give much details). You should then create a back buffer surface as well. Then, you can BltFast from the primary surface to the buffer any time you want to capture the screen and Lock the buffer surface to give you memory access to the actual bitmap bits (which will be in a device dependent format, which you need to parse using the information from the DDSURFACEDESC2 structure returned to you when you lock the surface).
There was an interesting post in this forum a couple of weeks back by LearnMFC, with several people (including myself) trying to help with a problem very similar. Its title mentioned getting access to a bitmap's bits a particular Hz, so if you find that, maybe it can give some more ideas!
I usually use both hand to grab the screen, this due to drunkeness (sp is that a freaking word?) word up bro....
and andreas was asking what ThreadJacking was..phhhppt...
-
August 1st, 2003, 01:32 PM
#9
Galathea:
DirectDraw7 works very fast:
Code:
LPDIRECTDRAW7 lpDD;
LPDIRECTDRAWSURFACE7 lpDDSPrimary;
DirectDrawCreateEx(NULL, (LPVOID*)&lpDD, IID_IDirectDraw7, NULL);
lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
DDSURFACEDESC2 ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
lpDDSPrimary->Lock(NULL, &ddsd, DDLOCK_READONLY, NULL);
//'ddsd.lpSurface' is a pointer to display memory
lpDDSPrimary->Unlock(NULL);
I forgot to mention that I needed to access ARGB values directly, so this wont get any faster than the code shown.
There is no copying involved and from there I can go on and apply my imaging to the bitmap i obtained.
There is one BIG problem though, and as far as I am concerned, it persists on most screen grab solutions out there:
Namely, the code above and GetDesktopWindow way only work in users desktop. I need my application to service the screen data even when the workstation is locked and no user is present (no user desktop or window station is present).
If I lock workstation before the program takes effect, my surface gets lost, and any attempts to restore it silently fail although they shamelessly return DD_OK. In other words, I cannot access the physical screen data without a user desktop...
Any suggestions ?
P.S. Mick are/were you drunk right now ?
-
August 1st, 2003, 02:04 PM
#10
My first reaction is that a DDI driver hook would be needed (something along the lines maybe of what Feng Yuan shows in his book on Graphics programming?). But that's my response to anything that needs to bypass user security and get to the system. There might be a way to do something with passing an impersonation access token to someone who is handling the screen, but I don't know who is handling the screen then (the SYSTEM account talks to ...?). If you can't gain the appropriate priveleges in user mode, the only way may be with a a driver...
*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
"It's hard to believe in something you don't understand." -- the sidhi X-files episode
galathaea: prankster, fablist, magician, liar
-
August 1st, 2003, 02:57 PM
#11
Originally posted by galathaea
My first reaction is that a DDI driver hook would be needed (something along the lines maybe of what Feng Yuan shows in his book on Graphics programming?). But that's my response to anything that needs to bypass user security and get to the system. There might be a way to do something with passing an impersonation access token to someone who is handling the screen, but I don't know who is handling the screen then (the SYSTEM account talks to ...?). If you can't gain the appropriate priveleges in user mode, the only way may be with a a driver...
Thanks for helping me out, I appreciate the hellp very much !!!
Given that topics this deep are seldom, I REALLY appreciate your response 
The application is a system service not a user process, hence even impersonating a user wont achieve desired effect (servicing a remote user with a screen visuals). In other words, say, I impersonated someone and now posess the credentials required to create and manage objects as if they were managed by him - the user; but my task is rather to simulate physical screen. I leave Windows security intact because if the workstation is locked they will have to unlock it by interacting with screen remotely first.
I will look onto device drivers if DDI is what I think it is, looks like it will save me, becase user APIs dont 
THanks again, tell me if you have any more input pleaaaaaaaaaaaaaase 
P.S. What is DDI ? Microsoft doesnt tell Do you mean DDK ? Device Driver Development Kit ? I cant find any APIs that interact with drivers....
Last edited by Amn; August 1st, 2003 at 03:32 PM.
-
August 2nd, 2003, 12:43 PM
#12
While I am burying myself in Windows DDK, is there anybody out there who knows the secret of capturing the screen in system mode with logon screens and all that ?
Anyone ? 
* Heads on to MSDN for further DDK research *
* MS is not exactly selfexplanatory *
-
August 4th, 2003, 05:07 PM
#13
The DDI is window's graphics Device Driver Interface. You can find some information at this MSDN introduction, but I admit it isn't really too helpful. Basically, if you need to capture graphics going on in the system that you can't reach in user mode, the only possibility that I can think of is to write a driver hook into the DDI and grab the data from there. The only really good example of this that I know of is from the book by Feng Yuan, which doesn't really go into what would be needed for you, it only shows you how to hook into the interface (it has another one of those low level interception programs that is mainly used to show the reader what is going on behind the scenes). I wish I had actual code to help out, but I haven't really done much along these lines yet. Some of what I do in my job kind of intersects here, but I couldn't give any real details as they are company property. However, I hope this helps you get started!
*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
"It's hard to believe in something you don't understand." -- the sidhi X-files episode
galathaea: prankster, fablist, magician, liar
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|