GDI_CapturingAnImage.cpp:“StretchBlt失败了”

时间:2014-07-20 09:29:05

标签: c++ windows winapi

这是我Where can I download "GDI_CapturingAnImage.h"?部分回答之后的后续问题,但我的代码中还有很多其他错误。

我不明白为什么这个程序无法运行。我可以编译它没有错误,但我只是在运行应用程序时出错。调试器只是说程序' [7588] Screenshot.exe'已退出代码0(0x0)。:

// GDI_CapturingAnImage.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Resource.h"
#include "Screenshot.h"
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
//#include "GDI_CapturingAnImage.h"

HWND hWnd;

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved

//
//   FUNCTION: CaptureAnImage(HWND hWnd)
//
//   PURPOSE: Captures a screenshot into a window and then saves it in a .bmp file.
//
//   COMMENTS: 
//
//      Note: This sample will attempt to create a file called captureqwsx.bmp 
//        



int CaptureAnImage(HWND hWnd)
{
    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(hWnd);

    // 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(hWnd, &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, 
               rcClient.right, rcClient.bottom, 
               hdcScreen, 
               0,0,
               GetSystemMetrics (SM_CXSCREEN),
               GetSystemMetrics (SM_CYSCREEN),
               SRCCOPY))
    {
        MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK);
        goto done;
    }

    // Create a compatible bitmap from the Window DC
    hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);

    if(!hbmScreen)
    {
        MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
        goto done;
    }

    // Select the compatible bitmap into the compatible memory DC.
    SelectObject(hdcMemDC,hbmScreen);

    // Bit block transfer into our compatible memory DC.
    if(!BitBlt(hdcMemDC, 
               0,0, 
               rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, 
               hdcWindow, 
               0,0,
               SRCCOPY))
    {
        MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
        goto done;
    }

    // Get the BITMAP from the HBITMAP
    GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);

    BITMAPFILEHEADER   bmfHeader;    
    BITMAPINFOHEADER   bi;

    bi.biSize = sizeof(BITMAPINFOHEADER);    
    bi.biWidth = bmpScreen.bmWidth;    
    bi.biHeight = bmpScreen.bmHeight;  
    bi.biPlanes = 1;    
    bi.biBitCount = 32;    
    bi.biCompression = BI_RGB;    
    bi.biSizeImage = 0;  
    bi.biXPelsPerMeter = 0;    
    bi.biYPelsPerMeter = 0;    
    bi.biClrUsed = 0;    
    bi.biClrImportant = 0;

    DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;

    // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
    // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
    // have greater overhead than HeapAlloc.
    HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize); 
    char *lpbitmap = (char *)GlobalLock(hDIB);    

    // Gets the "bits" from the bitmap and copies them into a buffer 
    // which is pointed to by lpbitmap.
    GetDIBits(hdcWindow, hbmScreen, 0,
        (UINT)bmpScreen.bmHeight,
        lpbitmap,
        (BITMAPINFO *)&bi, DIB_RGB_COLORS);

    // A file is created, this is where we will save the screen capture.
    HANDLE hFile = CreateFile(L"captureqwsx.bmp",
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);   

    // Add the size of the headers to the size of the bitmap to get the total file size
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    //Offset to where the actual bitmap bits start.
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); 

    //Size of the file
    bmfHeader.bfSize = dwSizeofDIB; 

    //bfType must always be BM for Bitmaps
    bmfHeader.bfType = 0x4D42; //BM   

    DWORD dwBytesWritten = 0;
    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);

    //Unlock and Free the DIB from the heap
    GlobalUnlock(hDIB);    
    GlobalFree(hDIB);

    //Close the handle for the file that was created
    CloseHandle(hFile);

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

    return 0;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND    - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY    - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_CREATE:
        {
        break;
        }
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
//            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;

    case WM_MOVE:

    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        CaptureAnImage(hWnd);
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}



#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                        // current instance
TCHAR szTitle[MAX_LOADSTRING];          // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];    // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);



int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MSG msg;
    HACCEL hAccelTable;



    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_GDI_CAPTURINGANIMAGE, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }



    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDI_CAPTURINGANIMAGE));

    // Main message loop:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GDI_CAPTURINGANIMAGE));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_GDI_CAPTURINGANIMAGE);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{


   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);



   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   CaptureAnImage(hWnd);

   return TRUE;



}

编辑:

我在hWnd = CreateWindow中设置断点时的callstack(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);     :

>   Screenshot.exe!InitInstance(HINSTANCE__ * hInstance, int nCmdShow) Line 363 C++
    Screenshot.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 288   C++
    Screenshot.exe!__tmainCRTStartup() Line 528 C
    Screenshot.exe!wWinMainCRTStartup() Line 377    C
    kernel32.dll!75ac338a() Unknown
    [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]  
    ntdll.dll!77bd9f72()    Unknown
    ntdll.dll!77bd9f45()    Unknown

汽车:

