VC++基於Dx完成的截圖法式示例代碼。本站提示廣大學習愛好者:(VC++基於Dx完成的截圖法式示例代碼)文章只能為提供參考,不一定能成為您想要的結果。以下是VC++基於Dx完成的截圖法式示例代碼正文
本文所述的法式示例為VC++圖像殊效的截圖示例,須要DirectX 3.0以上版,代碼中的GetScreen函數是本截圖法式的症結。運轉這個法式可用Esc鍵停止。代碼中須要ddutil.h與ddutil.cpp文件,請自行下載添加。關於InitDDraw()函數,功效是初始化DirectDraw情況,創立換頁鏈(主頁面,一個後台緩沖區),和創立一個准時器。
詳細的功效代碼以下:
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <ddraw.h>
#include <math.h>
#include "ddutil.h"
#define TITLE "截圖示例" //窗口題目
#define CLASSNAME "GetScreen" //窗口類名
#define COLORS 16
HINSTANCE hInst; //運用法式實例句柄
HWND hWndMain; //主窗口句柄
LPDIRECTDRAW lpDD; // DirectDraw對象
LPDIRECTDRAWSURFACE lpDDSPrimary; // 主頁面
LPDIRECTDRAWSURFACE lpDDSBack; // 後台緩沖區
LPDIRECTDRAWSURFACE lpDDSPic1; // 離屏頁面1
LPDIRECTDRAWPALETTE lpDDPal; // 調色板
BOOL bActive; // 運用法式能否活潑?
HBITMAP hbm;
RECT rect;
//函數聲明
void FreeObjects( void );
BOOL InitDDraw(void);
BOOL InitSurfaces(void);
void UpdateFrame(void);
void MakeRect(RECT *rect, long left, long top, long right, long bottom);
///////////////////////////////////////////////
// 截圖函數,是本法式的症結
// 函數名:GetScreen
// 參數:指向屏幕矩形的指針
// 返值:Bitmap裝備
//////////////////////////////////////////////
HANDLE GetScreen(LPRECT lpRect)
{
//界說屏幕的DC和內存DC
HDC hScrDC,hMemDC;
//界說Bitmap裝備
HANDLE hBitmap,hOldBitmap;
//界說屏幕坐標變量
unsigned int nX,nY,nX2,nY2;
unsigned int nWidth,nHeight;
//界說屏幕分辨率變量
unsigned int xScrn,yScrn;
//確保屏幕矩形不為空
if(IsRectEmpty(lpRect))
return NULL;
//創立屏幕的DC
hScrDC=CreateDC("DISPLAY",NULL,NULL,NULL);
//創立的內存DC
hMemDC=CreateCompatibleDC(hScrDC);
//將屏幕矩形坐標付給坐標變量
nX=lpRect->left;
nY=lpRect->top ;
nX2=lpRect->right ;
nY2=lpRect->bottom ;
//取得屏幕分辨率
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;
//取得屏幕寬度與長度
nWidth=nX2-nX;
nHeight=nY2-nY;
//取得屏幕圖象並付給一個Bitmap裝備
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);
//消除裝備
DeleteDC(hScrDC);
DeleteDC(hMemDC);
return hBitmap;
}
//*******************************************************************
//函數:FreeObject
//功效:釋放一切DirectDraw對象
//*******************************************************************
void FreeObjects( void )
{
//釋放hbm位圖對象
DeleteObject(hbm);
if( lpDD != NULL )//釋放DirectDraw對象
{
if( lpDDSPrimary != NULL )//釋放主頁面
{
lpDDSPrimary->Release();
lpDDSPrimary = NULL;
}
if( lpDDSPic1 != NULL )//釋放離屏頁面1
{
lpDDSPic1->Release();
lpDDSPic1 = NULL;
}
if( lpDDPal != NULL )//釋放調色板
{
lpDDPal->Release();
lpDDPal = NULL;
}
lpDD->Release();
lpDD = NULL;
}
}
//*******************************************************************
//函數:RestoreAll
//功效:頁面喪失後,恢復頁面內存
//*******************************************************************
HRESULT RestoreAll( void )
{
HRESULT ddrval;
//恢復主頁面,這也將恢復換頁鏈中的一切頁面
ddrval = lpDDSPrimary->Restore();
//恢復離屏頁面
ddrval = lpDDSPic1->Restore();
//從新繪制頁面圖像
InitSurfaces();
return ddrval;
}
//*******************************************************************
//函數:WindowProc
//功效:主窗口的新聞處置進程
//*******************************************************************
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://運用法式激活新聞
bActive = wParam;
break;
case WM_KEYDOWN://擊鍵新聞
switch( wParam )
{
case VK_ESCAPE:
PostMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_DESTROY://燒毀窗口新聞
FreeObjects();
PostQuitMessage(0);
break;
}
//挪用缺省的進程處置進程
return DefWindowProc(hWnd, message, wParam, lParam);
}
//******************************************************************
//函數:InitWindow()
//功效:創立主窗口。
//******************************************************************
BOOL InitWindow( HINSTANCE hInstance, int nCmdShow )
{
WNDCLASS wc; //窗口類構造
//填充窗口類構造
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);//選擇黑色刷做為窗口配景
wc.lpszMenuName = NULL;
wc.lpszClassName = CLASSNAME;
//注冊窗口類
RegisterClass( &wc );
//創立主窗口
hWndMain= CreateWindowEx(
0,
CLASSNAME, //窗口的類稱號,必需與下面的wc.lpszClassName分歧
TITLE, //窗口的題目名
WS_POPUP,
0,
0,
GetSystemMetrics( SM_CXSCREEN ),
GetSystemMetrics( SM_CYSCREEN ),
NULL,
NULL,
hInstance,
NULL );
if( !hWndMain )
return FALSE;
//顯示並更新窗口
ShowWindow( hWndMain, nCmdShow );
return TRUE;
}
//******************************************************************
//函數:InitDDraw()
//功效:初始化DirectDraw情況,創立換頁鏈(主頁面,一個後台緩沖區)
// 和創立一個准時器。
//******************************************************************
BOOL InitDDraw(void)
{
DDSURFACEDESC ddsd;
DDSCAPS ddscaps;
HRESULT ddrval;
//創立DirectDraw對象
ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
if( ddrval != DD_OK )
return FALSE;
//獲得全屏獨有形式
ddrval = lpDD->SetCooperativeLevel( hWndMain, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
if( ddrval != DD_OK )
return FALSE;
//設置顯示器顯示形式為以後屏幕的分辨率,16位加強顯示形式
ddrval = lpDD->SetDisplayMode(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), COLORS);
if( ddrval != DD_OK )
return FALSE;
//填充換頁鏈構造
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP |
DDSCAPS_COMPLEX;
//後台緩沖區數目為2
ddsd.dwBackBufferCount = 2;
//創立換頁鏈,包含了主頁面及厥後台緩沖區
ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
if( ddrval != DD_OK )
return FALSE;
//取得指向後台緩沖區的頁面指針
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);
if( ddrval != DD_OK )
return FALSE;
//創立離屏頁面
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;
//挪用頁面初始化函數
if( !InitSurfaces() )
return FALSE;
return TRUE;
}
//******************************************************************
//函數:WinMain()
//功效:運用法式進口
//******************************************************************
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
hInst=hInstance;
//取得屏幕分辨率
rect.left=rect.top=0;
rect.right=GetSystemMetrics(SM_CXSCREEN);
rect.bottom=GetSystemMetrics(SM_CYSCREEN);
//挪用截屏函數
hbm=(HBITMAP)GetScreen(&rect);
//初始化主窗口
if (!InitWindow( hInstance, nCmdShow))
return FALSE;
//初始化DirectDraw情況
if (!InitDDraw())
{
MessageBox(hWndMain, "初始化DirectDraw進程中失足!", "Error", MB_OK);
FreeObjects();
DestroyWindow(hWndMain);
return FALSE;
}
//進入新聞輪回
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;
}
//******************************************************************
//函數:InitSurfaces()
//功效:初始化頁面圖像
//******************************************************************
BOOL InitSurfaces( void )
{
if (hbm == NULL)
return FALSE;
DDCopyBitmap(lpDDSPic1, hbm, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
return TRUE;
}
//更新屏幕
void UpdateFrame( void )
{
HRESULT ddrval;
//清屏後台緩沖區
DDBLTFX ddBltFx;
ddBltFx.dwSize = sizeof(DDBLTFX);
ddBltFx.dwFillColor = DDColorMatch(lpDDSBack, RGB(0,0,0));
lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddBltFx);
//挪用灰度的完成函數
RECT srect, drect;
MakeRect(&srect, 0, 0, rect.right ,rect.bottom);
MakeRect(&drect, 0, 0, rect.right , rect.bottom);
//將配景圖像Blit到後台緩沖區
lpDDSBack->Blt(&drect, lpDDSPic1, &srect, DDBLT_WAIT, NULL);
// 換頁
while( 1 )
{
ddrval = lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );//挪用換頁函數
if( ddrval == DD_OK )//勝利則加入while輪回
break;
else if( ddrval == DDERR_SURFACELOST )//假如頁面喪失,則恢復頁面,再持續while輪回
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;
}