VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 573|回复: 4

[交流] 控制台截屏例程

[复制链接]
75_avatar_middle
最佳答案
0 
在线会员 发表于 2019-4-3 12:27:56 | 显示全部楼层 |阅读模式
截屏代码网上有很多,不过,这里代码很简单,看一眼,浪费不了多少时间。功能:
1、直接按F3截全屏,
2、按住Shift键,同时按鼠标左键拖动选择要截屏的区域,松开即选定。所选区域坐标,在控制台窗口标题有显示。
     选定后可松开shift, 并可移动窗口不遮盖选择区域。然后按F2截取到文件。文件保存在程序所在目录,文件名为截取的日期时间.bmp
3.  新建控制台程序,代码复制粘贴,编译即可。有空在里面淘金吧。无废码。

  1. #include "stdafx.h"
  2. #include <iostream>
  3. #include <iomanip>
  4. #include <fstream>
  5. #include <Windows.h>
  6. using namespace std;
  7. namespace cutscreen {
  8.         POINT   currpt = { 0,0 }, lastpt = { 0,0 };
  9.         HPEN    hpen  = NULL;
  10.         BOOL    boSel = FALSE;
  11.         HWND    hWndDesktop;
  12.         HDC     hdcScreen = NULL;
  13.         HDC     hdcMem = NULL;
  14.         HBITMAP hbitmap;
  15.         HBITMAP hOldBitmap;
  16.         DWORD   lastTick;
  17.         BYTE*   pBitmapData=NULL;
  18.         BITMAPINFO *pbmi;
  19.         int nMaxXScreen, nMaxYScreen;
  20.         void Prepare();
  21.         void Save(BOOL boFullScreen);
  22.         void Quit();
  23.         void GetInput();
  24.         void Adjust();
  25. };
  26. using namespace cutscreen;
  27. int main()
  28. {
  29.         hWndDesktop = GetDesktopWindow();
  30.         SetConsoleTitle(L"截取屏幕");
  31.         wcout.imbue(locale("chs"));
  32.         wcout << L"按住Shift和鼠标左键,拖动鼠标选择区域" << endl;
  33.         wcout << L"选择好按F2自动截取到文件。" << endl;
  34.         wcout << L"无需选择按F3自动全屏。" << endl;
  35.         wcout << L"按ESC退出" << endl;
  36.         Prepare();
  37.         while(1){
  38.                 short key = GetAsyncKeyState(VK_ESCAPE);
  39.                 if (key & 0x8000) break;
  40.                 GetInput();
  41.                 SleepEx(1, TRUE);
  42.         }
  43.         Quit();
  44.     return 0;
  45. }
  46. void cutscreen::GetInput() {
  47.         POINT pt;
  48.         short key, key1;
  49.         GetCursorPos(&pt);
  50.         key  = GetAsyncKeyState(VK_LBUTTON);
  51.         key1 = GetAsyncKeyState(VK_SHIFT);
  52.         if (key1 & 0x8000) {
  53.                         if((key & 0x8000)) {
  54.                                 if (!boSel) {
  55.                                         lastpt = pt;
  56.                                         currpt = pt;
  57.                                         boSel = TRUE;
  58.                                 }
  59.                                 //擦先前划线
  60.                                 HDC hdc = GetDC(hWndDesktop);
  61.                                 SetROP2(hdc, R2_NOTXORPEN);
  62.                                 SelectObject(hdc, GetStockObject(NULL_BRUSH));
  63.                                 SelectObject(hdc, hpen);
  64.                                 Rectangle(hdc, lastpt.x, lastpt.y, currpt.x, currpt.y);
  65.                                 ReleaseDC(hWndDesktop, hdc);
  66.                                 currpt = pt;
  67.                         }
  68.                         else
  69.                         {
  70.                                 if (boSel) {
  71.                                    currpt = pt;
  72.                                    Adjust();
  73.                                 }
  74.                                 boSel = FALSE;
  75.                         }
  76.         }       
  77.         //绘选择框
  78.         HDC hdc = GetDC(hWndDesktop);
  79.         SelectObject(hdc, GetStockObject(NULL_BRUSH));
  80.         SelectObject(hdc, hpen);
  81.         Rectangle(hdc, lastpt.x, lastpt.y, currpt.x, currpt.y);
  82.         ReleaseDC(hWndDesktop,hdc);
  83.         //标题显示选择区域
  84.         TCHAR szMsg[MAX_PATH];
  85.         wsprintf(szMsg, L"截取屏幕(%d,%d)-(%d,%d)", lastpt.x, lastpt.y, currpt.x, currpt.y);
  86.         SetConsoleTitle(szMsg);
  87.         //截取选择区域
  88.         key = GetAsyncKeyState(VK_F2);
  89.         if (key & 0x8000) {
  90.                 DWORD thisTick = GetTickCount();
  91.                 if (thisTick - lastTick > 1000) {
  92.                         Save(FALSE);
  93.                         lastTick = GetTickCount();
  94.                 }
  95.         }
  96.         //截取全屏
  97.         key = GetAsyncKeyState(VK_F3);
  98.         if (key & 0x8000) {
  99.                 DWORD thisTick = GetTickCount();
  100.                 if (thisTick - lastTick > 1000) {
  101.                         Save(TRUE);
  102.                         lastTick = GetTickCount();
  103.                 }
  104.         }
  105. }
  106. void cutscreen::Prepare() {
  107.         hpen = CreatePen(PS_SOLID, 1, RGB(255,0, 0));
  108.         lastTick = GetTickCount();
  109.         //不能静态分配,因为32位biCompression==BI_BITFIELDS时bmiColors有3个DWORD颜色掩码
  110.         //不分配多余空间会导致内存分配后,已有数据错位混乱
  111.         pbmi =(BITMAPINFO*) new BYTE[sizeof(BITMAPINFO) + 3 * sizeof(DWORD)];
  112.         //建立桌面兼容设备
  113.         hdcScreen = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  114.         hdcMem = CreateCompatibleDC(hdcScreen);
  115.         //只能建DDB兼容位图,不能用DIB位图
  116.         nMaxXScreen = GetDeviceCaps(hdcScreen, HORZRES);
  117.         nMaxYScreen = GetDeviceCaps(hdcScreen, VERTRES);
  118.         hbitmap = CreateCompatibleBitmap(hdcScreen, nMaxXScreen, nMaxYScreen);
  119.         hOldBitmap = (HBITMAP)SelectObject(hdcMem, hbitmap);
  120. }
  121. //调整选择区域为正矩形
  122. void cutscreen::Adjust() {
  123.         int t;
  124.         if (currpt.x < lastpt.x)
  125.         {
  126.                 t = currpt.x;
  127.                 currpt.x = lastpt.x;
  128.                 lastpt.x = t;
  129.         }
  130.         if (currpt.y < lastpt.y)
  131.         {
  132.                 t = currpt.y;
  133.                 currpt.y = lastpt.y;
  134.                 lastpt.y = t;
  135.         }
  136. }
  137. void cutscreen::Save(BOOL boFullScreen) {
  138.         int x, y, w, h;
  139.         if (boFullScreen) {
  140.                 x = 0;
  141.                 y = 0;
  142.                 w = nMaxXScreen,
  143.                 h = nMaxYScreen;
  144.         }
  145.         else {
  146.                 x = lastpt.x;
  147.                 y = lastpt.y;
  148.                 w = currpt.x - lastpt.x;
  149.                 h = currpt.y - lastpt.y;
  150.         }
  151.         if (w <= 0 || h <= 0) return;
  152.         //复制全屏幕
  153.         DWORD dwRop = SRCCOPY | CAPTUREBLT;
  154.         BOOL bRet = BitBlt(hdcMem, 0, 0, w, h, hdcScreen,0,0, dwRop);
  155.         //SetStretchBltMode(memdc, HALFTONE);
  156.         //StretchBlt(memdc, 0, 0, w, h, hdcscreen, x, y, w, h, SRCCOPY | CAPTUREBLT);
  157.         //获取内存位图数据的大小
  158.         ZeroMemory(pbmi, sizeof(BITMAPINFO));
  159.         pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  160.         int ret = GetDIBits(hdcMem, hbitmap, 0, nMaxYScreen, NULL, (BITMAPINFO*)pbmi, DIB_RGB_COLORS);
  161.         if (ret < 1) {
  162.                 wcout << L"获取内存数据大小不成功!" << endl;
  163.                 return;
  164.         }
  165.         //分配内存位图数据的大小
  166.         pBitmapData = new BYTE[pbmi->bmiHeader.biSizeImage];
  167.         //读取内存位图数据
  168.         ret = GetDIBits(hdcMem, hbitmap, 0, nMaxYScreen,(LPVOID)pBitmapData, (BITMAPINFO*)pbmi, DIB_RGB_COLORS);
  169.         if (ret < 1) {
  170.                 wcout << L"无法读取内存保存数据!" << endl;
  171.                 return;
  172.         }
  173.         //按时间产生文件名
  174.         SYSTEMTIME st;
  175.         GetLocalTime(&st);
  176.         TCHAR FileName[MAX_PATH];
  177.         wsprintf(FileName, L"scr%.4d%.2d%.2d%.2d%.2d%.2d.bmp",
  178.                 st.wYear,
  179.                 st.wMonth,
  180.                 st.wDay,
  181.                 st.wHour,
  182.                 st.wMinute,
  183.                 st.wSecond
  184.         );
  185.         wstring sfilename = FileName;
  186.         wcout << L"输出文件:" << sfilename.c_str()<<L"输出区域 ("<< x <<L","<<y <<L"-"<<(x+w)<<","<<(y+h)<<L")"<< endl;

  187. #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)

  188.         //位图存盘计算对齐位图宽度,WIDTHBYTES参数=原宽度*8
  189.         int newWidth = WIDTHBYTES(w * 8);
  190.         int nPitch = newWidth * 3;
  191.         //填位图文件头
  192.         BITMAPFILEHEADER bfh;
  193.         ZeroMemory(&bfh, sizeof(bfh));
  194.         bfh.bfType = (WORD)(*(WORD*)&"BM");
  195.         bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  196.         bfh.bfSize = bfh.bfOffBits + nPitch * h;
  197.     //填位图信息头,-h,数据颠倒存放,画图看才会是正的
  198.         BITMAPINFOHEADER bih;
  199.         ZeroMemory(&bih, sizeof(bih));
  200.         bih.biBitCount = 24;
  201.         bih.biHeight = -h;
  202.         bih.biWidth  = newWidth;
  203.         bih.biPlanes = 1;
  204.         bih.biCompression = BI_RGB;
  205.         bih.biSize = sizeof(BITMAPINFOHEADER);
  206.         //大小必须是按对齐的大小
  207.         bih.biSizeImage = nPitch * h;
  208.         //写位图文件
  209.         ofstream ofile(sfilename.c_str(), ios::out | ios::binary);
  210.         if (!ofile) {
  211.                 wcout << sfilename.c_str() << L" 不能写!错误码=" << GetLastError() << endl;
  212.                 return;
  213.         }
  214.         ofile.write((char*)&bfh, sizeof(BITMAPFILEHEADER));
  215.         ofile.write((char*)&bih, sizeof(BITMAPINFOHEADER));
  216.         int srcBytesPixel = pbmi->bmiHeader.biBitCount/8;
  217.         int srcPitch      = pbmi->bmiHeader.biWidth*srcBytesPixel;
  218.         //注意屏幕上位图坐标是正的,内存数据是颠倒地,
  219.         for (int i = nMaxYScreen - y;i>nMaxYScreen -(y + h);i--) {
  220.                 for (int j = x;j < x+newWidth;j++) {
  221.                         RGBTRIPLE rgb;
  222.                         rgb.rgbtBlue  = pBitmapData[i*srcPitch + j*srcBytesPixel + 0];
  223.                         rgb.rgbtGreen = pBitmapData[i*srcPitch + j*srcBytesPixel + 1];
  224.                         rgb.rgbtRed   = pBitmapData[i*srcPitch + j*srcBytesPixel + 2];
  225.                         ofile.write((char*)&rgb, 3);
  226.                 }
  227.         }
  228.         ofile.close();
  229.         if (pBitmapData) delete[]pBitmapData;
  230.         wcout << L"done!" << endl;
  231. }
  232. void cutscreen::Quit() {
  233.         DeleteObject(hpen);
  234.         if(pbmi) delete[]pbmi;
  235.         SelectObject(hdcMem, hOldBitmap);
  236.         DeleteDC(hdcMem);
  237.         DeleteDC(hdcScreen);
  238.         DeleteObject(hbitmap);
  239. }
复制代码


控制台截屏例程


   

评分

参与人数 3驿站币 +5 热心值 +5 收起 理由
16_avatar_small firefox + 1 + 1 感谢分享!
58_avatar_small thzzl + 2 + 2 很给力!
77_avatar_small Health + 2 + 2 感谢分享!

查看全部评分





上一篇:MFC六大核心机制
下一篇:Visual Studio项目清理(批处理)
77_avatar_middle
最佳答案
31 
online_vip 发表于 2019-4-3 12:48:05 | 显示全部楼层
楼主原创吗?不错啊,摘录点代码,以后用的上
58_avatar_middle
最佳答案
43 
online_vip 发表于 2019-4-3 13:00:22 | 显示全部楼层
收藏,稍后好好学学
16_avatar_middle
最佳答案
0 
在线会员 发表于 2019-4-3 13:24:59 | 显示全部楼层
谢谢楼主分享
16_avatar_middle
最佳答案
0 
在线会员 发表于 2019-4-5 21:13:01 | 显示全部楼层
写的不错收藏了
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )|网站地图wx_jqr

GMT+8, 2020-10-25 15:49

Powered by CcTry.CoM

© 2009-2020 cctry.com

快速回复 返回顶部 返回列表