基于visual c++之windows核心编程代码分析(11)实现屏幕截取

               

 

我们在进行Windows编程的时候,经常需要进行屏幕截取,我们来实现截取屏幕,不依赖MFC来实现屏幕截取。请见代码实现与注释讲解

 

 

 

/* 头文件 */#include <windows.h>/* 常量定义 */#define PALVERSION 0x300#define CAP_SHOW_MODE_STRTCH 1#define CAP_SHOW_MODE_NOSTRTCH 0/* 全局变量 */HBITMAP ghBitmap = NULL;RECT rectShow;// 修改这里截取不同的窗口,如果为NULL,则截取屏幕LPSTR szCaptureWindowName = "Windows 任务管理器";/* 函数申明 */LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);HBITMAP ScreenCapture(LPSTR filename ,WORD BitCount,LPRECT lpRect);VOID DoPaint(HWND hWnd, DWORD dwMode);/************************************** DWORD WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)* 功能 截屏,保存为文件,并显示在窗口上***************************************/INT WINAPI WinMain(HINSTANCE hinstance,      HINSTANCE hPrevInstance,      LPSTR lpCmdLine,      int nCmdShow){ WNDCLASSEX wcx; HWND hwnd; MSG msg; WORD wport = 80; BOOL fGotMessage; HWND hwndCap = NULL// 截取全屏幕还是窗口 if(szCaptureWindowName != NULL) {  hwndCap = FindWindow(NULL,"Windows 任务管理器");  // 获取窗口的RECT,可自行修改,获取屏幕中的任意区域  if(!GetWindowRect(hwndCap,&rectShow))  {   MessageBox(NULL,"Can not find window to capture", "erroe",MB_OK);   return 0;  } } // 注册窗口类,并创建窗口,用于显示截取的位图 wcx.cbSize = sizeof(wcx); wcx.style = CS_HREDRAW | CS_VREDRAW; wcx.lpfnWndProc = MainWndProc; wcx.cbClsExtra = 0; wcx.cbWndExtra = 0; wcx.hInstance = hinstance; wcx.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION)); wcx.hCursor = LoadCursor(NULL, IDC_ARROW); wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wcx.lpszMenuName = NULL; wcx.lpszClassName = "MainWClass"; wcx.hIconSm = NULLif( !RegisterClassEx(&wcx))  return 1// 创建窗口 hwnd = CreateWindow(  "MainWClass",  "CAP",  WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |  WS_MAXIMIZE | WS_POPUPWINDOW,  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,  (HWND) NULL, (HMENU) NULL, hinstance, (LPVOID) NULL); if (!hwnd)  return 1// 截取屏幕,可根据需要设置不同的参数,这里只演示截取特定窗口。 ghBitmap = ScreenCapture("taskmgr.bmp" ,32, &rectShow); // 显示 ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1) {  TranslateMessage(&msg);  DispatchMessage(&msg); } return msg.wParam; UNREFERENCED_PARAMETER(lpCmdLine);}LRESULT CALLBACK MainWndProc(        HWND hwnd,        UINT uMsg,        WPARAM wParam,        LPARAM lParam)switch (uMsg) { case WM_PAINT:  // 显示截取的屏幕  DoPaint(hwnd,CAP_SHOW_MODE_STRTCH);  breakcase WM_DESTROY:  // 创建的BITMAP对象需要删除,以释放资源  DeleteObject(ghBitmap);  ExitProcess(0);  breakdefault:  break; } return DefWindowProc(hwnd, uMsg, wParam, lParam);}/************************************** VOID DoPaint(HWND hWnd, DWORD dwMode)* 功能 将位图(全局变量ghBitmap)显示在界面上** 参数 HWND hWnd,用于显示位图的窗口* DWORD dwMode,模式,是否拉申** 无返回值**************************************/VOID DoPaint(HWND hWnd, DWORD dwMode){ PAINTSTRUCT ps; RECT rect; HDC hdcMem; BITMAP bm; // BeginPaint HDC hDC = BeginPaint(hWnd, &ps); // 获取窗口的Client区域,用于显示位图 GetClientRect(hWnd, &rect); // 设置拉申模式 SetStretchBltMode(hDC, HALFTONE); // 将BITMAP对象选择入内存DC hdcMem = CreateCompatibleDC(hDC); SelectObject(hdcMem, ghBitmap); if (ghBitmap) {  // 获取DIB属性  if (GetObject(ghBitmap, sizeof(BITMAP), &bm))  {   // 判断参数示:是否根据显示窗口大小拉申位图   // 采用不同的方面将内存DC StretchBl t至窗口Client区域DC   if(dwMode == CAP_SHOW_MODE_STRTCH)   {    StretchBlt(hDC, 0, 0, rect.right, rect.bottom,     hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);   }   else   {    // 不拉伸,计算显示的位置,将其显示在Client的中央    INT ixStart = (rect.right - rect.left - bm.bmWidth)/2;    INT iyStart = (rect.bottom - rect.top - bm.bmHeight)/2;    ixStart = ixStart < 0 ? 0 : ixStart;    iyStart = iyStart < 0 ? 0 : iyStart;    BitBlt(hDC, 0, 0, rect.right, rect.bottom,     hdcMem,-ixStart,-iyStart, SRCCOPY);   }   DeleteDC(hdcMem);  } } // 如果没有位图,则使用Brush填充 else {  PatBlt(hDC, 0, 0, rect.right, rect.bottom, BLACKNESS); } // EndPaint EndPaint(hWnd, &ps);}/************************************** BITMAP ScreenCapture(LPSTR filename ,WORD BitCount,LPRECT lpRect);* 功能 截取指定区域的屏幕,并保存为文件** 参数 LPSTR filename 保存位图文件的文件路径,如果为NULL,则不保存*  WORD BitCount Bit深度,用于表示一个像素点所使用的数据长度*  LPRECT lpRect 所需截取的屏幕区域,如果为NULL,则获取全屏幕** 返回 HBITMAP 所截取的位图对象**************************************/HBITMAP ScreenCapture(LPSTR filename ,WORD BitCount,LPRECT lpRect){ HBITMAP hBitmap; // 显示器屏幕DC HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL); HDC hmemDC = CreateCompatibleDC(hScreenDC); // 显示器屏幕的宽和高 int ScreenWidth = GetDeviceCaps(hScreenDC, HORZRES); int ScreenHeight = GetDeviceCaps(hScreenDC, VERTRES); // 旧的BITMAP,用于与所需截取的位置交换 HBITMAP hOldBM; // 保存位图数据 PVOID lpvpxldata; // 截屏获取的长宽及起点 INT ixStart; INT iyStart; INT iX; INT iY; // 位图数据大小 DWORD dwBitmapArraySize; // 几个大小 DWORD nBitsOffset; DWORD lImageSize ; DWORD lFileSize ; // 位图信息头 BITMAPINFO bmInfo; // 位图文件头 BITMAPFILEHEADER bmFileHeader; // 写文件用 HANDLE hbmfile; DWORD dwWritten; // 如果LPRECT 为NULL 截取整个屏幕 if(lpRect == NULL) {  ixStart = iyStart = 0;  iX = ScreenWidth;  iY =ScreenHeight; } else {  ixStart = lpRect->left;  iyStart = lpRect->top;  iX = lpRect->right - lpRect->left;  iY = lpRect->bottom - lpRect->top; } // 创建BTIMAP hBitmap = CreateCompatibleBitmap(hScreenDC, iX, iY); // 将BITMAP选择入内存DC。 hOldBM = (HBITMAP)SelectObject(hmemDC, hBitmap); // BitBlt屏幕DC到内存DC,根据所需截取的获取设置参数 BitBlt(hmemDC, 0, 0, iX, iY, hScreenDC, ixStart, iyStart, SRCCOPY); // 将旧的BITMAP对象选择回内存DC,返回值为被替换的对象,既所截取的位图 hBitmap = (HBITMAP)SelectObject(hmemDC, hOldBM); if(filename == NULL) {  DeleteDC( hScreenDC);  DeleteDC(hmemDC);  return hBitmap; } // 为位图数据申请内存空间 dwBitmapArraySize = ((((iX*32) + 31) & ~31)>> 3)* iY; lpvpxldata = HeapAlloc(GetProcessHeap(),HEAP_NO_SERIALIZE,dwBitmapArraySize); ZeroMemory(lpvpxldata,dwBitmapArraySize); // 添充 BITMAPINFO 结构 ZeroMemory(&bmInfo,sizeof(BITMAPINFO)); bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmInfo.bmiHeader.biWidth = iX; bmInfo.bmiHeader.biHeight = iY; bmInfo.bmiHeader.biPlanes = 1; bmInfo.bmiHeader.biBitCount = BitCount; bmInfo.bmiHeader.biCompression = BI_RGB; // 添充 BITMAPFILEHEADER 结构 ZeroMemory(&bmFileHeader,sizeof(BITMAPFILEHEADER)); nBitsOffset = sizeof(BITMAPFILEHEADER) + bmInfo.bmiHeader.biSize; lImageSize =  ((((bmInfo.bmiHeader.biWidth * bmInfo.bmiHeader.biBitCount) + 31) & ~31)>> 3)  * bmInfo.bmiHeader.biHeight; lFileSize = nBitsOffset + lImageSize; bmFileHeader.bfType = 'B'+('M'<<8); bmFileHeader.bfSize = lFileSize; bmFileHeader.bfOffBits = nBitsOffset; // 获取DIB用于写入到文件 GetDIBits(hmemDC, hBitmap, 0, bmInfo.bmiHeader.biHeight,  lpvpxldata, &bmInfo, DIB_RGB_COLORS); // 写文件 hbmfile = CreateFile(filename,  GENERIC_WRITE,  FILE_SHARE_WRITE,  NULL,  CREATE_ALWAYS,  FILE_ATTRIBUTE_NORMAL,  NULL); if(hbmfile == INVALID_HANDLE_VALUE) {  MessageBox(NULL,"create file error","error",MB_OK); } WriteFile(hbmfile,&bmFileHeader,sizeof(BITMAPFILEHEADER),&dwWritten,NULL); WriteFile(hbmfile,&bmInfo,sizeof(BITMAPINFO),&dwWritten,NULL); WriteFile(hbmfile,lpvpxldata,lImageSize,&dwWritten,NULL); CloseHandle(hbmfile); // 释放内存,清除不同的DC。 // 这里没有删除BITMAP对象,需在显示完成后删除 HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,lpvpxldata); ReleaseDC(0, hScreenDC); DeleteDC(hmemDC);  return hBitmap;}


 

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值