【小沐学C++】C++实现截图截屏功能汇总

在这里插入图片描述

《内卷篇》

第一幕:
离开学校的那一天,一群小伙伴在KTV里,感怀过去,憧憬未来。心中有火,眼中有光,藏着赤忱热烈和星辰大海,他们是一群发光的少年。
歌云:
Are you going to Scarborough Fair?
Parsley, sage, rosemary and thyme.
Remember me to one who lives there.
She once was a true love of mine.
Tell her to make me a cambric shirt.
Parsley, sage, rosemary and thyme.

第二幕:
工作了许多年,戈戈不分昼夜地加班,饥一顿饱一顿。最近经常在半夜胸口隐隐作痛,难道快要结束了?
诗云:
人生实苦需修炼,
是你是你就是你。
只想休闲不动脑,
是他是他就是他。
花卷蛋卷羊肉卷,
外卷内卷拼命卷。
焦虑紧张鸭梨大,
解救之道非躺平。
群鱼,相濡以沫,
不如相忘于江湖。
众人,誉尧非桀,
不如两忘化其道。

第三幕:
昨天,终于迎来了今年的第一场雪。虽然雪下得不大,但大家的心都是属于冰冰的。狄狄在楼顶上忙乎了一上午,堆了一个小雪人。找来水彩笔,涂成了呆呆萌萌的“冰墩墩”。最后插上几支刚发芽的柳枝。凝视着“冰墩墩”,良久,狄狄望向远方,轻叹一声。
诗云:
遥知兄弟登高处,
遍插茱萸少一人。

幕落。

本节内容如下:

  • 1、截图工具
    • 1.1 键盘截图(PrtScn键)
    • 1.2 win10自带截图工具(Win+Shift+S)
    • 1.3 Win7/Win10自带截图工具2
    • 1.4 ffmpeg
    • 1.5 ScreenToGif
    • 1.6 Google Chrome
    • 1.7 Microsoft Edge
    • 1.8 Open Broadcaster Software(OBS)
    • 1.9 PicPick
    • 1.10 Snipaste
    • 1.11 Camtasia Studio(喀秋莎软件)
    • 1.12 微信
    • 1.13 Nvidia GeForce Experience
    • 1.14 WPS
    • 1.15 飞秋
  • 2、C++、GDI
    • 2.1 微软官方例子
    • 2.2 C++、GDI、CImage
    • 2.3 C++、GDI、系统剪切板
    • 2.4 C++、GDI、GDI+
    • 2.5 C++、GDI、MFC
    • 2.6 C++、GDI、PrintWindow
  • 3、C++、OpenGL
  • 4、C++、OpenCV
  • 5、C++、QT
  • 6、C++、DirectX 9
  • 7、C++、DXGI
  • 结语

“有人来时,入江湖,意气风发。去时,出江湖,问心无愧。”

1、截图工具

1.1 键盘截图(PrtScn键)

如何使用Microsoft Windows操作系统中的Print Screen(打印屏幕)键
(1)Print Screen键
按下之后,截取整个屏幕的画面到剪切板里。可以复制到其他软件里,比如系统的画图工具,Office Word等。

(2)Alt+Print Screen组合键
按下之后,截取当前活动窗口的画面到剪切板里。
【小沐学C++】C++实现截图截屏功能汇总_第1张图片

1.2 win10自带截图工具(Win+Shift+S)

【小沐学C++】C++实现截图截屏功能汇总_第2张图片
【小沐学C++】C++实现截图截屏功能汇总_第3张图片

小沐温馨小提示:
  • (1)快捷键"Win+Shift+S",能直接开始截图。按下该组合键之后,使用鼠标在屏幕上画出想要截取的矩形区域,自动保存到系统剪切板里。

在这里插入图片描述

  • (2)快捷键"Win+W",右下角会弹出屏幕草图工具栏,也可以作为间接截图使用,见下图所示:

