Включить курсор мыши в захват экрана

#c #c #screenshot #screen-capture

#c #c #скриншот #захват экрана

Вопрос:

Я использую CreateDC / BitBlt / GetDIBits и т.д. для захвата экрана, но курсор не захвачен. Есть ли какой-нибудь простой аргумент или что-то еще, чтобы включить его?

Комментарии:

1. Одним словом, нет. Курсор рисуется ОС и, как таковой, на самом деле он не является частью изображения, хранящегося в HBITMAP, выбранного в HDC. Он рисуется поверх (копии) этого изображения при выводе на экран. Способ справиться с этим — получить положение мыши при выполнении захвата. Затем вы рисуете копию изображения курсора в этой позиции. Обратите внимание, что курсор также не захватывается при нажатии кнопки PrtSc. Программное обеспечение InstantDemo (приложение для записи экрана) использует подход, о котором я упоминал, для отображения курсора мыши.

2. Как мне получить изображение курсора?

3. Погуглив «указатель курсора», а затем загрузив тот, который вам нравится. Там всего 5 миллионов просмотров или около того — я бы предположил, что вы найдете тот, который вам нравится.

4. Но мне нужно, чтобы курсор был таким же, как на экране, поскольку он будет записан в программном обеспечении с пользовательскими курсорами.

5. Забавно, что вы должны это сказать, я рассмотрел именно такую возможность вскоре после публикации моего ответа. В этом случае вы можете получить курсор с помощью функции GetCursor, хотя, я считаю, это не будет работать в другом процессе или потоке. В этом случае я подозреваю, что вам следует использовать GetCursorInfo. msdn.microsoft.com/en-us/library/windows/desktop / … кажется, это хорошее место для начала. Как бы то ни было, они очень похожи на HICON, хотя и с дополнительными переменными для определения положения точки доступа. (т.е. вверху слева для «обычного» курсора, в центре по центру для перекрестия)

Ответ №1:

 #include <Windows.h>
#include <stdio.h>
#include <assert.h>

void scrshot() {
    HWND hwnd = GetDesktopWindow();
    HDC hdc = GetWindowDC(hwnd);
    HDC hdcMem = CreateCompatibleDC(hdc);
    int cx = GetDeviceCaps(hdc, HORZRES);
    int cy = GetDeviceCaps(hdc, VERTRES);
    HBITMAP hbitmap(NULL);
    hbitmap = CreateCompatibleBitmap(hdc, cx, cy);
    SelectObject(hdcMem, hbitmap);
    BitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY);
    CURSORINFO cursor = { sizeof(cursor) };
    GetCursorInfo(amp;cursor);
    if (cursor.flags == CURSOR_SHOWING) {
        RECT rect;
        GetWindowRect(hwnd, amp;rect);
        ICONINFO info = { sizeof(info) };
        GetIconInfo(cursor.hCursor, amp;info);
        const int x = cursor.ptScreenPos.x - rect.left - rect.left - info.xHotspot;
        const int y = cursor.ptScreenPos.y - rect.top - rect.top - info.yHotspot;
        BITMAP bmpCursor = { 0 };
        GetObject(info.hbmColor, sizeof(bmpCursor), amp;bmpCursor);
        DrawIconEx(hdcMem, x, y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight,
            0, NULL, DI_NORMAL);
    }
}

int main(){
    scrshot();
    return 0;
}
  

Ответ №2:

В дополнение к обсуждению, которое произошло в комментариях, у меня была возможность продолжить изучение вопроса. В результате я придумал следующий код, который захватит HBITMAP текущего курсора и выведет его на экран.

Поскольку курсор на самом деле является HICON, он поставляется с маской. Первоначально я просто сделал простой BitBlt — однако я получил черный квадрат размером 32×32 с курсором в верхнем левом углу 1/4 или около того.

Затем я исследовал с помощью MaskBlt. В зависимости от того, где находится курсор при запуске приложения, я получаю либо курсор ожидания, либо курсор изменения размера NS, либо стандартный указатель. Я думаю, вы могли бы запустить таймер и добавить обработчик WM_TIMER для запуска пару раз в секунду, чтобы получать обновление курсора в режиме реального времени, поскольку он использовался в других окнах системы. Казалось, что это простое любопытство, чтобы сделать что-то подобное, поэтому я не стал беспокоиться.

РЕДАКТИРОВАТЬ: я действительно запустил таймер в WM_INITDIALOG и обработал его в WM_TIMER. Теперь вы можете видеть, что изображение обновляется 10 раз в секунду. По какой-то причине курсор двутавровой балки, похоже, вообще не отображается — я думаю, это случай для дальнейшего расследования по мере необходимости.

Вот полный список (за исключением resource.rc и resource.h — просто создайте диалоговое приложение и убедитесь, что идентификатор ресурса диалогового окна используется внутри Main в вызове диалогового окна)

 #include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"

HINSTANCE hInst;

HBITMAP getCursorHBITMAP(HBITMAP *maskBmp)
{
    CURSORINFO pci;
    ICONINFO iconinfo;
    HBITMAP resu<

    pci.cbSize = sizeof(pci);
    GetCursorInfo(amp;pci);

    if (GetIconInfo(pci.hCursor,amp;iconinfo))
    {
        result = iconinfo.hbmColor;
        if (maskBmp)
            *maskBmp = iconinfo.hbmMask;
    }
    else
        result = NULL;

    return resu<
}

BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_INITDIALOG:
        {
            SetTimer(hwndDlg, 1, 100, NULL);
        }
        return TRUE;

        case WM_TIMER:
        {
            InvalidateRect(hwndDlg, NULL, true);
        }
        return 0;

        case WM_ERASEBKGND:
        {
            HDC hdc = (HDC)wParam;
            RECT mRect;
            GetClientRect(hwndDlg, amp;mRect);
            FillRect(hdc, amp;mRect, (HBRUSH)GetStockObject(GRAY_BRUSH));
        }
        return 1;

        case WM_PAINT:
        {
            HBITMAP oldBm, cursorBmp, maskBmp;

            cursorBmp = getCursorHBITMAP(amp;maskBmp);
            if (cursorBmp)
            {
                HDC hdc;
                PAINTSTRUCT ps;
                HDC memDC;
                BITMAP bm;

                hdc = BeginPaint(hwndDlg, amp;ps);
                memDC = CreateCompatibleDC(hdc);
                oldBm = (HBITMAP) SelectObject(memDC, cursorBmp);

                GetObject(cursorBmp, sizeof(bm), amp;bm);
    //            printf("Cursor size: %d x %dn", bm.bmWidth, bm.bmHeight);

    //            BitBlt(hdc, 10,10, 32,32, memDC, 0,0, SRCCOPY);
                MaskBlt(hdc, 10,10, bm.bmWidth, bm.bmHeight, memDC, 0,0, maskBmp, 0,0, MAKEROP4(SRCPAINT,SRCCOPY) );


                SelectObject(memDC, oldBm);
                DeleteDC(memDC);
                EndPaint(hwndDlg, amp;ps);
            }
        }
        return 0;

        case WM_CLOSE:
        {
            EndDialog(hwndDlg, 0);
        }
        return TRUE;

        case WM_COMMAND:
        {
            switch(LOWORD(wParam))
            {
            }
        }
        return TRUE;
    }
    return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst=hInstance;
    InitCommonControls();
    return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
}