1

I am trying to get a 500x500 screenshot from the 0x0 (top-left) position of screen and put it in a window.

Here is my code (hwnd is my Window Handle):

HDC appDc = GetDC(hwnd);
HDC dc = GetDC(NULL);
HBITMAP bitmap = CreateCompatibleBitmap(dc, 500, 500);
HDC memoryDc = CreateCompatibleDC(dc);
SelectObject(memoryDc, bitmap);
BitBlt(appDc, 0, 0, 500, 500, dc, 0, 0, SRCCOPY);
ShowWindow(hwnd, SW_SHOW);
SetWindowText(hwnd, _T("Window"));   

What am I missing here? I am getting black inside the window instead of the screen capture.

EDIT

It works after I changed memoryDc to dc It previously was BitBlt(appDc, 0, 0, 500, 500, memoryDc, 0, 0, SRCCOPY); But now the problem is SelectObject is not working.I meant Its not putting the Image in HBITMAP. However BitBlt is copying from dc to appDc

Neel Basu
  • 12,638
  • 12
  • 82
  • 146
  • Concerning your edit: blitting from `dc` to `appDc` outputs it in your window. To get it into your bitmap, blit from `dc` to `memoryDc`. – Thalur Mar 31 '11 at 12:25

2 Answers2

1

First, there seems to be a confusion with the device contexts. You blit from memoryDc to appDc, but memoryDc does not contain anything - it has been created to be compatible to dc, but that does not mean it shares the content. Also, you do not release the DCs in your example.

Second, your call to ShowWindow() seems to imply that the window has not been visible before. If that is the case, anything that has been "drawn" before has not actually been drawn and will not be visible in the window. Capture the screen content in a bitmap and display it during WM_PAINT.

Thalur
  • 1,155
  • 9
  • 13
0

Since you're calling ShowWindow for your application's window at the end of the code block, I assume that the window is not visible prior to that time.

If so, then that is your problem because when an invisible window is made visible again, its client area is always repainted. This causes its background to be erased with the default brush for that window (apparently a black brush, in your case), and anything that you painted (using the BitBlt function) into its device context (DC) to be lost.

A better approach would be to draw the screen capture into a temporary bitmap, instead. Then, just keep a copy of this bitmap around and paint it onto the window whenever you receive a WM_PAINT message.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • @Neel: The edit doesn't change anything. The `BitBlt` function is still copying the image of the desktop to your window's device context. As soon as the window is shown, however, it gets erased and redrawn. That's why you don't see anything you draw into its device context. You need to change that line to `BitBlt(memoryDc, 0, 0, 500, 500, dc, 0, 0, SRCCOPY);`. You *also* need to clean up after yourself. I hope you've just omitted that code from your question, but you **absolutely must call [`ReleaseDC`](http://msdn.microsoft.com/en-us/library/dd162920.aspx)** on the desktop window. – Cody Gray - on strike Mar 31 '11 at 12:34
  • Ya I understand. This is just a Dry Code. I'll run `ReleaseDC` at the end. and at the moment I am getting the Screen's 0x0 top-left screenshot of 500x500 size in my `appDc` However What I actually wanted is to get the Screenshot to `HBITMAP` and show *that* `HBITMAP` into the `appDc` (The Application window) – Neel Basu Mar 31 '11 at 13:13
  • @Neel: I don't know what a Dry Code is, but it's difficult to provide helpful feedback when you're not looking at the *real* code. You can't always assume users know about stuff like freeing memory. Anyway, maybe I don't understand what's going on. You've selected the bitmap into the memory DC, so you need to blit the image of the desktop into that memory DC. That'll get it on the bitmap, then you can paint the bitmap onto your application window whenever you want. Why isn't that working? – Cody Gray - on strike Mar 31 '11 at 13:22