【小沐学C++】C++实现截图截屏功能汇总_第4张图片

1.3 Win7/Win10自带截图工具2

【小沐学C++】C++实现截图截屏功能汇总_第5张图片
【小沐学C++】C++实现截图截屏功能汇总_第6张图片
【小沐学C++】C++实现截图截屏功能汇总_第7张图片

1.4 ffmpeg

ffmpeg -i “输入视频” -fflags nobuffer -t 60 -ss 0 “输出地址”
说明:代表截取输入视频从0秒到60秒的片段,保存到输出地址。
-ss n : 起始时间为第n秒
-t n : 总共截取的片段时长为n秒

运行后会生成截图: out1.jpg out2.jpg out3.jpg …

ffmpeg -i fight.mp4 -r 1 -t 200 -ss 1 -f image2 out%d.jpg

1.5 ScreenToGif

ScreenToGif官网网址
ScreenToGif源码网址

Use ScreenToGif to record your screen, your webcam feed or sketch board drawings.(用 ScreenToGif 录下你的屏幕,你的摄像头视频或画板涂鸦。)
【小沐学C++】C++实现截图截屏功能汇总_第8张图片
【小沐学C++】C++实现截图截屏功能汇总_第9张图片
【小沐学C++】C++实现截图截屏功能汇总_第10张图片

1.6 Google Chrome

对浏览器当前打开的网页进行全屏截图或局部截图,结果会自动保存为一个本地图片文件。
快捷键:
(1)首先Ctrl+Shift+I 打开开发者界面.
(2)然后Ctrl+Shift+P打开命令输入界面
(3)最后输入命令:screenshot

这四个指令分别对应着:
Capture area screenshot:区域截图,截取网页的一个区域。
Capture full size screenshot:全网页截图,截取整个网页。
Capture node screenshot:节点截图,截取网页中的一个元素节点。
Capture screenshot:窗口截图,截取当前浏览器窗口显示的内容。

【小沐学C++】C++实现截图截屏功能汇总_第11张图片

1.7 Microsoft Edge

对浏览器当前打开的网页进行全屏截图或局部截图,结果会存到系统剪切板里。
快捷键:Ctrl+Shift+S

【小沐学C++】C++实现截图截屏功能汇总_第12张图片

1.8 Open Broadcaster Software(OBS)

官网:https://obsproject.com/zh-cn

OBS Studio是目前比较主流的免费开源录屏和直播软件,它提供了丰富的功能特性,可以媲美一些受欢迎的同类商业软件。如果你正在考虑使用低成本方案来录屏或进行直播,那么这将是一个不错的选择。
【小沐学C++】C++实现截图截屏功能汇总_第13张图片
【小沐学C++】C++实现截图截屏功能汇总_第14张图片

1.9 PicPick

官网地址:https://picpick.app/zh/

一个全功能的屏幕截图工具,直观的图像编辑器,颜色选择器,颜色调色板,像素标尺,量角器,瞄准线和白板等等。

【小沐学C++】C++实现截图截屏功能汇总_第15张图片

1.10 Snipaste

官网地址:https://zh.snipaste.com/
微软商店:https://www.microsoft.com/zh-cn/p/snipaste/9p1wxpkb68kx?cid=snipaste&rtc=1&activetab=pivot:overviewtab

Snipaste 提供强大易用的截图、贴图以及图片标注功能,拥有丰富的自定义选项,满足你的各种需求。

截图功能不仅可以自动选取界面元素,还能通过 W A S D 键进行精确的鼠标移动,并特有截图记录回放功能。

贴图功能是将截图或其他图片作为窗口进行置顶,也许你还没接触过这种操作,请不妨尝试一下,善用贴图功能将大大提升你的工作效率!
【小沐学C++】C++实现截图截屏功能汇总_第16张图片

1.11 Camtasia Studio(喀秋莎软件)

