0

我在多个显示环境中选择显示器并制作捕获的程序。

并尝试通过在多个显示器中选择 dc 来绘制光标。

我用 bitblt 位图图像绘制光标,效果很好。

HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);

但是当我从 createDC 多显示值中选择时,

DISPLAY_DEVICEW info = { 0 };
info.cb = sizeof(DISPLAY_DEVICEW);
EnumDisplayDevicesW(NULL, 0, &info, EDD_GET_DEVICE_INTERFACE_NAME); 
HDCC = CreateDC(info.DeviceName, NULL, NULL, NULL);

我正在努力获得其他显示图像。但是没有绘图光标。(其他形式的光标不绘制,只绘制文本光标)

这是我的代码。

const int d_count = GetSystemMetrics(SM_CMONITORS);  //I have 3 display and count is 3.
HDC hCaptureDC;
HDC HDCC;
HBITMAP hBitmap;
HGDIOBJ hOld;
BYTE *src;


bool GetMouse() {
     CURSORINFO cursor = { sizeof(cursor) };
     ::GetCursorInfo(&cursor);

     ICONINFOEXW info = { sizeof(info) };
     ::GetIconInfoExW(cursor.hCursor, &info);

     BITMAP bmpCursor = { 0 };
     GetObject(info.hbmColor, sizeof(bmpCursor), &bmpCursor);

     POINT point;
     GetCursorPos(&point);

     bool res = DrawIconEx(hCaptureDC, point.x, point.y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight, 0, NULL, DI_NORMAL);
     return res;
}

void screencap(){
    BITMAPINFO MyBMInfo;
    BITMAPINFOHEADER bmpInfoHeader;
    HWND m_hWndCopy= GetDesktopWindow();
    GetClientRect(m_hWndCopy, &ImageRect);  
    const int nWidth = ImageRect.right - ImageRect.left; 
    const int nHeight = ImageRect.bottom - ImageRect.top;

    MyBMInfo = { 0 };
    MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

    bmpInfoHeader = { sizeof(BITMAPINFOHEADER) };
    bmpInfoHeader.biWidth = nWidth;
    bmpInfoHeader.biHeight = nHeight;
    bmpInfoHeader.biPlanes = 1;
    bmpInfoHeader.biBitCount = 32;

    b_size = ((nWidth * bmpInfoHeader.biBitCount + 31) / 32) * 4 * nHeight;

     //HDCC = CreateDC((L"Display"), NULL, NULL, NULL);   //It's good.
    DISPLAY_DEVICEW info = { 0 };
    info.cb = sizeof(DISPLAY_DEVICEW);
    EnumDisplayDevicesW(NULL, 0, &info, EDD_GET_DEVICE_INTERFACE_NAME); 
    HDCC = CreateDC(info.DeviceName, NULL, NULL, NULL);   // It draws only text cursor.

    hCaptureDC = CreateCompatibleDC(HDCC);
    hBitmap = CreateCompatibleBitmap(HDCC, nWidth, nHeight);
    hOld = SelectObject(hCaptureDC, hBitmap);

    BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, HDCC, 0, 0, SRCCOPY);

    GetMouse();

    SelectObject(hCaptureDC, hOld);

    src = (BYTE*)malloc(b_size);
    if (GetDIBits(hCaptureDC, hBitmap, 0, nHeight, src, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)) {
        if (RGBSaveBMP(src) == true) 
        free(src);
    }  
}

我正在使用 Windows 10。

我该如何解决?

任何链接,想法,谢谢。

添加

它不绘制光标....(文本光标除外。)

HDCC = CreateDC(TEXT("\\\\.\\Display1"), NULL, NULL, NULL);

HDCC = 创建DC(文本(

它绘制光标..

HDCC = CreateDC(TEXT("Display"), NULL, NULL, NULL);

HDCC = 创建DC(文本(

解决了:

现在,我改变了我的算法。

CreateDC(L"Display", NULL, NULL, NULL) 为所有显示器创建 DC,那么您的问题是什么?– 用户 2120666 4 月 22 日 15:37

这条评论很有帮助,但并不友好。(或者我很愚蠢。):(

HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);

HDCC 拥有“所有虚拟屏幕”DC。

当我选择了我需要的显示器时,相应地选择并使用了要在虚拟屏幕上捕获的区域。

HDC hCaptureDC = CreateCompatibleDC(HDCC);  
HBITMAP hBitmap = CreateCompatibleBitmap(HDCC, nWidth, nHeight);
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
DEVMODE dev;

std::string str = "\\\\.\\Display" + std::to_string(select);
std::wstring temp;
temp.assign(str.begin(), str.end());

EnumDisplaySettingsW(temp.c_str(), ENUM_CURRENT_SETTINGS, &dev);
printf("Display%d : (%d * %d) (%d, %d)\n", select, dev.dmPelsWidth, dev.dmPelsHeight, dev.dmPosition.x, dev.dmPosition.y);

nWidth = dev.dmPelsWidth;
nHeight = dev.dmPelsHeight;
nposx = dev.dmPosition.x;
nposy = dev.dmPosition.y;

hOld = SelectObject(hCaptureDC, hBitmap);
BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, HDCC, nposx, nposy, SRCCOPY);
int colorcheck = GetSystemMetrics(SM_SAMEDISPLAYFORMAT);

CURSORINFO cursor = { sizeof(cursor) };
bool check = ::GetCursorInfo(&cursor);
bool check2 = ::GetCursorInfo(&cursor);
int count = ShowCursor(TRUE);

info = { sizeof(info) };
::GetIconInfoExW(cursor.hCursor, &info);

GetCursorPos(&point);

if (point.x > nWidth) {
    point.x = point.x - nWidth;
}
else if (point.x < 0) {
    point.x = nWidth + point.x;
}
if (point.y > nHeight) {
    point.y = point.y - nHeight;
}
else if (point.y < 0) {
    point.y = nHeight + point.y;
}
cursor.ptScreenPos.x = point.x;
cursor.ptScreenPos.y = point.y;

bool res = ::DrawIconEx(hCaptureDC, point.x, point.y, cursor.hCursor, 0, 0, 0, NULL, DI_NORMAL);


BYTE* src = (BYTE*)malloc(b_size);
GetDIBits(hCaptureDC, hBitmap, 0, nHeight, src, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)

感谢您的评论!

4

2 回答 2

0

你的电话GetClientRect(m_hWndCopy, &ImageRect);是错误的。

文档

GetWindowRect 或 GetClientRect 返回的桌面窗口的矩形始终等于主监视器的矩形,以便与现有应用程序兼容。

因此,您只捕获主显示器。

于 2019-04-23T07:19:24.003 回答
0

按照MSDN获取EnumDisplayMonitor可能会解决您的问题。

使用 EnumDisplayMonitors 获取设备名称并将其传递给 CreateDC。

于 2019-04-23T06:41:42.090 回答