Een afbeelding vastleggen
U kunt een bitmap gebruiken om een afbeelding vast te leggen en u kunt de vastgelegde afbeelding opslaan in het geheugen, deze weergeven op een andere locatie in het venster van uw toepassing of weergeven in een ander venster.
In sommige gevallen wilt u mogelijk dat uw toepassing afbeeldingen vastlegt en deze slechts tijdelijk opslaat. Wanneer u bijvoorbeeld een afbeelding schaalt of zoomt die in een tekentoepassing is gemaakt, moet de toepassing tijdelijk de normale weergave van de afbeelding opslaan en de ingezoomde weergave weergeven. Wanneer de gebruiker later de normale weergave selecteert, moet de toepassing de ingezoomde afbeelding vervangen door een kopie van de normale weergave die tijdelijk is opgeslagen.
Als u een afbeelding tijdelijk wilt opslaan, moet uw toepassing CreateCompatibleDC aanroepen om een apparaatcontext (DC) te maken die compatibel is met de huidige venster-DC. Nadat u een compatibele apparaatcontext hebt gemaakt, maakt u een bitmap met de juiste dimensies door de functie CreateCompatibleBitmap aan te roepen en deze vervolgens in deze apparaatcontext te selecteren door de functie SelectObject aan te roepen.
Nadat de compatibele apparaatcontext is gemaakt en de juiste bitmap erin is geselecteerd, kunt u de afbeelding vastleggen. Met de functie BitBlt worden afbeeldingen vastgelegd. Met deze functie wordt een bitblokoverdracht uitgevoerd. Dit houdt in dat gegevens van een bron bitmap naar een doel bitmap worden gekopieerd. De twee argumenten voor deze functie zijn echter geen bitmapgrepen. In plaats daarvan ontvangt BitBlt- handles om twee apparaatcontexten te identificeren en kopieert het de bitmapgegevens van een bitmap die is geselecteerd in de bronapparaatcontext naar een bitmap die is geselecteerd in de doelapparaatcontext. In dit geval is de doeldomeincontroller de compatibele DC, dus wanneer BitBlt de overdracht voltooit, is de afbeelding opgeslagen in het geheugen. Als u de afbeelding opnieuw wilt weergeven, roept u BitBlt een tweede keer aan, waarbij u de compatibele DC opgeeft als de bron-DC en een venster-DC (of printer-DC) als doel-DC.
Codevoorbeeld
Deze sectie bevat een codevoorbeeld waarmee een afbeelding van het hele bureaublad wordt vastgelegd, wordt deze omlaag geschaald naar de huidige venstergrootte en vervolgens opgeslagen in een bestand (evenals het weergeven in het clientgebied).
Als u het codevoorbeeld wilt uitproberen, begint u met het maken van een nieuw project in Visual Studio op basis van de Windows-bureaubladtoepassing projectsjabloon. Het is belangrijk om het nieuwe project de naam GDI_CapturingAnImage
te geven, zodat de code hieronder wordt gecompileerd (bijvoorbeeld, het bevat GDI_CapturingAnImage.h
, die in uw nieuwe project zal bestaan als u het de voorgestelde naam geeft).
Open het GDI_CapturingAnImage.cpp
broncodebestand in uw nieuwe project en vervang de inhoud door de onderstaande vermelding. Bouw en voer vervolgens uit. Telkens wanneer u het formaat van het venster wijzigt, ziet u de vastgelegde schermopname die wordt weergegeven in het clientgebied.
// GDI_CapturingAnImage.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "GDI_CapturingAnImage.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR 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 wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_GDICAPTURINGANIMAGE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDICAPTURINGANIMAGE));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW 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_GDICAPTURINGANIMAGE));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_GDICAPTURINGANIMAGE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&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 hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
// 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 function attempts to create a file called captureqwsx.bmp
//
int CaptureAnImage(HWND hWnd)
{
HDC hdcScreen;
HDC hdcWindow;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
BITMAP bmpScreen;
DWORD dwBytesWritten = 0;
DWORD dwSizeofDIB = 0;
HANDLE hFile = NULL;
char* lpbitmap = NULL;
HANDLE hDIB = NULL;
DWORD dwBmpSize = 0;
// 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;
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.
hDIB = GlobalAlloc(GHND, dwBmpSize);
lpbitmap = (char*)GlobalLock(hDIB);
// Gets the "bits" from the bitmap, and copies them into a buffer
// that's 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.
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.
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.
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)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(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_PAINT:
{
PAINTSTRUCT ps;
HDC 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;
}