Camtasia Studio是TechSmith旗下一款专门录制屏幕动作的工具,它能在任何颜色模式下轻松地记录屏幕动作,包括影像、音效、鼠标移动轨迹、解说声音等等;另外,它还具有即时播放和编辑压缩的功能,可对视频片段进行剪接、添加转场效果。它输出的文件格式很多,包括Flash(SWF/FLV)、AVI、WMV、M4V、CAMV、MOV、RM、GIF动画等多种常见格式,是制作视频演示的绝佳工具。 Camtasia Studio是专业的屏幕录像和编辑的软件套装。软件提供了强大的屏幕录像(Camtasia Recorder)、视频的剪辑和编辑(Camtasia Studio)、视频菜单制作(Camtasia MenuMaker)、视频剧场(Camtasia Theater)和视频播放功能(Camtasia Player)等。使用本套装软件,用户可以方便地进行屏幕操作的录制和配音、视频的剪辑和过场动画、添加说明字幕和水印、制作视频封面和菜单、视频压缩和播放。

腾讯软件中心的下载地址:https://pc.qq.com/detail/15/detail_3275.html
官网地址:https://www.techsmith.com/download/camtasia/
【小沐学C++】C++实现截图截屏功能汇总_第17张图片

1.12 微信

【小沐学C++】C++实现截图截屏功能汇总_第18张图片

1.13 Nvidia GeForce Experience

Nvidia® Geforce® Experience™(以下简称GFE)是一款专为游戏玩家设计的软件,它可以帮助Nvidia显卡用户快速升级驱动、优化游戏设置、截取游戏画面。在出货搭载Nvidia显卡的机台中,该软件随显卡驱动一并安装。
【小沐学C++】C++实现截图截屏功能汇总_第19张图片

  • 分享激动人心的游戏时刻
    现在,您可以使用记录游戏视频,更可以直接分享到微博,燃爆你的社交圈。通过游戏中浮窗功能 NVIDIA ShadowPlay™ 技术,在保障游戏性能的前提下,轻松截取游戏视频和截图,绝不错过任何一秒的精彩画面。GeForce Experience 游戏内浮窗功能可以轻松快速地实现这一点。

  • 使用 NVIDIA ANSEL 截取令人惊叹的游戏图像
    借助功能强大的 NVIDIA Ansel 照相模式,您可轻松截取专业级游戏图像,然后直接分享到微博或 Shot With GeForce 网站。您可在支持此功能的游戏中,选择截取超清、360、HDR 或立体的图像。

  • 通过 SHIELD 畅玩 PC 游戏
    借助 GeForce RTX 显卡的强大功能,您可以将 PC 游戏从卧室串流传输到客厅的电视上。只需利用 NVIDIA GameStream 技术将 PC 与 SHIELD 配对。然后,便可以从客厅在 4K HDR 画质下畅享 60 FPS、5.1 环绕立体声的游戏。

    【小沐学C++】C++实现截图截屏功能汇总_第20张图片
    【小沐学C++】C++实现截图截屏功能汇总_第21张图片
    【小沐学C++】C++实现截图截屏功能汇总_第22张图片

1.14 WPS

很多办公软件也有自带的截图功能,如国产办公软件WPS。在它的工具栏“插入”分页中找到“截屏”菜单。
【小沐学C++】C++实现截图截屏功能汇总_第23张图片

1.15 飞秋

官网地址:http://www.feiq18.com/

“办公室神器”飞秋的截图方法如下:

  1. 打开聊天对话框,找到截图并设置一下截图方式。
  2. 在指定区域用鼠标画框截图,截图是会出现黑色的边框,边框内就是截图内容。
  3. 截图完毕,双击截图区域,截图内容就会自动粘贴到对话框中。

【小沐学C++】C++实现截图截屏功能汇总_第24张图片

2、C++、GDI

2.1 微软官方例子

https://docs.microsoft.com/en-us/windows/win32/gdi/capturing-an-image

