Gdi+ 截屏多台显示器
Gdi+ Take Screenshot multiple monitors
我有一个在 windows 平台上用 gdi plus 和 c++ 截屏的例程,它只用一个显示器就可以完美地工作,但是当我 运行 它在一台有 2 个 VM 的机器上时监控它只拍一张图片。
这就是我正在做的事情:
#include <stdlib.h>
#include <windows.h>
#include <iostream>
#include <GdiPlus.h>
#include <wingdi.h>
#include <fstream>
#include <unistd.h>
#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "ws2_32.lib")
using namespace std;
// Se encarga de configurar, por asi decirlo, el formato
// de la imagen, este metodo es llamado en gdiscreen al
// momento de guardar la imagen.
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
using namespace Gdiplus;
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1; // Failure
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 0;
}
// Este es el metodo que tomo la captura.
// c es solo una variable que utilice para probar el
// metodo en un loop, la puede quitar y remplazar c
// por el log_sec_num.
inline void take_screenshot(const std::string & filename)
{
using namespace Gdiplus;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
{
HDC scrdc, memdc;
HBITMAP membit;
scrdc = ::GetDC(0);
int Height = GetSystemMetrics(SM_CYSCREEN);
int Width = GetSystemMetrics(SM_CXSCREEN);
memdc = CreateCompatibleDC(scrdc);
membit = CreateCompatibleBitmap(scrdc, Width, Height);
HBITMAP hOldBitmap =(HBITMAP) SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
Gdiplus::Bitmap bitmap(membit, NULL);
CLSID clsid;
const char* name = filename.c_str();
const size_t cSize = strlen(name)+1;
wchar_t* wc = new wchar_t[cSize];
mbstowcs (wc, name, cSize);
GetEncoderClsid(L"image/png", &clsid);
bitmap.Save(wc, &clsid,NULL);
SelectObject(memdc, hOldBitmap);
DeleteObject(memdc);
DeleteObject(membit);
::ReleaseDC(0,scrdc);
}
GdiplusShutdown(gdiplusToken);
}
int main ()
{
const std::string & filename = "C:\Screenshot.png";
take_screenshot(filename);
}
如果尝试获取整个屏幕,但我最终只有图片。谁能看出我的错误在哪里??
可能的解1
使用 GetDC(0)
您将仅获得主监视器的 HDC。来自 CreateDC MSDN
If there are multiple monitors on the system, calling
CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL)
will create a DC covering all
the monitors.
它可能会起作用,但尚未经过测试。
可能的解法2
分别捕获每个桌面,然后合并它们。要获得所有显示,请使用 EnumDisplayMonitors. Some working example is in some codeproject's article.
int Height = GetSystemMetrics(SM_CYSCREEN);
引自 MSDN 文档:"The height of the screen of the primary display monitor"。您完全 得到了您想要的,主显示器是您的显示器之一。第一个.
改用SM_CYVIRTUALSCREEN
。 X 也一样。
我有一个在 windows 平台上用 gdi plus 和 c++ 截屏的例程,它只用一个显示器就可以完美地工作,但是当我 运行 它在一台有 2 个 VM 的机器上时监控它只拍一张图片。
这就是我正在做的事情:
#include <stdlib.h>
#include <windows.h>
#include <iostream>
#include <GdiPlus.h>
#include <wingdi.h>
#include <fstream>
#include <unistd.h>
#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "ws2_32.lib")
using namespace std;
// Se encarga de configurar, por asi decirlo, el formato
// de la imagen, este metodo es llamado en gdiscreen al
// momento de guardar la imagen.
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
using namespace Gdiplus;
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1; // Failure
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 0;
}
// Este es el metodo que tomo la captura.
// c es solo una variable que utilice para probar el
// metodo en un loop, la puede quitar y remplazar c
// por el log_sec_num.
inline void take_screenshot(const std::string & filename)
{
using namespace Gdiplus;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
{
HDC scrdc, memdc;
HBITMAP membit;
scrdc = ::GetDC(0);
int Height = GetSystemMetrics(SM_CYSCREEN);
int Width = GetSystemMetrics(SM_CXSCREEN);
memdc = CreateCompatibleDC(scrdc);
membit = CreateCompatibleBitmap(scrdc, Width, Height);
HBITMAP hOldBitmap =(HBITMAP) SelectObject(memdc, membit);
BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
Gdiplus::Bitmap bitmap(membit, NULL);
CLSID clsid;
const char* name = filename.c_str();
const size_t cSize = strlen(name)+1;
wchar_t* wc = new wchar_t[cSize];
mbstowcs (wc, name, cSize);
GetEncoderClsid(L"image/png", &clsid);
bitmap.Save(wc, &clsid,NULL);
SelectObject(memdc, hOldBitmap);
DeleteObject(memdc);
DeleteObject(membit);
::ReleaseDC(0,scrdc);
}
GdiplusShutdown(gdiplusToken);
}
int main ()
{
const std::string & filename = "C:\Screenshot.png";
take_screenshot(filename);
}
如果尝试获取整个屏幕,但我最终只有图片。谁能看出我的错误在哪里??
可能的解1
使用 GetDC(0)
您将仅获得主监视器的 HDC。来自 CreateDC MSDN
If there are multiple monitors on the system, calling
CreateDC(TEXT("DISPLAY"),NULL,NULL,NULL)
will create a DC covering all the monitors.
它可能会起作用,但尚未经过测试。
可能的解法2
分别捕获每个桌面,然后合并它们。要获得所有显示,请使用 EnumDisplayMonitors. Some working example is in some codeproject's article.
int Height = GetSystemMetrics(SM_CYSCREEN);
引自 MSDN 文档:"The height of the screen of the primary display monitor"。您完全 得到了您想要的,主显示器是您的显示器之一。第一个.
改用SM_CYVIRTUALSCREEN
。 X 也一样。