|
Hello,
I would like to know if there are a way to take a snapshot of a hidden window. With Hidden window I want to say that the window is not in Foreground, but its status has been modified before by ShowWindow(hWin, SW_SHOW).
I tried to make this:
- Take the HWND of the window
- Use GetWindowDC or GetDC to get the DC of the Window
- Create ( CreateCompatibleDC + CreateCompatibleBitmap + SelectObject of the Bitmap)
- Make a BitBlt from the DC of the Window to the memory DC
- Free DC
But this doesn't work. I think that the BitBlt do nothing, because the Window is not in ForeGround.
|
|
|
|
|
That's correct. This code will not capture a hidden window; it is designed to capture only a window that is not obscured by any other window.
As far as I know, there is no general-purpose way to capture an image on another window that is covered. You can create one, if the window is in your app, but I know of no way to get the contents of an arbitrary window.
|
|
|
|
|
Thanks for the answer.
Could you tell me, how I can get the snapshot of the hidden window if the window is in my application??
The hidden window have different controls (buttons, ListView etc).
The way that I found is to send a WM_PAINT to the window and then to each control, with a memory DC as the WPARAM and then copy them in a final memory DC.
This method works fine with the buttons, but with others controls, like the listview it doesn't work, because the memory DC retourned contains only the texts of the listview but not the background of the list(like the grid).
Maybe this is not the good solution.
Do you have any idea??
Best Regards
|
|
|
|
|
I think the right answer is that capturing the screen image is not a good solution. The question is WHY you want to capture the image; what you're asking for is an explanation of how to use a particular technology without an explanation of what problem you are trying to solve.
My function was written specifically to capture screen images of the window I was working on for purposes of book illustration; it doesn't pretend to be more general than that.
But generally, capturing a screen image for most other purposes (especially printing) is pretty useless, and without knowing what your goals are, it is hard to advise as to what a better strategy might be.
|
|
|
|
|
thanks for reply me.
I would like to developpe an application for Windows Mobile. What I want to do, is to add animations to my app when switching between windows, in order to make a Slide effect of the two windows.
For that I need two bitmaps (the snapshot of each window), in order to copy to a final DC the portions of image that I need, using BitBlt operations.
For the first bitmap(the current window), I can take it with your function. But I can't get properly the bitmap for the Hidden window.
Best Regards
|
|
|
|
|
That's a quite different question.
And it is vastly easier.
All you need to do is SetWindowPos the incoming window at a place you want to see it, and the outgoing window, and let the windows draw themselves! No need to capture bitmaps at all.
|
|
|
|
|
I was trying to make a program that could capture the minesweeper window when minesweeper is running.
I use VS 6.0 C++ running on windows XP
When I run this code the clipboard contents are a black rectangle the size of the minesweeper window.
Here's the code:
#include <windows.h>
void main() {
HWND hWnd=FindWindow(NULL,"Minesweeper");
//Find the proper dimensions
RECT r;
GetWindowRect(hWnd,&r);
int x =r.right - r.left;
int y =r.bottom - r.top;
//Find the HDC
HDC hdc= GetDC (hWnd);
HDC memDC = CreateCompatibleDC(hdc);
//Create the Bitmap
HBITMAP bm = CreateCompatibleBitmap(hdc, x, y);
SelectObject(memDC,bm);
//Post it to the Clipboard
OpenClipboard(hWnd);
EmptyClipboard();
SetClipboardData(CF_BITMAP,bm);
CloseClipboard();
ReleaseDC(hWnd,hdc);
}
Any help would be Appreciated
Thanks
|
|
|
|
|
I hope you need to copy the Content using BitBlt
|
|
|
|
|
Very nice! However, the default bitmap format is uncompressed . So when people then go and paste it into an email and send it, it is several MBs in size . That is sad since PNG and other formats can compress it to a fraction of that size.
So it would be simply wonderful if you could also post some code to place the bitmap in the clipboard, but in DIB format (which I believe can be compressed) or in PNG format.
I have only found one old snippet of code that shows how to place a bitmap into the clipboard in compressed DIB format. I had one go at trying to get it to work, but I did not succeed. Of course I had to borrow some internal snippets from CxImage or PNG lib for the compression.
I am also not sure if pasting a DIB from the clipboard into Outlook would preserve the compression or not?
Any thoughts?
|
|
|
|
|
|
You could compress it yourself using any of the various means of creating compressed images. Note, however, that pasting it into another app requires the other app be aware of the bitmap format. CF_DIBV5 format allows compression. However, I'll leave the actual compression as an Exercise For The Reader. You will have to use a library from some other source to do this.
|
|
|
|
|
If the window to be captured is overlaid by another window either because it is not on the top of the Z order or because there is an always on top window overlaying it, then the hidden part of the window to be captured to be captured will be replaced by the overlaid window. This makes sense, because BitBlt() is just copying a rectangle from the screen. But is there an technique to capture the window even if it is totally or partially captured? Thanks...
|
|
|
|
|
I am not aware of any technique. What I have suggested that what might be possible is to set the window to always-on-top, capture it, then restore it to its previous Z-order.
|
|
|
|
|
I was afraid of that. As a Windows user, I used to think that a window had an image in memory and the Windows just took care of displaying it correctly with all the others. Now as a beginning Windows programmer, I realize that the image only exists on the screen and it's the programmers' OnPaint() and OnDraw() that take care of displaying it. I guess MS had no choice back in the days of small, expensive main memory and it just stuck.
|
|
|
|
|
once you have an hwnd for the window you want to get an image of:
<br />
RECT rc;<br />
GetWindowRect(hWnd, &rc);<br />
<br />
Bitmap* bmp = new Bitmap(rc.right-rc.left, rc.bottom-rc.top);<br />
<br />
Graphics* gfxBitmap = Graphics::FromImage(bmp);<br />
<br />
HDC hdcBitmap = gfxBitmap->GetHDC();<br />
<br />
HDC hdcWindow = GetWindowDC(hWnd); <br />
<br />
BitBlt(hdcBitmap, 0, 0, rc.right-rc.left, rc.bottom-rc.top, <br />
hdcWindow, 0, 0, SRCCOPY);<br />
<br />
gfxBitmap->ReleaseHDC(hdcBitmap); <br />
<br />
ReleaseDC(hWnd, hdcWindow);<br />
<br />
at the end you have bmp to either save as a file or to the clipboard
|
|
|
|
|
Sir,
Thaks for the article.Iam looking for such a code for some time.
Iam working on a projet for remote dektop viewing.Can you please explain how can I send the captured image through a socket.If you don't mind please give me the code.
-Biju
|
|
|
|
|
Might want to look into VNC... (Google for it!)
Peace!
-=- James If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Tip for new SUV drivers: Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! DeleteFXPFiles & CheckFavorites (Please rate this post!)
|
|
|
|
|
This is actually fairly difficult to do well. You would have to compress it, or you would be sending over two megabytes per screen at 1024x768, but even under the best of conditions this is going to give you abysmal performance.
JPEG compression would give you better compression, but it is lossy compression and the image would be distorted by the lossiness.
All you have to do is get the pixels from the bitmap and write them to the socket. Or write the compressed pixels. PKZIP-style (there are open-source ZIP libraries) compression would probably do better than run-length-encoding (RLE), so I'd suggest looking at that. GetBitmapBits will give you a pointer to the bitmap, after that you are pretty much on your own.
|
|
|
|
|
I can not give any code but i suggest U logic behide that...U have to do some effort on it..
Some of the steps are:
First collect Desktop HWND.
-Throught HWND value fill BITMAPINFO structure instance.
-Send this object to Another Terminal.
-Using that object display that image data to CDC object of targeted window.
Actually i have completed this project, i have not remembred what excat function i have used but i sugget U go throght BITMAPINFO structure and using MSDN sample U would be get code to fill the BItmapinfo structure..
Hope that U will Understood my suggetion/Ideia...
With Regards,
Jagdish
|
|
|
|
|
hello,
Sir,
firstly thanks for your great work related this artical
becoz this artical has help me very nuch!.
But still i have a Que -how can i get image into memory.
i mean to say that i want to transer current desktop image to
another Pc so how can collect current desktop image.I have alredy tried it by creating bitmap file(.bmp) and then sending
that file to another PC.But problem is that becoz of file r/w
there is too long delay so that at another end cant get current image.If anybody has idies or solN then help me.
|
|
|
|
|
It is not entirely clear what your question is about.
I've already shown how to capture a screen, and you claim you have already captured the desktop. So there is no question how to get an image into memory.
As far as sending it, you should compress it, using GIF, JPEG, or some other form of data compression of your choice. Zip might also work, although JPEG will probably give the best compression if a photo is on the screen. In any case, you can expect it will take a few seconds to transmit this image over a high-bandwidth communication channel, and vastly longer on dialup modems.
|
|
|
|
|
thanks for attention me.
Actualy i want to transfer image from one Pc to Another Pc.
if current desktop image is alrady in memory then how can i collect all the data ralated to that image.
I mean to say that if memDC object of CDC class contains data about image(using bitblt() fun of CDC).then how can i collect that image data to another memory location.Or How can i transfer that image to another socket(Pc) by using that memDC object.
I hope that you understood my problem.
thanking you,
Jagdish
|
|
|
|
|
There are several possible answers here.
First, if you are trying to do some sort of remote control, be aware that (a) this is very, very nontrivial and (b) it is not done by capturing screen images.
By "already in memory", I presume you mean that you have used the techniques I described to actually capture the screen.
If you have a memory DC with a bitmap, you can get the bitmap image using GetBitmapBits, GetDIBits, etc. You cannot transfer it to another PC by using a memDC; you have to extract the bits from the memory DC, then send them via a socket to another computer, which is running the other side of the communication, which transfers the bits into a memDC, and then displays it on another window.
Sending a bitmap for a 1024x178 display requires a minimum of 2,359,296 bytes for 24-bit color. But not all those bytes have to be transmitted. Using compression schemes such as JPEG, GIF, or even ZIP, you can sometimes compress that image down by a factor of 20:1 (on a good day, with luck). Thus, on a good day you might only need 120K bytes. Your Mileage May Vary.
The time taken to do the transmission is, of course, a function of the network bandwidth. But don't think 100Base-T (100Mb/s) can actually transfer 100Mb/s. Concepts such as packetization mean that you will get a certain overhead every, well, 1456 bytes. You might need 85-100 packets to transmit a compressed image; five or ten times that for one that does not compress well. Add to this the transmission overhead, packet flow control, etc. and you will be lucky to get anything vaguely useful. Figure your best will be 1Mb, your worst, 18Mb. So the worst case would take, if 100% of the bandwidth could be used, about 188ms per screen. But realistically, you might expect to get one or two screens per second under worst case, over 100Base-T. For 10Base-T, that's one screen every 5 to 10 seconds. By the time you get to 1000Base-T (gigabit copper) you would hope to see 20ms/screen, but I doubt you can get that rate (that's 50 frames/sec, and I know that doesn't happen over 1000Base-T without a LOT of effort).
Dialup is ruled out entirely.
|
|
|
|
|
thanks for reply me.
but sir,Actualy i dont know to much about GetDibBits function.how i can use it and how i can set DIB bits at other end.if possible then plz give me some code that will be help me........
Waiting for reply....
Regards,
Jagdish
|
|
|
|
|
As to how to use it, you have to read the documentation, same as I do. I use it about once every two years, and whenver I need to use it, I just read the documentation. Same for SetDIBits.
joe
|
|
|
|
|