int CaptureAnImage(HWND hWnd)
{
    HDC hdcScreen;
    HDC hdcWindow;
    HDC hdcMemDC = NULL;
    HBITMAP hbmScreen = NULL;
    BITMAP bmpScreen;
    DWORD dwBytesWritten = 0;
    DWORD dwSizeofDIB = 0;
    HANDLE hFile = NULL;
    char* lpbitmap = NULL;
    HANDLE hDIB = NULL;
    DWORD dwBmpSize = 0;

    // Retrieve the handle to a display device context for the client 
    // area of the window. 
    hdcScreen = GetDC(NULL);
    hdcWindow = GetDC(hWnd);

    // Create a compatible DC, which is used in a BitBlt from the window DC.
    hdcMemDC = CreateCompatibleDC(hdcWindow);

    if (!hdcMemDC)
    {
        MessageBox(hWnd, L"CreateCompatibleDC has failed", L"Failed", MB_OK);
        goto done;
    }

    // Get the client area for size calculation.
    RECT rcClient;
    GetClientRect(hWnd, &rcClient);

    // This is the best stretch mode.
    SetStretchBltMode(hdcWindow, HALFTONE);

    // The source DC is the entire screen, and the destination DC is the current window (HWND).
    if (!StretchBlt(hdcWindow,
        0, 0,
        rcClient.right, rcClient.bottom,
        hdcScreen,
        0, 0,
        GetSystemMetrics(SM_CXSCREEN),
        GetSystemMetrics(SM_CYSCREEN),
        SRCCOPY))
    {
        MessageBox(hWnd, L"StretchBlt has failed", L"Failed", MB_OK);
        goto done;
    }

    // Create a compatible bitmap from the Window DC.
    hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);

    if (!hbmScreen)
    {
        MessageBox(hWnd, L"CreateCompatibleBitmap Failed", L"Failed", MB_OK);
        goto done;
    }

    // Select the compatible bitmap into the compatible memory DC.
    SelectObject(hdcMemDC, hbmScreen);

    // Bit block transfer into our compatible memory DC.
    if (!BitBlt(hdcMemDC,
        0, 0,
        rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
        hdcWindow,
        0, 0,
        SRCCOPY))
    {
        MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
        goto done;
    }

    // Get the BITMAP from the HBITMAP.
    GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);

    BITMAPFILEHEADER   bmfHeader;
    BITMAPINFOHEADER   bi;

    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bmpScreen.bmWidth;
    bi.biHeight = bmpScreen.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;

    // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
    // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 
    // have greater overhead than HeapAlloc.
    hDIB = GlobalAlloc(GHND, dwBmpSize);
    lpbitmap = (char*)GlobalLock(hDIB);

    // Gets the "bits" from the bitmap, and copies them into a buffer 
    // that's pointed to by lpbitmap.
    GetDIBits(hdcWindow, hbmScreen, 0,
        (UINT)bmpScreen.bmHeight,
        lpbitmap,
        (BITMAPINFO*)&bi, DIB_RGB_COLORS);

    // A file is created, this is where we will save the screen capture.
    hFile = CreateFile(L"captureqwsx.bmp",
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);

    // Add the size of the headers to the size of the bitmap to get the total file size.
    dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    // Offset to where the actual bitmap bits start.
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);

    // Size of the file.
    bmfHeader.bfSize = dwSizeofDIB;

    // bfType must always be BM for Bitmaps.
    bmfHeader.bfType = 0x4D42; // BM.

    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);

    // Unlock and Free the DIB from the heap.
    GlobalUnlock(hDIB);
    GlobalFree(hDIB);

    // Close the handle for the file that was created.
    CloseHandle(hFile);

    // Clean up.
done:
    DeleteObject(hbmScreen);
    DeleteObject(hdcMemDC);
    ReleaseDC(NULL, hdcScreen);
    ReleaseDC(hWnd, hdcWindow);

    return 0;
}

