VC++ based on Dx to achieve the screenshot procedure sample code
- 2020-04-02 02:28:21
- OfStack
The procedure described in this article is VC++ image effects screenshot example, need DirectX 3.0 version above, the GetScreen function in the code is the key to the screenshot procedure. Running this program ends with the Esc key. Ddutil. H and ddutil. CPP files are needed in the code, please download and add them by yourself. For the InitDDraw() function, it initializes the DirectDraw environment, creates a pager (main page, a background buffer), and creates a timer.
The specific functional code is as follows:
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <ddraw.h>
#include <math.h>
#include "ddutil.h"
#define TITLE " Screenshot of the sample " //The window title
#define CLASSNAME "GetScreen" //The window class name
#define COLORS 16
HINSTANCE hInst; //Application instance handle
HWND hWndMain; //Handle to the main window
LPDIRECTDRAW lpDD; //DirectDraw object
LPDIRECTDRAWSURFACE lpDDSPrimary; //The main page
LPDIRECTDRAWSURFACE lpDDSBack; //Background buffer
LPDIRECTDRAWSURFACE lpDDSPic1; //Off screen 1
LPDIRECTDRAWPALETTE lpDDPal; //The palette
BOOL bActive; //Application is active ?
HBITMAP hbm;
RECT rect;
//Function declaration
void FreeObjects( void );
BOOL InitDDraw(void);
BOOL InitSurfaces(void);
void UpdateFrame(void);
void MakeRect(RECT *rect, long left, long top, long right, long bottom);
///////////////////////////////////////////////
//Screenshot function, is the key to the program
//Function name: GetScreen
//Parameter: pointer to the screen rectangle
//Return value: Bitmap device
//////////////////////////////////////////////
HANDLE GetScreen(LPRECT lpRect)
{
//Define the screen DC and memory DC
HDC hScrDC,hMemDC;
//Define the Bitmap device
HANDLE hBitmap,hOldBitmap;
//Define screen coordinate variables
unsigned int nX,nY,nX2,nY2;
unsigned int nWidth,nHeight;
//Define the screen resolution variable
unsigned int xScrn,yScrn;
//Make sure the screen rectangle is not empty
if(IsRectEmpty(lpRect))
return NULL;
//Create the DC for the screen
hScrDC=CreateDC("DISPLAY",NULL,NULL,NULL);
//Memory DC created
hMemDC=CreateCompatibleDC(hScrDC);
//The screen rectangle coordinates are paid to the coordinate variable
nX=lpRect->left;
nY=lpRect->top ;
nX2=lpRect->right ;
nY2=lpRect->bottom ;
//Get screen resolution
xScrn=GetDeviceCaps(hScrDC,HORZRES);
yScrn=GetDeviceCaps(hScrDC,VERTRES);
if(nX<0)
nX=0;
if(nY<0)
nY=0;
if(nX2>xScrn)
nX2=xScrn;
if(nY2>yScrn)
nY2=yScrn;
//Gets screen width and length
nWidth=nX2-nX;
nHeight=nY2-nY;
//Get the screen image and pay a Bitmap device
hBitmap=CreateCompatibleBitmap(hScrDC,nWidth,nHeight);
hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);
BitBlt(hMemDC,0,0,nWidth,nHeight,hScrDC,nX,nY,SRCCOPY);
hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);
//Remove equipment
DeleteDC(hScrDC);
DeleteDC(hMemDC);
return hBitmap;
}
//*******************************************************************
//Function: FreeObject
//Function: releases all DirectDraw objects
//*******************************************************************
void FreeObjects( void )
{
//Frees the HBM bitmap object
DeleteObject(hbm);
if( lpDD != NULL )//Release the DirectDraw object
{
if( lpDDSPrimary != NULL )//Release main page
{
lpDDSPrimary->Release();
lpDDSPrimary = NULL;
}
if( lpDDSPic1 != NULL )//Release off screen 1
{
lpDDSPic1->Release();
lpDDSPic1 = NULL;
}
if( lpDDPal != NULL )//Release the palette
{
lpDDPal->Release();
lpDDPal = NULL;
}
lpDD->Release();
lpDD = NULL;
}
}
//*******************************************************************
//Function: RestoreAll
//Function: restore page memory after page loss
//*******************************************************************
HRESULT RestoreAll( void )
{
HRESULT ddrval;
//Restore the main page, which will also restore all pages in the page-changing chain
ddrval = lpDDSPrimary->Restore();
//Restore the off - screen page
ddrval = lpDDSPic1->Restore();
//Redraw the page image
InitSurfaces();
return ddrval;
}
//*******************************************************************
//Function: WindowProc
//Function: message processing for the main window
//*******************************************************************
LRESULT CALLBACK WinProc( HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_SETCURSOR:
SetCursor(LoadCursor( NULL, IDC_ARROW ));
return TRUE;
case WM_ACTIVATEAPP://Application activation messages
bActive = wParam;
break;
case WM_KEYDOWN://Keystroke messages
switch( wParam )
{
case VK_ESCAPE:
PostMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_DESTROY://Destroy window message
FreeObjects();
PostQuitMessage(0);
break;
}
//Invokes the default procedure handler
return DefWindowProc(hWnd, message, wParam, lParam);
}
//******************************************************************
//Function: InitWindow ()
//Function: create the main window.
//******************************************************************
BOOL InitWindow( HINSTANCE hInstance, int nCmdShow )
{
WNDCLASS wc; //Window class structure
// fill Window class structure
wc.style = 0;
wc.lpfnWndProc = WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);//Select the black brush as the window background
wc.lpszMenuName = NULL;
wc.lpszClassName = CLASSNAME;
//Register window class
RegisterClass( &wc );
//Create the main window
hWndMain= CreateWindowEx(
0,
CLASSNAME, //The class name of the window must be the same as the wc.lpszclassname above
TITLE, //The title name of the window
WS_POPUP,
0,
0,
GetSystemMetrics( SM_CXSCREEN ),
GetSystemMetrics( SM_CYSCREEN ),
NULL,
NULL,
hInstance,
NULL );
if( !hWndMain )
return FALSE;
//Displays and updates the window
ShowWindow( hWndMain, nCmdShow );
return TRUE;
}
//******************************************************************
//Function: InitDDraw ()
//Function: initialize DirectDraw environment, create pager (main page, a background buffer)
//And create a timer.
//******************************************************************
BOOL InitDDraw(void)
{
DDSURFACEDESC ddsd;
DDSCAPS ddscaps;
HRESULT ddrval;
//Create a DirectDraw object
ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
if( ddrval != DD_OK )
return FALSE;
//Get full screen exclusive mode
ddrval = lpDD->SetCooperativeLevel( hWndMain, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
if( ddrval != DD_OK )
return FALSE;
//Set the display mode to the resolution of the current screen, 16-bit enhanced display mode
ddrval = lpDD->SetDisplayMode(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), COLORS);
if( ddrval != DD_OK )
return FALSE;
//Fill in the paging chain structure
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP |
DDSCAPS_COMPLEX;
//The number of background buffers is 2
ddsd.dwBackBufferCount = 2;
//Create a swap chain that includes the main page and its background buffer
ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
if( ddrval != DD_OK )
return FALSE;
//Gets a page pointer to the background buffer
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
if( ddrval != DD_OK )
return FALSE;
//Create an off-screen page
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth =GetSystemMetrics(SM_CXSCREEN);
ddsd.dwHeight = GetSystemMetrics(SM_CYSCREEN);
if (lpDD->CreateSurface(&ddsd, &lpDDSPic1, NULL) != DD_OK)
return FALSE;
//Call the page initialization function
if( !InitSurfaces() )
return FALSE;
return TRUE;
}
//******************************************************************
//Function: the WinMain ()
//Function: application entry
//******************************************************************
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
hInst=hInstance;
//Get screen resolution
rect.left=rect.top=0;
rect.right=GetSystemMetrics(SM_CXSCREEN);
rect.bottom=GetSystemMetrics(SM_CYSCREEN);
//Call the screenshot function
hbm=(HBITMAP)GetScreen(&rect);
//Initializes the main window
if (!InitWindow( hInstance, nCmdShow))
return FALSE;
//Initialize the DirectDraw environment
if (!InitDDraw())
{
MessageBox(hWndMain, " Initialize the DirectDraw Error in the process! ", "Error", MB_OK);
FreeObjects();
DestroyWindow(hWndMain);
return FALSE;
}
//Enter the message loop
while(1)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if(!GetMessage(&msg, NULL, 0, 0 ))
return msg.wParam;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if(bActive)
{
UpdateFrame();
}
else WaitMessage();
}
return msg.wParam;
}
//******************************************************************
//Function: InitSurfaces ()
//Function: initialize page image
//******************************************************************
BOOL InitSurfaces( void )
{
if (hbm == NULL)
return FALSE;
DDCopyBitmap(lpDDSPic1, hbm, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
return TRUE;
}
//Update the screen
void UpdateFrame( void )
{
HRESULT ddrval;
//Clear the background buffer
DDBLTFX ddBltFx;
ddBltFx.dwSize = sizeof(DDBLTFX);
ddBltFx.dwFillColor = DDColorMatch(lpDDSBack, RGB(0,0,0));
lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddBltFx);
//Call the grayscale implementation function
RECT srect, drect;
MakeRect(&srect, 0, 0, rect.right ,rect.bottom);
MakeRect(&drect, 0, 0, rect.right , rect.bottom);
//Blit the background image to the background buffer
lpDDSBack->Blt(&drect, lpDDSPic1, &srect, DDBLT_WAIT, NULL);
//Change the page
while( 1 )
{
ddrval = lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );//Call the page-changing function
if( ddrval == DD_OK )//Success exits the while loop
break;
else if( ddrval == DDERR_SURFACELOST )//If the page is lost, the page is restored and the while loop continues
RestoreAll();
else
break;
}
}
void MakeRect(RECT *rect, long left, long top, long right, long bottom)
{
rect->left=left;
rect->top=top;
rect->right=right;
rect->bottom=bottom;
}