-       hInst   0x00890000 {Screenshot.exe!_IMAGE_DOS_HEADER __ImageBase} {unused=9460301 } HINSTANCE__ *
        unused  9460301 int
-       hInstance   0x00890000 {Screenshot.exe!_IMAGE_DOS_HEADER __ImageBase} {unused=9460301 } HINSTANCE__ *
        unused  9460301 int
-       hWnd    0x00000000 {unused=??? }    HWND__ *
        unused  <Unable to read memory> 
-       szTitle 0x008a9138 L"Screenshot"    wchar_t[100]
        [0] 83 'S'  wchar_t
        [1] 99 'c'  wchar_t
        [2] 114 'r' wchar_t
        [3] 101 'e' wchar_t
        [4] 101 'e' wchar_t
        [5] 110 'n' wchar_t
        [6] 115 's' wchar_t
        [7] 104 'h' wchar_t
        [8] 111 'o' wchar_t
        [9] 116 't' wchar_t
        [10]    0 '\0'  wchar_t
        [11]    0 '\0'  wchar_t
        [12]    0 '\0'  wchar_t
        [13]    0 '\0'  wchar_t
        [14]    0 '\0'  wchar_t
        [15]    0 '\0'  wchar_t
        [16]    0 '\0'  wchar_t
        [17]    0 '\0'  wchar_t
        [18]    0 '\0'  wchar_t
        [19]    0 '\0'  wchar_t
        [20]    0 '\0'  wchar_t
        [21]    0 '\0'  wchar_t
        [22]    0 '\0'  wchar_t
        [23]    0 '\0'  wchar_t
        [24]    0 '\0'  wchar_t
        [25]    0 '\0'  wchar_t
        [26]    0 '\0'  wchar_t
        [27]    0 '\0'  wchar_t
        [28]    0 '\0'  wchar_t
        [29]    0 '\0'  wchar_t
        [30]    0 '\0'  wchar_t
        [31]    0 '\0'  wchar_t
        [32]    0 '\0'  wchar_t
        [33]    0 '\0'  wchar_t
        [34]    0 '\0'  wchar_t
        [35]    0 '\0'  wchar_t
        [36]    0 '\0'  wchar_t
        [37]    0 '\0'  wchar_t
        [38]    0 '\0'  wchar_t
        [39]    0 '\0'  wchar_t
        [40]    0 '\0'  wchar_t
        [41]    0 '\0'  wchar_t
        [42]    0 '\0'  wchar_t
        [43]    0 '\0'  wchar_t
        [44]    0 '\0'  wchar_t
        [45]    0 '\0'  wchar_t
        [46]    0 '\0'  wchar_t
        [47]    0 '\0'  wchar_t
        [48]    0 '\0'  wchar_t
        [49]    0 '\0'  wchar_t
        [50]    0 '\0'  wchar_t
        [51]    0 '\0'  wchar_t
        [52]    0 '\0'  wchar_t
        [53]    0 '\0'  wchar_t
        [54]    0 '\0'  wchar_t
        [55]    0 '\0'  wchar_t
        [56]    0 '\0'  wchar_t
        [57]    0 '\0'  wchar_t
        [58]    0 '\0'  wchar_t
        [59]    0 '\0'  wchar_t
        [60]    0 '\0'  wchar_t
        [61]    0 '\0'  wchar_t
        [62]    0 '\0'  wchar_t
        [63]    0 '\0'  wchar_t
        [64]    0 '\0'  wchar_t
        [65]    0 '\0'  wchar_t
        [66]    0 '\0'  wchar_t
        [67]    0 '\0'  wchar_t
        [68]    0 '\0'  wchar_t
        [69]    0 '\0'  wchar_t
        [70]    0 '\0'  wchar_t
        [71]    0 '\0'  wchar_t
        [72]    0 '\0'  wchar_t
        [73]    0 '\0'  wchar_t
        [74]    0 '\0'  wchar_t
        [75]    0 '\0'  wchar_t
        [76]    0 '\0'  wchar_t
        [77]    0 '\0'  wchar_t
        [78]    0 '\0'  wchar_t
        [79]    0 '\0'  wchar_t
        [80]    0 '\0'  wchar_t
        [81]    0 '\0'  wchar_t
        [82]    0 '\0'  wchar_t
        [83]    0 '\0'  wchar_t
        [84]    0 '\0'  wchar_t
        [85]    0 '\0'  wchar_t
        [86]    0 '\0'  wchar_t
        [87]    0 '\0'  wchar_t
        [88]    0 '\0'  wchar_t
        [89]    0 '\0'  wchar_t
        [90]    0 '\0'  wchar_t
        [91]    0 '\0'  wchar_t
        [92]    0 '\0'  wchar_t
        [93]    0 '\0'  wchar_t
        [94]    0 '\0'  wchar_t
        [95]    0 '\0'  wchar_t
        [96]    0 '\0'  wchar_t
        [97]    0 '\0'  wchar_t
        [98]    0 '\0'  wchar_t
        [99]    0 '\0'  wchar_t