2.2 C++、GDI、CImage

HDC hdcSrc = GetDC(NULL);
int nBitPerPixel = GetDeviceCaps(hdcSrc, BITSPIXEL);
int nWidth = GetDeviceCaps(hdcSrc, HORZRES);
int nHeight = GetDeviceCaps(hdcSrc, VERTRES);
CImage image;
image.Create(nWidth, nHeight, nBitPerPixel);
BitBlt(image.GetDC(), 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY);
ReleaseDC(NULL, hdcSrc);
image.ReleaseDC();
image.Save("d:\\temp.png", Gdiplus::ImageFormatPNG);

2.3 C++、GDI、系统剪切板

#include 

void main()
{
	//获取桌面大小
	HDC hdcScreen = ::GetDC(NULL);
	//HDC hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL);
	int nBitPerPixel = GetDeviceCaps(hdcScreen, BITSPIXEL);
	int nWidth = GetDeviceCaps(hdcScreen, HORZRES); 
	int nHeight = GetDeviceCaps(hdcScreen, VERTRES);
	
    //建立一个屏幕设备环境句柄
	HDC hMemDC;
	HBITMAP hBitmap, hOldBitmap;
    hMemDC = CreateCompatibleDC(hdcScreen);
    hBitmap = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight);
    hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);

    //把屏幕设备描述表拷贝到内存设备描述表中
    BitBlt(hMemDC,0,0,nWidth,nHeight,hdcScreen,0,0,SRCCOPY);

    //打开剪贴板,并将位图拷到剪贴板上
    OpenClipboard(NULL);
    EmptyClipboard();
    SetClipboardData(CF_BITMAP,hBitmap);
    CloseClipboard();
	
	//释放资源
	DeleteDC(hdcScreen);
	DeleteDC(hMemDC);
	DeleteObject(hBitmap);
}

2.4 C++、GDI、GDI+

GDI+
Retrieving the Class Identifier for an Encoder

GDI+ :
Windows GDI+ is a class-based API for C/C++ programmers. It enables applications to use graphics and formatted text on both the video display and the printer. Applications based on the Microsoft Win32 API do not access graphics hardware directly. Instead, GDI+ interacts with device drivers on behalf of applications. GDI+ is also supported by Microsoft Win64.

GetEncoderClsid:
The function GetEncoderClsid in the following example receives the MIME type of an encoder and returns the class identifier (CLSID) of that encoder. The MIME types of the encoders built into Windows GDI+ are as follows:

  • image/bmp
  • image/jpeg
  • image/gif
  • image/tiff
  • image/png
#include 
#include 
#pragma comment(lib,"gdiplus.lib")

class GdiplusWrapper{
public:
	GdiplusWrapper() {
		Gdiplus::GdiplusStartupInput gdiplusStartupInput;
		GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
	}
	
	~GdiplusWrapper(){
		Gdiplus::GdiplusShutdown(gdiplusToken);
	}

	int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
	{
		UINT  num = 0;          // number of image encoders
		UINT  size = 0;         // size of the image encoder array in bytes

		Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;

		Gdiplus::GetImageEncodersSize(&num, &size);
		if(size == 0)
			return -1;  // Failure

		pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
		if(pImageCodecInfo == NULL)
			return -1;  // Failure

		Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);

		for(UINT j = 0; j < num; ++j)
		{
			if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
			{
				*pClsid = pImageCodecInfo[j].Clsid;
				free(pImageCodecInfo);
				return j;  // Success
			}    
		}

		free(pImageCodecInfo);
		return -1;  // Failure
	}

	void SaveImage(HBITMAP hBitmap, const WCHAR* filename, const WCHAR* format) {
		CLSID pngClsid;
		Gdiplus::Bitmap bitmap(hBitmap, NULL);
		GetEncoderClsid(format,&pngClsid);
		bitmap.Save(filename,&pngClsid);
	}

