win32 Snipping Tool-esque program problems

I want to recreate window's snipping tool and I'm referring to this topic: http://msdn.microsoft.com/en-us/library/dd183402%28v=vs.85%29.aspx

The problem is I want to display the screenshot in a new window, but it displays a white window. I don't know why it doesn't work.
I've bolded the code I've modified. I don't know where to go from here. Please help.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int CaptureAnImage(HWND hwnd)
{
	
    // Create a topmost window and print image in the window, overlapping everything on screen.
    HWND testhwnd =		CreateWindow(L"STATIC", NULL,
					     SS_BITMAP| WS_POPUPWINDOW, 
					     0, 0, 
					     GetSystemMetrics(SM_CXVIRTUALSCREEN), 
					     GetSystemMetrics(SM_CYVIRTUALSCREEN),
					     NULL, NULL, NULL, NULL);

    HDC hdcScreen;
    HDC hdcWindow;
    HDC hdcMemDC = NULL;
    HBITMAP hbmScreen = NULL;
    BITMAP bmpScreen;

    // Retrieve the handle to a display device context for the client 
    // area of the window. 
    hdcScreen = GetDC(NULL);
    hdcWindow = GetDC(testhwnd);

    // Create a compatible DC which is used in a BitBlt from the window DC
    hdcMemDC = CreateCompatibleDC(hdcWindow); 

    if(!hdcMemDC)
    {
        MessageBox(hwnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK);
        goto done;
    }

    // Get the client area for size calculation
    RECT rcClient;
    GetClientRect(testhwnd, &rcClient);

    //This is the best stretch mode
    SetStretchBltMode(hdcWindow,HALFTONE);

    //The source DC is the entire screen and the destination DC is the current window (HWND)
    if(!StretchBlt(hdcWindow, 
				   0,0, 
				   GetSystemMetrics (SM_CXVIRTUALSCREEN)-10,
				   GetSystemMetrics (SM_CYVIRTUALSCREEN)-10,
				   //rcClient.right, rcClient.bottom, 
				   hdcScreen, 
				   0,0,
				   GetSystemMetrics (SM_CXVIRTUALSCREEN),
				   GetSystemMetrics (SM_CYVIRTUALSCREEN),
				   SRCCOPY))
    {
        MessageBox(hwnd, L"StretchBlt has failed",L"Failed", MB_OK);
        goto done;
    }
	ShowWindow(testhwnd, SW_SHOW);

    //Clean up
done:
    DeleteObject(hbmScreen);
    DeleteObject(hdcMemDC);
    ReleaseDC(NULL,hdcScreen);
    ReleaseDC(testhwnd,hdcWindow);

    return 0;
}
Edit: it's just sunk it that you trying to create a popup static window. Control windows are not intended to be used as main windows (WS_OVERLAPPED or WS_POPUP), only as child windows (WS_CHILD). What you need to do is create a dialog with a static control and then display that (with either DialogBox or CreateDialog)

And static controls with the SS_BITMAP style will draw the bitmap for you. You set the bitmap by sending it a STM_SETIMAGE message with the HBITMAP to the required image.

This does require you to capture to a bitmap, obviously.

STM_SETIMAGE message
http://msdn.microsoft.com/en-us/library/windows/desktop/bb760782%28v=vs.85%29.aspx

How to create the bitmap

Capturing an Image
http://msdn.microsoft.com/en-us/library/windows/desktop/dd183402%28v=vs.85%29.aspx

Andy

Edit: Previous attempt (spotted WS_POPUPWINDOW, whe looking for SS_BITMAP...)

Where is CaptureAnImage() called from?

As it stands...

- Windows are responsible for drawing themselves (at least most of the time).
- The static control you create will be painting over what you draw in it's window (usually using light grey), as it's called to paint after its parent (as with all child windows.) So you won't see what you draw.
- You could subclass the static window to stop it drawing, but...
- As you are doing the drawing, you might as well just draw into the main window, rather than use the static. (You could use a (hidden) static control as a positioning aid; this is more uncommonly used with dialogs.)
- or get the static to do the work for you by sending it the HBITMAP to the required image using the STM_SETBITMAP message.

Andy

Last edited on
Sorry Andy, I still can't figure out what to do after trying your advice.

I tried replacing testhwnd with a dialog using this:
 
HWND testdialog =	CreateDialog(hINSTANCE, L"dialogname", hWnd, DlgProc);

The result was the screen was captured and drawn over my current screen, but any draws made by other windows will draw over my screenshot.

I tried nesting a static control and sending the STM_SETIMAGE message to the static control, but I got the same result as I did initially.
1
2
3
4
5
6
7
8
9
10
HWND testdialog =	CreateDialog(hINSTANCE, L"dialogname", hWnd, DlgProc);
HWND staticctrl =	CreateWindow(L"STATIC", NULL,
				SS_BITMAP,
				0, 0, 
				GetSystemMetrics(SM_CXVIRTUALSCREEN), 
				GetSystemMetrics(SM_CYVIRTUALSCREEN),
				testdialog, NULL, NULL, NULL);
/* some code */
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
SendMessage(staticctrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmScreen);


How can I make the screenshot repaint itself(not go away if something else moves)? Also with the dialog it doesn't seem to feel like the dialog actually exists. Sorry for my ignorance. I tried searching for hours to solve this but either I'm bad at searching or there's not much discussion about this online.
The STATIC control should be defined by the dialog template, not created independently.

You then use GetDlgItem() to get the control handle and post the message to it.

1
2
3
4
5
HWND testdialog =	CreateDialog(hINSTANCE, L"dialogname", hWnd, DlgProc);
HWND staticctrl =	GetDlgItem(testdialog, ID_STATIC_IMAGE);
/* some code */
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
SendMessage(staticctrl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmScreen);


where ID_STATIC_IMAGE is the ID of your static control (defined in resource.h)

But if you're trying to make it screen sized, then the dialog approach mght be the wrong choice. You will prob need a custom window class.

Andy
Topic archived. No new replies allowed.