-       szWindowClass   0x008a9200 L""  wchar_t[100]
        [0] 0 '\0'  wchar_t
        [1] 0 '\0'  wchar_t
        [2] 0 '\0'  wchar_t
        [3] 0 '\0'  wchar_t
        [4] 0 '\0'  wchar_t
        [5] 0 '\0'  wchar_t
        [6] 0 '\0'  wchar_t
        [7] 0 '\0'  wchar_t
        [8] 0 '\0'  wchar_t
        [9] 0 '\0'  wchar_t
        [10]    0 '\0'  wchar_t
        [11]    0 '\0'  wchar_t
        [12]    0 '\0'  wchar_t
        [13]    0 '\0'  wchar_t
        [14]    0 '\0'  wchar_t
        [15]    0 '\0'  wchar_t
        [16]    0 '\0'  wchar_t
        [17]    0 '\0'  wchar_t
        [18]    0 '\0'  wchar_t
        [19]    0 '\0'  wchar_t
        [20]    0 '\0'  wchar_t
        [21]    0 '\0'  wchar_t
        [22]    0 '\0'  wchar_t
        [23]    0 '\0'  wchar_t
        [24]    0 '\0'  wchar_t
        [25]    0 '\0'  wchar_t
        [26]    0 '\0'  wchar_t
        [27]    0 '\0'  wchar_t
        [28]    0 '\0'  wchar_t
        [29]    0 '\0'  wchar_t
        [30]    0 '\0'  wchar_t
        [31]    0 '\0'  wchar_t
        [32]    0 '\0'  wchar_t
        [33]    0 '\0'  wchar_t
        [34]    0 '\0'  wchar_t
        [35]    0 '\0'  wchar_t
        [36]    0 '\0'  wchar_t
        [37]    0 '\0'  wchar_t
        [38]    0 '\0'  wchar_t
        [39]    0 '\0'  wchar_t
        [40]    0 '\0'  wchar_t
        [41]    0 '\0'  wchar_t
        [42]    0 '\0'  wchar_t
        [43]    0 '\0'  wchar_t
        [44]    0 '\0'  wchar_t
        [45]    0 '\0'  wchar_t
        [46]    0 '\0'  wchar_t
        [47]    0 '\0'  wchar_t
        [48]    0 '\0'  wchar_t
        [49]    0 '\0'  wchar_t
        [50]    0 '\0'  wchar_t
        [51]    0 '\0'  wchar_t
        [52]    0 '\0'  wchar_t
        [53]    0 '\0'  wchar_t
        [54]    0 '\0'  wchar_t
        [55]    0 '\0'  wchar_t
        [56]    0 '\0'  wchar_t
        [57]    0 '\0'  wchar_t
        [58]    0 '\0'  wchar_t
        [59]    0 '\0'  wchar_t
        [60]    0 '\0'  wchar_t
        [61]    0 '\0'  wchar_t
        [62]    0 '\0'  wchar_t
        [63]    0 '\0'  wchar_t
        [64]    0 '\0'  wchar_t
        [65]    0 '\0'  wchar_t
        [66]    0 '\0'  wchar_t
        [67]    0 '\0'  wchar_t
        [68]    0 '\0'  wchar_t
        [69]    0 '\0'  wchar_t
        [70]    0 '\0'  wchar_t
        [71]    0 '\0'  wchar_t
        [72]    0 '\0'  wchar_t
        [73]    0 '\0'  wchar_t
        [74]    0 '\0'  wchar_t
        [75]    0 '\0'  wchar_t
        [76]    0 '\0'  wchar_t
        [77]    0 '\0'  wchar_t
        [78]    0 '\0'  wchar_t
        [79]    0 '\0'  wchar_t
        [80]    0 '\0'  wchar_t
        [81]    0 '\0'  wchar_t
        [82]    0 '\0'  wchar_t
        [83]    0 '\0'  wchar_t
        [84]    0 '\0'  wchar_t
        [85]    0 '\0'  wchar_t
        [86]    0 '\0'  wchar_t
        [87]    0 '\0'  wchar_t
        [88]    0 '\0'  wchar_t
        [89]    0 '\0'  wchar_t
        [90]    0 '\0'  wchar_t
        [91]    0 '\0'  wchar_t
        [92]    0 '\0'  wchar_t
        [93]    0 '\0'  wchar_t
        [94]    0 '\0'  wchar_t
        [95]    0 '\0'  wchar_t
        [96]    0 '\0'  wchar_t
        [97]    0 '\0'  wchar_t
        [98]    0 '\0'  wchar_t
        [99]    0 '\0'  wchar_t

1 个答案:

答案 0 :(得分:2)

你有无效的HWND,因为你在注册窗口类之前创建窗口。

我推荐阅读一些关于Windows编程的书籍。另外如果你在调试器下运行它,你会看到这一点。