VC++基于Dx实现的截图程序示例代码
本文所述的程序示例为VC++图象特效的截图示例,需要DirectX3.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" #defineTITLE"截图示例"//窗口标题 #defineCLASSNAME"GetScreen"//窗口类名 #defineCOLORS16 HINSTANCEhInst;//应用程序实例句柄 HWNDhWndMain;//主窗口句柄 LPDIRECTDRAWlpDD;//DirectDraw对象 LPDIRECTDRAWSURFACElpDDSPrimary;//主页面 LPDIRECTDRAWSURFACElpDDSBack;//后台缓冲区 LPDIRECTDRAWSURFACElpDDSPic1;//离屏页面1 LPDIRECTDRAWPALETTElpDDPal;//调色板 BOOLbActive;//应用程序是否活跃? HBITMAPhbm; RECTrect; //函数声明 voidFreeObjects(void); BOOLInitDDraw(void); BOOLInitSurfaces(void); voidUpdateFrame(void); voidMakeRect(RECT*rect,longleft,longtop,longright,longbottom); /////////////////////////////////////////////// //截图函数,是本程序的关键 //函数名:GetScreen //参数:指向屏幕矩形的指针 //返值:Bitmap设备 ////////////////////////////////////////////// HANDLEGetScreen(LPRECTlpRect) { //定义屏幕的DC和内存DC HDChScrDC,hMemDC; //定义Bitmap设备 HANDLEhBitmap,hOldBitmap; //定义屏幕坐标变量 unsignedintnX,nY,nX2,nY2; unsignedintnWidth,nHeight; //定义屏幕分辩率变量 unsignedintxScrn,yScrn; //确保屏幕矩形不为空 if(IsRectEmpty(lpRect)) returnNULL; //创建屏幕的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); returnhBitmap; } //******************************************************************* //函数:FreeObject //功能:释放所有DirectDraw对象 //******************************************************************* voidFreeObjects(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 //功能:页面丢失后,恢复页面内存 //******************************************************************* HRESULTRestoreAll(void) { HRESULTddrval; //恢复主页面,这也将恢复换页链中的所有页面 ddrval=lpDDSPrimary->Restore(); //恢复离屏页面 ddrval=lpDDSPic1->Restore(); //重新绘制页面图象 InitSurfaces(); returnddrval; } //******************************************************************* //函数:WindowProc //功能:主窗口的消息处理过程 //******************************************************************* LRESULTCALLBACKWinProc(HWNDhWnd,UINTmessage, WPARAMwParam,LPARAMlParam) { switch(message) { caseWM_SETCURSOR: SetCursor(LoadCursor(NULL,IDC_ARROW)); returnTRUE; caseWM_ACTIVATEAPP://应用程序激活消息 bActive=wParam; break; caseWM_KEYDOWN://击键消息 switch(wParam) { caseVK_ESCAPE: PostMessage(hWnd,WM_CLOSE,0,0); break; } break; caseWM_DESTROY://销毁窗口消息 FreeObjects(); PostQuitMessage(0); break; } //调用缺省的过程处理过程 returnDefWindowProc(hWnd,message,wParam,lParam); } //****************************************************************** //函数:InitWindow() //功能:创建主窗口。 //****************************************************************** BOOLInitWindow(HINSTANCEhInstance,intnCmdShow) { WNDCLASSwc;//窗口类结构 //填充窗口类结构 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) returnFALSE; //显示并更新窗口 ShowWindow(hWndMain,nCmdShow); returnTRUE; } //****************************************************************** //函数:InitDDraw() //功能:初始化DirectDraw环境,创建换页链(主页面,一个后台缓冲区) //以及创建一个定时器。 //****************************************************************** BOOLInitDDraw(void) { DDSURFACEDESCddsd; DDSCAPSddscaps; HRESULTddrval; //创建DirectDraw对象 ddrval=DirectDrawCreate(NULL,&lpDD,NULL); if(ddrval!=DD_OK) returnFALSE; //取得全屏独占模式 ddrval=lpDD->SetCooperativeLevel(hWndMain,DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN); if(ddrval!=DD_OK) returnFALSE; //设置显示器显示模式为当前屏幕的分辩率,16位增强显示模式 ddrval=lpDD->SetDisplayMode(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),COLORS); if(ddrval!=DD_OK) returnFALSE; //填充换页链结构 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) returnFALSE; //获得指向后台缓冲区的页面指针 ddscaps.dwCaps=DDSCAPS_BACKBUFFER; ddrval=lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBack); if(ddrval!=DD_OK) returnFALSE; //创建离屏页面 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) returnFALSE; //调用页面初始化函数 if(!InitSurfaces()) returnFALSE; returnTRUE; } //****************************************************************** //函数:WinMain() //功能:应用程序入口 //****************************************************************** intPASCALWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPSTRlpCmdLine,intnCmdShow) { MSGmsg; 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)) returnFALSE; //初始化DirectDraw环境 if(!InitDDraw()) { MessageBox(hWndMain,"初始化DirectDraw过程中出错!","Error",MB_OK); FreeObjects(); DestroyWindow(hWndMain); returnFALSE; } //进入消息循环 while(1) { if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) { if(!GetMessage(&msg,NULL,0,0)) returnmsg.wParam; TranslateMessage(&msg); DispatchMessage(&msg); } elseif(bActive) { UpdateFrame(); } elseWaitMessage(); } returnmsg.wParam; } //****************************************************************** //函数:InitSurfaces() //功能:初始化页面图象 //****************************************************************** BOOLInitSurfaces(void) { if(hbm==NULL) returnFALSE; DDCopyBitmap(lpDDSPic1,hbm,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)); returnTRUE; } //更新屏幕 voidUpdateFrame(void) { HRESULTddrval; //清屏后台缓冲区 DDBLTFXddBltFx; ddBltFx.dwSize=sizeof(DDBLTFX); ddBltFx.dwFillColor=DDColorMatch(lpDDSBack,RGB(0,0,0)); lpDDSBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddBltFx); //调用灰度的实现函数 RECTsrect,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; elseif(ddrval==DDERR_SURFACELOST)//如果页面丢失,则恢复页面,再继续while循环 RestoreAll(); else break; } } voidMakeRect(RECT*rect,longleft,longtop,longright,longbottom) { rect->left=left; rect->top=top; rect->right=right; rect->bottom=bottom; }