#include "GdiCapturer.h" #include namespace avrecorder { namespace video { bool GdiCapturer::open(const CaptureTarget& target, int width, int height) { #ifdef PLATFORM_WINDOWS close(); if (target.type != CaptureTargetType::Window) return false; m_hwnd = target.hwnd; m_width = width; m_height = height; _srcHdc = GetWindowDC(m_hwnd); _dstHdc = CreateCompatibleDC(_srcHdc); _bitmap = CreateCompatibleBitmap(_srcHdc, width, height); SelectObject(_dstHdc, _bitmap); _bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); _bitmapInfo.bmiHeader.biPlanes = 1; _bitmapInfo.bmiHeader.biBitCount = 24; _bitmapInfo.bmiHeader.biWidth = width; _bitmapInfo.bmiHeader.biHeight = height; _bitmapInfo.bmiHeader.biCompression = BI_RGB; _bitmapInfo.bmiHeader.biSizeImage = width * height; _frame = Frame::Alloc(AV_PIX_FMT_BGR24, width, height); return true; #else return false; #endif } void GdiCapturer::close() { #ifdef PLATFORM_WINDOWS if (_frame) { av_frame_free(&_frame); _frame = nullptr; } if (_dstHdc) { DeleteObject(_dstHdc); _dstHdc = nullptr; } if (_bitmap) { DeleteObject(_bitmap); _bitmap = nullptr; } // _srcHdc 由系统管理,无需手动释放 #endif } AVFrame* GdiCapturer::getFrame() { #ifdef PLATFORM_WINDOWS if (!_srcHdc || !_dstHdc || !_frame) return nullptr; BitBlt(_dstHdc, 0, 0, m_width, m_height, _srcHdc, 0, 0, SRCCOPY); auto linesize = _frame->linesize[0]; for (int row = 0; row < m_height; ++row) { GetDIBits(_dstHdc, _bitmap, m_height - 1 - row, 1, _frame->data[0] + row * linesize, &_bitmapInfo, DIB_RGB_COLORS); } if (m_drawCursor) { drawCursor(_dstHdc); } return _frame; #else return nullptr; #endif } void GdiCapturer::drawCursor(HDC hdc) { CURSORINFO ci = {sizeof(CURSORINFO)}; if (!GetCursorInfo(&ci)) return; if (ci.flags != CURSOR_SHOWING) return; RECT rect; GetWindowRect(m_hwnd, &rect); POINT pos = {ci.ptScreenPos.x - rect.left, ci.ptScreenPos.y - rect.top}; DrawIconEx(hdc, pos.x, pos.y, ci.hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT); } } // namespace video } // namespace avrecorder