private:
	ULONG_PTR gdiplusToken;
};

void main()
{
	HDC hdcScreen = ::GetDC(NULL);
	//HDC hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL);
	int nBitPerPixel = GetDeviceCaps(hdcScreen, BITSPIXEL);
	int nWidth = GetDeviceCaps(hdcScreen, HORZRES); 
	int nHeight = GetDeviceCaps(hdcScreen, VERTRES);
    
    //建立一个屏幕设备环境句柄
	HDC hMemDC;
	HBITMAP hBitmap, hOldBitmap;
    hMemDC = CreateCompatibleDC(hdcScreen);
    hBitmap = CreateCompatibleBitmap(hdcScreen, nWidth, nHeight);
    hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);

    //把屏幕设备描述表拷贝到内存设备描述表中
    BitBlt(hMemDC,0,0,nWidth,nHeight,hdcScreen,0,0,SRCCOPY);

	// Initialize GDI+.
	GdiplusWrapper gdiplus;
	gdiplus.SaveImage(hBitmap, L"d:\\temp.jpg",L"image/jpeg");
	
	//释放资源
	DeleteDC(hdcScreen);
	DeleteDC(hMemDC);
	DeleteObject(hBitmap);
}

2.5 C++、GDI、MFC


void CTestMFCDlg::OnBnClickedOk()
{
	// 获取屏幕参数
	int nScreenCX = ::GetSystemMetrics(SM_CXSCREEN);
	int nSCreenCY = ::GetSystemMetrics(SM_CYSCREEN);
	
	// 创建兼容DC
	CWindowDC DesktopDC(GetDesktopWindow());
	CDC cdc;
	cdc.CreateCompatibleDC(&DesktopDC);
	
	// 获取桌面图像
	CBitmap bitmap;
	bitmap.CreateCompatibleBitmap(&DesktopDC, nScreenCX, nSCreenCY);
	cdc.SelectObject(bitmap);
	cdc.BitBlt(0,0, nScreenCX, nSCreenCY,&DesktopDC,0,0,SRCCOPY);

	//保存图片文件
	CImage image;
	image.Attach(bitmap);
	image.Save("d:\\temp.jpg");
}

2.6 C++、GDI、PrintWindow

PrintWindow function (winuser.h)

The PrintWindow function copies a visual window into the specified device context (DC), typically a printer DC.

只要想截的窗口不是最小化,无论在屏幕外还是只显示一半还是被覆盖,都可以成功截取。

int GetWindowBitmapToClipboard()
{
	//根据窗口类名查找窗口句柄
	RECT rc;
	HWND hwnd = FindWindow(TEXT("Notepad"), NULL); 
	if (hwnd == NULL)
	{
		std::cout << "找不到记事本窗口!" << std::endl;
		return 0;
	}
	GetClientRect(hwnd, &rc);

	//创建指定窗口的上下文
	int w = rc.right - rc.left;
	int h = rc.bottom - rc.top;
	HDC hdcScreen = GetDC(NULL);
	HDC hdc = CreateCompatibleDC(hdcScreen);
	HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, w, h);
	SelectObject(hdc, hbmp);

	//复制指定窗口的画面到上下文句柄里
	PrintWindow(hwnd, hdc, 0);

	//复制到粘贴板
	OpenClipboard(NULL);
	EmptyClipboard();
	SetClipboardData(CF_BITMAP, hbmp);
	CloseClipboard();

	//释放资源
	DeleteDC(hdc);
	DeleteObject(hbmp);
	ReleaseDC(NULL, hdcScreen);

	std::cout << "已复制到粘贴板!" << std::endl;
	return 0;
}

【小沐学C++】C++实现截图截屏功能汇总_第25张图片
【小沐学C++】C++实现截图截屏功能汇总_第26张图片

3、C++、OpenGL

void CaptureOpenGLWindow(const char* savePath, int w, int h)
{
	GLubyte* pPixelData; 
	GLint    PixelDataLength;  

	// 分配内存和打开文件
	pPixelData = (GLubyte*)malloc(w*h*3);
	if (pPixelData == 0)
		return;
	
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 
	glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pPixelData);
	stbi_write_png(savePath, w, h, 3, pPixelData, 0);
	free(pPixelData);

	int iw = w, ih = h, n = 3;
	stbi_set_flip_vertically_on_load(true);
	unsigned char *idata = stbi_load(savePath, &iw, &ih, &n, 0);
	stbi_write_png(savePath, w, h, 3, idata, 0);
	stbi_image_free(idata);

}

4、C++、OpenCV

#pragma once
#include 
#include 

using nammespace cv;

BITMAPINFOHEADER createBitmapHeader(int width, int height)
{
   BITMAPINFOHEADER  bi;

     // create a bitmap
     bi.biSize = sizeof(BITMAPINFOHEADER);
     bi.biWidth = width;
     bi.biHeight = -height;  //this is the line that makes it draw upside down or not
     bi.biPlanes = 1;
     bi.biBitCount = 32;
     bi.biCompression = BI_RGB;
     bi.biSizeImage = 0;
     bi.biXPelsPerMeter = 0;
     bi.biYPelsPerMeter = 0;
     bi.biClrUsed = 0;
     bi.biClrImportant = 0;

     return bi;
}

Mat captureScreenMat(HWND hwnd)
{
     Mat src;

     // get handles to a device context (DC)
     HDC hwindowDC = GetDC(hwnd);
     HDC hwindowCompatibleDC = CreateCompatibleDC(hwindowDC);
     SetStretchBltMode(hwindowCompatibleDC, COLORONCOLOR);

     // define scale, height and width
     int screenx = GetSystemMetrics(SM_XVIRTUALSCREEN);
     int screeny = GetSystemMetrics(SM_YVIRTUALSCREEN);
     int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
     int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);

     // create mat object
     src.create(height, width, CV_8UC4);

     // create a bitmap
     HBITMAP hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
     BITMAPINFOHEADER bi = createBitmapHeader(width, height);

     // use the previously created device context with the bitmap
     SelectObject(hwindowCompatibleDC, hbwindow);

     // copy from the window device context to the bitmap device context
     StretchBlt(hwindowCompatibleDC, 0, 0, width, height, hwindowDC, screenx, screeny, width, height, SRCCOPY);  //change SRCCOPY to NOTSRCCOPY for wacky colors !
     GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, src.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);            //copy from hwindowCompatibleDC to hbwindow

     // avoid memory leak
     DeleteObject(hbwindow);
     DeleteDC(hwindowCompatibleDC);
     ReleaseDC(hwnd, hwindowDC);

     return src;
 }
 int main()
{
      // capture image
      HWND hwnd = GetDesktopWindow();
      Mat src = captureScreenMat(hwnd);

      // save img
      cv::imwrite("Screenshot.png", src);

      return 0;
}

5、C++、QT

QDesktopWidget *desk = QApplication::desktop();
QScreen * screen = QGuiApplication::primaryScreen();
QPixmap p = screen->grabWindow(desk->winId());
QImage image = p.toImage();
image.save("d:\\temp.png");

6、C++、DirectX 9

D3DXSaveSurfaceToFile 函数

