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;
}

Related articles: