VC++基于Dx實(shí)現(xiàn)的截圖程序示例代碼
本文所述的程序示例為VC++圖象特效的截圖示例,需要DirectX 3.0以上版,代碼中的GetScreen函數(shù)是本截圖程序的關(guān)鍵。運(yùn)行這個(gè)程序可用Esc鍵結(jié)束。代碼中需要ddutil.h與ddutil.cpp文件,請(qǐng)自行下載添加。關(guān)于InitDDraw()函數(shù),功能是初始化DirectDraw環(huán)境,創(chuàng)建換頁鏈(主頁面,一個(gè)后臺(tái)緩沖區(qū)),以及創(chuàng)建一個(gè)定時(shí)器。
具體的功能代碼如下:
#include <windows.h> #include <windowsx.h> #include <stdio.h> #include <ddraw.h> #include <math.h> #include "ddutil.h" #define TITLE "截圖示例" //窗口標(biāo)題 #define CLASSNAME "GetScreen" //窗口類名 #define COLORS 16 HINSTANCE hInst; //應(yīng)用程序?qū)嵗浔? HWND hWndMain; //主窗口句柄 LPDIRECTDRAW lpDD; // DirectDraw對(duì)象 LPDIRECTDRAWSURFACE lpDDSPrimary; // 主頁面 LPDIRECTDRAWSURFACE lpDDSBack; // 后臺(tái)緩沖區(qū) LPDIRECTDRAWSURFACE lpDDSPic1; // 離屏頁面1 LPDIRECTDRAWPALETTE lpDDPal; // 調(diào)色板 BOOL bActive; // 應(yīng)用程序是否活躍? HBITMAP hbm; RECT rect; //函數(shù)聲明 void FreeObjects( void ); BOOL InitDDraw(void); BOOL InitSurfaces(void); void UpdateFrame(void); void MakeRect(RECT *rect, long left, long top, long right, long bottom); /////////////////////////////////////////////// // 截圖函數(shù),是本程序的關(guān)鍵 // 函數(shù)名:GetScreen // 參數(shù):指向屏幕矩形的指針 // 返值:Bitmap設(shè)備 ////////////////////////////////////////////// HANDLE GetScreen(LPRECT lpRect) { //定義屏幕的DC和內(nèi)存DC HDC hScrDC,hMemDC; //定義Bitmap設(shè)備 HANDLE hBitmap,hOldBitmap; //定義屏幕坐標(biāo)變量 unsigned int nX,nY,nX2,nY2; unsigned int nWidth,nHeight; //定義屏幕分辯率變量 unsigned int xScrn,yScrn; //確保屏幕矩形不為空 if(IsRectEmpty(lpRect)) return NULL; //創(chuàng)建屏幕的DC hScrDC=CreateDC("DISPLAY",NULL,NULL,NULL); //創(chuàng)建的內(nèi)存DC hMemDC=CreateCompatibleDC(hScrDC); //將屏幕矩形坐標(biāo)付給坐標(biāo)變量 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; //獲得屏幕圖像并付給一個(gè)Bitmap設(shè)備 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); //清除設(shè)備 DeleteDC(hScrDC); DeleteDC(hMemDC); return hBitmap; } //******************************************************************* //函數(shù):FreeObject //功能:釋放所有DirectDraw對(duì)象 //******************************************************************* void FreeObjects( void ) { //釋放hbm位圖對(duì)象 DeleteObject(hbm); if( lpDD != NULL )//釋放DirectDraw對(duì)象 { if( lpDDSPrimary != NULL )//釋放主頁面 { lpDDSPrimary->Release(); lpDDSPrimary = NULL; } if( lpDDSPic1 != NULL )//釋放離屏頁面1 { lpDDSPic1->Release(); lpDDSPic1 = NULL; } if( lpDDPal != NULL )//釋放調(diào)色板 { lpDDPal->Release(); lpDDPal = NULL; } lpDD->Release(); lpDD = NULL; } } //******************************************************************* //函數(shù):RestoreAll //功能:頁面丟失后,恢復(fù)頁面內(nèi)存 //******************************************************************* HRESULT RestoreAll( void ) { HRESULT ddrval; //恢復(fù)主頁面,這也將恢復(fù)換頁鏈中的所有頁面 ddrval = lpDDSPrimary->Restore(); //恢復(fù)離屏頁面 ddrval = lpDDSPic1->Restore(); //重新繪制頁面圖象 InitSurfaces(); return ddrval; } //******************************************************************* //函數(shù):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://應(yīng)用程序激活消息 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; } //調(diào)用缺省的過程處理過程 return DefWindowProc(hWnd, message, wParam, lParam); } //****************************************************************** //函數(shù):InitWindow() //功能:創(chuàng)建主窗口。 //****************************************************************** BOOL InitWindow( HINSTANCE hInstance, int nCmdShow ) { WNDCLASS wc; //窗口類結(jié)構(gòu) //填充窗口類結(jié)構(gòu) 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; //注冊(cè)窗口類 RegisterClass( &wc ); //創(chuàng)建主窗口 hWndMain= CreateWindowEx( 0, CLASSNAME, //窗口的類名稱,必須與上面的wc.lpszClassName一致 TITLE, //窗口的標(biāo)題名 WS_POPUP, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ), NULL, NULL, hInstance, NULL ); if( !hWndMain ) return FALSE; //顯示并更新窗口 ShowWindow( hWndMain, nCmdShow ); return TRUE; } //****************************************************************** //函數(shù):InitDDraw() //功能:初始化DirectDraw環(huán)境,創(chuàng)建換頁鏈(主頁面,一個(gè)后臺(tái)緩沖區(qū)) // 以及創(chuàng)建一個(gè)定時(shí)器。 //****************************************************************** BOOL InitDDraw(void) { DDSURFACEDESC ddsd; DDSCAPS ddscaps; HRESULT ddrval; //創(chuàng)建DirectDraw對(duì)象 ddrval = DirectDrawCreate( NULL, &lpDD, NULL ); if( ddrval != DD_OK ) return FALSE; //取得全屏獨(dú)占模式 ddrval = lpDD->SetCooperativeLevel( hWndMain, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ); if( ddrval != DD_OK ) return FALSE; //設(shè)置顯示器顯示模式為當(dāng)前屏幕的分辯率,16位增強(qiáng)顯示模式 ddrval = lpDD->SetDisplayMode(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), COLORS); if( ddrval != DD_OK ) return FALSE; //填充換頁鏈結(jié)構(gòu) ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; //后臺(tái)緩沖區(qū)數(shù)量為2 ddsd.dwBackBufferCount = 2; //創(chuàng)建換頁鏈,包括了主頁面及其后臺(tái)緩沖區(qū) ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ); if( ddrval != DD_OK ) return FALSE; //獲得指向后臺(tái)緩沖區(qū)的頁面指針 ddscaps.dwCaps = DDSCAPS_BACKBUFFER; ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack); if( ddrval != DD_OK ) return FALSE; //創(chuàng)建離屏頁面 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; //調(diào)用頁面初始化函數(shù) if( !InitSurfaces() ) return FALSE; return TRUE; } //****************************************************************** //函數(shù):WinMain() //功能:應(yīng)用程序入口 //****************************************************************** 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); //調(diào)用截屏函數(shù) hbm=(HBITMAP)GetScreen(&rect); //初始化主窗口 if (!InitWindow( hInstance, nCmdShow)) return FALSE; //初始化DirectDraw環(huán)境 if (!InitDDraw()) { MessageBox(hWndMain, "初始化DirectDraw過程中出錯(cuò)!", "Error", MB_OK); FreeObjects(); DestroyWindow(hWndMain); return FALSE; } //進(jìn)入消息循環(huán) 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; } //****************************************************************** //函數(shù):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; //清屏后臺(tái)緩沖區(qū) DDBLTFX ddBltFx; ddBltFx.dwSize = sizeof(DDBLTFX); ddBltFx.dwFillColor = DDColorMatch(lpDDSBack, RGB(0,0,0)); lpDDSBack->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddBltFx); //調(diào)用灰度的實(shí)現(xiàn)函數(shù) RECT srect, drect; MakeRect(&srect, 0, 0, rect.right ,rect.bottom); MakeRect(&drect, 0, 0, rect.right , rect.bottom); //將背景圖象Blit到后臺(tái)緩沖區(qū) lpDDSBack->Blt(&drect, lpDDSPic1, &srect, DDBLT_WAIT, NULL); // 換頁 while( 1 ) { ddrval = lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );//調(diào)用換頁函數(shù) if( ddrval == DD_OK )//成功則退出while循環(huán) break; else if( ddrval == DDERR_SURFACELOST )//如果頁面丟失,則恢復(fù)頁面,再繼續(xù)while循環(huán) 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; }
相關(guān)文章
C語言每日練習(xí)之統(tǒng)計(jì)文本單詞數(shù)及高頻詞
本文文大家準(zhǔn)備了個(gè)C語言練習(xí)題:統(tǒng)計(jì)單詞數(shù)并找出頻率最高的單詞,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語言有一定幫助,感興趣的可以了解一下2022-05-05一文詳解C++中動(dòng)態(tài)內(nèi)存管理
這篇文章主要介紹了一文詳解C++中動(dòng)態(tài)內(nèi)存管理,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)孩子沒需要的朋友可以才可以參考一下2022-07-07Cocos2dx實(shí)現(xiàn)數(shù)字跳動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Cocos2dx實(shí)現(xiàn)數(shù)字跳動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09C語言驅(qū)動(dòng)開發(fā)內(nèi)核特征碼掃描PE代碼段
這篇文章主要為大家介紹了C語言驅(qū)動(dòng)開發(fā)內(nèi)核特征碼掃描PE代碼段,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10C語言二維數(shù)組運(yùn)用實(shí)現(xiàn)掃雷游戲
這篇文章主要為大家詳細(xì)介紹了C語言二維數(shù)組運(yùn)用實(shí)現(xiàn)掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06C語言結(jié)構(gòu)體(struct)常見使用方法(細(xì)節(jié)問題)
這篇文章主要介紹了C語言結(jié)構(gòu)體(struct)常見使用方法(細(xì)節(jié)問題),需要的朋友可以參考下2017-03-03C語言 解決不用+、-、×、÷數(shù)字運(yùn)算符做加法的實(shí)現(xiàn)方法
本篇文章是對(duì)在C語言中解決不用+、-、×、÷數(shù)字運(yùn)算符做加法的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05