HRESULT D3DXSaveSurfaceToFile(
  _In_       LPCTSTR              pDestFile,
  _In_       D3DXIMAGE_FILEFORMAT DestFormat,
  _In_       LPDIRECT3DSURFACE9   pSrcSurface,
  _In_ const PALETTEENTRY         *pSrcPalette,
  _In_ const RECT                 *pSrcRect
);
typedef enum D3DXIMAGE_FILEFORMAT { 
  D3DXIFF_BMP          = 0,
  D3DXIFF_JPG          = 1,
  D3DXIFF_TGA          = 2,
  D3DXIFF_PNG          = 3,
  D3DXIFF_DDS          = 4,
  D3DXIFF_PPM          = 5,
  D3DXIFF_DIB          = 6,
  D3DXIFF_HDR          = 7,
  D3DXIFF_PFM          = 8,
  D3DXIFF_FORCE_DWORD  = 0x7fffffff
} D3DXIMAGE_FILEFORMAT, *LPD3DXIMAGE_FILEFORMAT;
#include "stdafx.h"
#include 
#include 

#pragma comment( lib, "d3d9.lib" )
#pragma comment( lib, "d3dx9.lib" )

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize( NULL );

    LPDIRECT3D9 pD3D = NULL;
    D3DDISPLAYMODE ddm;
    D3DPRESENT_PARAMETERS d3dpp;
    IDirect3DDevice9 * g_pd3dDevice;
    IDirect3DSurface9 * pSurface;
    ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
    ZeroMemory( &d3dpp, sizeof(d3dpp) );

    pD3D=Direct3DCreate9(D3D_SDK_VERSION);
    pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm);
    d3dpp.Windowed=TRUE;
    d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    d3dpp.BackBufferFormat=ddm.Format;
    d3dpp.BackBufferHeight=ddm.Height;
    d3dpp.BackBufferWidth=ddm.Width;
    d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
    d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow=GetDesktopWindow();
    d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
    d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;

    HRESULT hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT
                                    ,D3DDEVTYPE_HAL
                                    ,GetDesktopWindow()
                                    ,D3DCREATE_SOFTWARE_VERTEXPROCESSING
                                    ,&d3dpp
                                    ,&g_pd3dDevice);

    hr = g_pd3dDevice->CreateOffscreenPlainSurface(ddm.Width
            , ddm.Height
            , D3DFMT_A8R8G8B8
            , D3DPOOL_SCRATCH
            , &pSurface
            , NULL);

    hr = g_pd3dDevice->GetFrontBufferData(0
                                          , pSurface);

    LPD3DXBUFFER bufferedImage = NULL;
    hr = D3DXSaveSurfaceToFileInMemory( &bufferedImage
                                        , D3DXIFF_PNG
                                        ,pSurface
                                        ,NULL
                                        ,NULL);


    hr = D3DXSaveSurfaceToFile("d://temp.png"
                               , D3DXIFF_PNG
                               ,pSurface
                               ,NULL
                               ,NULL);

    bufferedImage->Release();
    pSurface->Release();
    g_pd3dDevice->Release ();
    pD3D->Release ();

    CoUninitialize();
    return 0;
}

7、C++、DXGI

DXGI
DXGI desktop duplication sample

Microsoft DirectX 图形基础设施 (DXGI) 负责枚举图形适配器、枚举显示模式、选择缓冲区格式、在进程 (之间共享资源(例如,在应用程序和 桌面窗口管理器 (DWM) ) 之间共享资源)以及向窗口或监视器显示呈现的帧以用于显示。

DXGI 由 Direct3D 10、Direct3D 11 和 Direct3D 12 使用。

尽管大多数图形编程都是使用 Direct3D 完成,但可以使用 DXGI 向窗口、监视器或其他图形组件呈现帧,以便最终组合和显示。 还可使用 DXGI 读取监视器上的内容。

To develop DXGI, you need these headers:

dxgi.h
dxgi1_2.h
dxgi1_3.h
dxgi1_4.h
dxgi1_5.h
dxgi1_6.h
dxgicommon.h
dxgidebug.h
dxgiformat.h

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进。o_O???
如果您需要相关功能的代码定制化开发,可以留言私聊。(✿◡‿◡)
感谢各位童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

朝看花开满树红,暮看花落树还空。若将花比人间事,花与人间事一同。

你可能感兴趣的:(C/C++,c++,win32开发,截图,截屏,录屏)