首页 > 编程 > C++ > 正文

VC++基于Dx实现的截图程序示例代码

2020-01-26 15:26:37
字体:
来源:转载
供稿:网友

本文所述的程序示例为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 16HINSTANCE hInst; //应用程序实例句柄HWND hWndMain; //主窗口句柄LPDIRECTDRAW      lpDD;      // DirectDraw对象LPDIRECTDRAWSURFACE   lpDDSPrimary;  // 主页面LPDIRECTDRAWSURFACE   lpDDSBack;   // 后台缓冲区LPDIRECTDRAWSURFACE   lpDDSPic1;   // 离屏页面1LPDIRECTDRAWPALETTE   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;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表