这是我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
答案 0 :(得分:2)
你有无效的HWND,因为你在注册窗口类之前创建窗口。
我推荐阅读一些关于Windows编程的书籍。另外如果你在调试器下运行它,你会看到这一点。