绘制光标多个显示(仅绘制文本图标)GDI

问题描述 投票:-1回答:2

我在多个显示环境中选择显示并生成捕获的程序。

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

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

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

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

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 = CreateDC(TEXT("\\.\Display1"), NULL, NULL, NULL);

它绘制光标..

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

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

解决了:

现在,我改变了算法。

CreateDC(L“Display”,NULL,NULL,NULL)为所有监视器创建DC,那么你的问题是什么? - user2120666 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)

谢谢你的评论!

winapi screenshot gdi mousecapture
2个回答
0
投票

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

来自documentation

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

所以你只捕获主要显示。


0
投票

以下MSDN获得EnumDisplayMonitor可能会解决您的问题。

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

© www.soinside.com 2019 - 2024. All rights reserved.